706 lines
No EOL
31 KiB
JavaScript
706 lines
No EOL
31 KiB
JavaScript
/**
|
|
* Zoho CRM Admin JavaScript
|
|
*
|
|
* @package HVACCommunityEvents
|
|
*/
|
|
jQuery(document).ready(function ($) {
|
|
|
|
// =====================================================
|
|
// Password visibility toggle
|
|
// =====================================================
|
|
$('#toggle-secret').on('click', function () {
|
|
var passwordField = $('#zoho_client_secret');
|
|
var toggleBtn = $(this);
|
|
|
|
if (passwordField.attr('type') === 'password') {
|
|
passwordField.attr('type', 'text');
|
|
toggleBtn.text('Hide');
|
|
} else {
|
|
passwordField.attr('type', 'password');
|
|
toggleBtn.text('Show');
|
|
}
|
|
});
|
|
|
|
// =====================================================
|
|
// Copy redirect URI to clipboard
|
|
// =====================================================
|
|
$('#copy-redirect-uri').on('click', function () {
|
|
var redirectUri = hvacZoho.redirectUri || '';
|
|
if (!redirectUri) {
|
|
alert('Redirect URI not available');
|
|
return;
|
|
}
|
|
|
|
navigator.clipboard.writeText(redirectUri).then(function () {
|
|
$('#copy-redirect-uri').text('Copied!').prop('disabled', true);
|
|
setTimeout(function () {
|
|
$('#copy-redirect-uri').text('Copy').prop('disabled', false);
|
|
}, 2000);
|
|
}).catch(function () {
|
|
// Fallback for older browsers
|
|
var tempInput = $('<input>');
|
|
$('body').append(tempInput);
|
|
tempInput.val(redirectUri).select();
|
|
document.execCommand('copy');
|
|
tempInput.remove();
|
|
$('#copy-redirect-uri').text('Copied!').prop('disabled', true);
|
|
setTimeout(function () {
|
|
$('#copy-redirect-uri').text('Copy').prop('disabled', false);
|
|
}, 2000);
|
|
});
|
|
});
|
|
|
|
// =====================================================
|
|
// Flush rewrite rules
|
|
// =====================================================
|
|
$('#flush-rewrite-rules').on('click', function () {
|
|
var button = $(this);
|
|
button.prop('disabled', true).text('Flushing...');
|
|
|
|
$.post(hvacZoho.ajaxUrl, {
|
|
action: 'hvac_zoho_flush_rewrite_rules'
|
|
}, function (response) {
|
|
if (response.success) {
|
|
button.text('Flushed!').css('color', '#46b450');
|
|
setTimeout(function () {
|
|
location.reload();
|
|
}, 1000);
|
|
} else {
|
|
button.text('Error').css('color', '#dc3232');
|
|
setTimeout(function () {
|
|
button.prop('disabled', false).text('Flush Rules').css('color', '');
|
|
}, 2000);
|
|
}
|
|
});
|
|
});
|
|
|
|
// =====================================================
|
|
// Credentials form submission
|
|
// =====================================================
|
|
// =====================================================
|
|
// Credentials form submission
|
|
// =====================================================
|
|
$('#zoho-credentials-form').on('submit', function (e) {
|
|
e.preventDefault();
|
|
|
|
var formData = {
|
|
action: 'hvac_zoho_save_credentials',
|
|
zoho_client_id: $('#zoho_client_id').val(),
|
|
zoho_client_secret: $('#zoho_client_secret').val(),
|
|
nonce: $('input[name="hvac_zoho_nonce"]').val()
|
|
};
|
|
|
|
var $saveBtn = $('#save-credentials');
|
|
$saveBtn.prop('disabled', true).text('Saving...');
|
|
|
|
// Clear any previous messages
|
|
$('.notice').remove();
|
|
|
|
$.ajax({
|
|
url: hvacZoho.ajaxUrl,
|
|
method: 'POST',
|
|
data: formData,
|
|
success: function (response) {
|
|
if (response.success) {
|
|
window.location.href = window.location.href.split('?')[0] + '?page=hvac-zoho-sync&credentials_saved=1';
|
|
} else {
|
|
// Create error notice
|
|
var errorHtml = '<div class="notice notice-error is-dismissible"><p>' +
|
|
'<strong>Error saving credentials:</strong> ' + response.data.message +
|
|
'</p></div>';
|
|
$('h1').after(errorHtml);
|
|
|
|
$saveBtn.prop('disabled', false).text('Save Credentials');
|
|
}
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.error('Zoho Save Error:', xhr);
|
|
|
|
var errorMessage = 'Unknown error occurred';
|
|
var errorDetails = '';
|
|
|
|
if (xhr.status === 400 || xhr.status === 403) {
|
|
errorMessage = 'Request blocked (' + xhr.status + ')';
|
|
errorDetails = 'This is likely due to a security plugin or Web Application Firewall (WAF) blocking the request. ' +
|
|
'The content (e.g. Client Secret) might be triggering a false positive security rule.';
|
|
} else if (xhr.status === 500) {
|
|
errorMessage = 'Server Error (500)';
|
|
errorDetails = 'Check the server error logs for more information.';
|
|
} else if (status === 'timeout') {
|
|
errorMessage = 'Request timed out';
|
|
} else if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
|
|
errorMessage = xhr.responseJSON.data.message;
|
|
} else {
|
|
errorMessage = error || status;
|
|
}
|
|
|
|
var errorHtml = '<div class="notice notice-error is-dismissible" style="border-left-color: #dc3232;">' +
|
|
'<p><strong>❌ Save Failed:</strong> ' + errorMessage + '</p>';
|
|
|
|
if (errorDetails) {
|
|
errorHtml += '<p><em>' + errorDetails + '</em></p>';
|
|
}
|
|
|
|
// Add debug details
|
|
errorHtml += '<details style="margin-top: 10px;">' +
|
|
'<summary>Technical Details</summary>' +
|
|
'<ul style="margin-top: 5px; font-size: 12px; background: #f0f0f0; padding: 10px;">' +
|
|
'<li>Status: ' + xhr.status + ' ' + xhr.statusText + '</li>' +
|
|
'<li>Response: ' + (xhr.responseText ? xhr.responseText.substring(0, 100) + '...' : '(empty)') + '</li>' +
|
|
'</ul>' +
|
|
'</details></div>';
|
|
|
|
$('h1').after(errorHtml);
|
|
|
|
// Re-enable button
|
|
$saveBtn.prop('disabled', false).text('Save Credentials');
|
|
|
|
// Scroll to error
|
|
$('html, body').animate({ scrollTop: 0 }, 'slow');
|
|
}
|
|
});
|
|
});
|
|
|
|
// =====================================================
|
|
// OAuth authorization handler
|
|
// =====================================================
|
|
$('#start-oauth').on('click', function () {
|
|
var clientId = $('#zoho_client_id').val();
|
|
var clientSecret = $('#zoho_client_secret').val();
|
|
|
|
if (!clientId || !clientSecret) {
|
|
alert('Please save your credentials first before starting OAuth authorization.');
|
|
return;
|
|
}
|
|
|
|
// Use server-generated OAuth URL with CSRF state parameter
|
|
var oauthUrl = hvacZoho.oauthUrl || '';
|
|
|
|
if (!oauthUrl) {
|
|
alert('OAuth URL not available. Please save your credentials first and refresh the page.');
|
|
return;
|
|
}
|
|
|
|
// Open OAuth URL in the same window to handle callback properly
|
|
window.location.href = oauthUrl;
|
|
});
|
|
|
|
// =====================================================
|
|
// Test connection
|
|
// =====================================================
|
|
$('#test-connection').on('click', function () {
|
|
var $button = $(this);
|
|
var $status = $('#connection-status');
|
|
|
|
$button.prop('disabled', true).text('Testing...');
|
|
$status.html('');
|
|
|
|
$.ajax({
|
|
url: hvacZoho.ajaxUrl,
|
|
method: 'POST',
|
|
data: {
|
|
action: 'hvac_zoho_test_connection',
|
|
nonce: hvacZoho.nonce
|
|
},
|
|
success: function (response) {
|
|
if (response.success) {
|
|
var successHtml = '<div class="notice notice-success">';
|
|
successHtml += '<p><strong>' + response.data.message + '</strong></p>';
|
|
|
|
// Show credential details
|
|
if (response.data.client_id) {
|
|
successHtml += '<p>Client ID: ' + response.data.client_id + '</p>';
|
|
}
|
|
if (response.data.client_secret_exists) {
|
|
successHtml += '<p>Client Secret: ✓ Loaded</p>';
|
|
}
|
|
if (response.data.refresh_token_exists) {
|
|
successHtml += '<p>Refresh Token: ✓ Found</p>';
|
|
} else {
|
|
successHtml += '<p>Refresh Token: ❌ Missing (OAuth required)</p>';
|
|
}
|
|
|
|
// Show debug info if available
|
|
if (response.data.debug) {
|
|
successHtml += '<details style="margin-top: 10px;">';
|
|
successHtml += '<summary>Debug Information</summary>';
|
|
successHtml += '<pre style="background: #f0f0f0; padding: 10px; font-size: 12px;">';
|
|
successHtml += JSON.stringify(response.data.debug, null, 2);
|
|
successHtml += '</pre></details>';
|
|
}
|
|
|
|
successHtml += '</div>';
|
|
$status.html(successHtml);
|
|
} else {
|
|
// Debug: Log the response to see what we're getting
|
|
console.log('Error response:', response);
|
|
console.log('Message:', response.data.message);
|
|
console.log('Has auth_url:', !!response.data.auth_url);
|
|
|
|
// Handle OAuth authorization case specially
|
|
if (response.data.message === 'OAuth Authorization Required' && response.data.auth_url) {
|
|
var authHtml = '<div class="notice notice-warning">';
|
|
authHtml += '<h3>🔐 OAuth Authorization Required</h3>';
|
|
authHtml += '<p><strong>' + response.data.details + '</strong></p>';
|
|
|
|
if (response.data.next_steps) {
|
|
authHtml += '<ol>';
|
|
response.data.next_steps.forEach(function (step) {
|
|
authHtml += '<li>' + step + '</li>';
|
|
});
|
|
authHtml += '</ol>';
|
|
}
|
|
|
|
authHtml += '<p><a href="' + response.data.auth_url + '" target="_blank" class="button button-primary" style="margin: 10px 0;">🚀 Authorize with Zoho CRM</a></p>';
|
|
|
|
// Show credential status
|
|
if (response.data.credentials_status) {
|
|
authHtml += '<p><strong>Current Status:</strong></p>';
|
|
authHtml += '<ul>';
|
|
authHtml += '<li>Client ID: ' + response.data.credentials_status.client_id + '</li>';
|
|
authHtml += '<li>Client Secret: ' + (response.data.credentials_status.client_secret_exists ? '✓ Loaded' : '❌ Missing') + '</li>';
|
|
authHtml += '<li>Refresh Token: ' + (response.data.credentials_status.refresh_token_exists ? '✓ Found' : '❌ Missing') + '</li>';
|
|
authHtml += '</ul>';
|
|
}
|
|
|
|
authHtml += '<p><em>After authorization, come back and test the connection again.</em></p>';
|
|
authHtml += '</div>';
|
|
$status.html(authHtml);
|
|
return;
|
|
} else {
|
|
console.log('OAuth conditions not met:');
|
|
console.log('Message matches:', response.data.message === 'OAuth Authorization Required');
|
|
console.log('Auth URL exists:', !!response.data.auth_url);
|
|
}
|
|
|
|
// Create detailed error display for other errors
|
|
var errorHtml = '<div class="notice notice-error">';
|
|
errorHtml += '<p><strong>' + response.data.message + ':</strong> ' + response.data.error + '</p>';
|
|
|
|
// Add error code if available
|
|
if (response.data.code) {
|
|
errorHtml += '<p><strong>Error Code:</strong> ' + response.data.code + '</p>';
|
|
}
|
|
|
|
// Add details if available
|
|
if (response.data.details) {
|
|
errorHtml += '<p><strong>Details:</strong> ' + response.data.details + '</p>';
|
|
}
|
|
|
|
// Add debugging info
|
|
errorHtml += '<div class="hvac-zoho-debug-info">';
|
|
errorHtml += '<p><strong>Debug Information:</strong></p>';
|
|
errorHtml += '<p>Check the PHP error log for more details.</p>';
|
|
errorHtml += '<p>Log location: wp-content/plugins/hvac-community-events/logs/zoho-debug.log</p>';
|
|
|
|
// Add raw response data if available
|
|
if (response.data.raw) {
|
|
errorHtml += '<details>';
|
|
errorHtml += '<summary>Raw Response Data (click to expand)</summary>';
|
|
errorHtml += '<pre style="background: #f0f0f0; padding: 10px; max-height: 300px; overflow: auto;">' +
|
|
JSON.stringify(JSON.parse(response.data.raw), null, 2) +
|
|
'</pre>';
|
|
errorHtml += '</details>';
|
|
}
|
|
|
|
// Add file/line info if available (for exceptions)
|
|
if (response.data.file) {
|
|
errorHtml += '<p><strong>File:</strong> ' + response.data.file + '</p>';
|
|
}
|
|
|
|
// Add trace if available
|
|
if (response.data.trace) {
|
|
errorHtml += '<details>';
|
|
errorHtml += '<summary>Stack Trace (click to expand)</summary>';
|
|
errorHtml += '<pre style="background: #f0f0f0; padding: 10px; max-height: 300px; overflow: auto;">' +
|
|
response.data.trace +
|
|
'</pre>';
|
|
errorHtml += '</details>';
|
|
}
|
|
|
|
errorHtml += '</div>'; // Close debug info
|
|
errorHtml += '</div>'; // Close notice
|
|
|
|
$status.html(errorHtml);
|
|
}
|
|
},
|
|
error: function (xhr, status, error) {
|
|
var errorHtml = '<div class="notice notice-error">';
|
|
errorHtml += '<p><strong>AJAX Error:</strong> Connection test failed</p>';
|
|
errorHtml += '<p><strong>Status:</strong> ' + status + '</p>';
|
|
errorHtml += '<p><strong>Error:</strong> ' + error + '</p>';
|
|
errorHtml += '</div>';
|
|
|
|
$status.html(errorHtml);
|
|
},
|
|
complete: function () {
|
|
$button.prop('disabled', false).text('Test Connection');
|
|
}
|
|
});
|
|
});
|
|
|
|
// =====================================================
|
|
// Sync data with batch progress
|
|
// =====================================================
|
|
|
|
/**
|
|
* Sync with progress - auto-continues through all batches
|
|
* @param {jQuery} $button - The sync button
|
|
* @param {string} type - Sync type (events, users, attendees, rsvps, purchases)
|
|
* @param {jQuery} $status - Status container element
|
|
* @param {number} offset - Current offset
|
|
* @param {object} accumulated - Accumulated results across batches
|
|
*/
|
|
function syncWithProgress($button, type, $status, offset, accumulated) {
|
|
accumulated = accumulated || {
|
|
synced: 0,
|
|
failed: 0,
|
|
errors: [],
|
|
total: 0,
|
|
staging_mode: false,
|
|
responses: [],
|
|
test_data: []
|
|
};
|
|
|
|
$.ajax({
|
|
url: hvacZoho.ajaxUrl,
|
|
method: 'POST',
|
|
data: {
|
|
action: 'hvac_zoho_sync_data',
|
|
type: type,
|
|
offset: offset,
|
|
nonce: hvacZoho.nonce
|
|
},
|
|
success: function (response) {
|
|
if (response.success) {
|
|
var result = response.data;
|
|
|
|
// Update accumulated totals
|
|
accumulated.total = result.total; // Total is consistent across batches
|
|
accumulated.synced += result.synced;
|
|
accumulated.failed += result.failed;
|
|
accumulated.staging_mode = result.staging_mode;
|
|
|
|
// Merge arrays
|
|
if (result.errors && result.errors.length > 0) {
|
|
accumulated.errors = accumulated.errors.concat(result.errors);
|
|
}
|
|
if (result.responses && result.responses.length > 0) {
|
|
accumulated.responses = accumulated.responses.concat(result.responses);
|
|
}
|
|
if (result.test_data && result.test_data.length > 0) {
|
|
accumulated.test_data = accumulated.test_data.concat(result.test_data);
|
|
}
|
|
|
|
// Calculate progress
|
|
var processed = accumulated.synced + accumulated.failed;
|
|
var percent = accumulated.total > 0 ? Math.round((processed / accumulated.total) * 100) : 0;
|
|
|
|
// Update progress bar
|
|
var progressHtml = '<div class="sync-progress-bar" style="margin: 10px 0;">' +
|
|
'<div style="background: #e0e0e0; border-radius: 4px; overflow: hidden; height: 20px;">' +
|
|
'<div style="background: linear-gradient(90deg, #0073aa, #00a0d2); height: 100%; width: ' + percent + '%; transition: width 0.3s;"></div>' +
|
|
'</div>' +
|
|
'<p style="margin: 5px 0; font-size: 13px;">' +
|
|
'<strong>' + processed + ' of ' + accumulated.total + '</strong> processed (' + percent + '%)' +
|
|
'</p></div>';
|
|
$status.html(progressHtml);
|
|
|
|
// Check if there are more batches
|
|
if (result.has_more && result.next_offset > offset) {
|
|
// Continue with next batch
|
|
syncWithProgress($button, type, $status, result.next_offset, accumulated);
|
|
} else {
|
|
// All done! Show final results
|
|
displaySyncResults($button, type, $status, accumulated, result);
|
|
}
|
|
} else {
|
|
$status.html('<div class="notice notice-error"><p>' + response.data.message + ': ' + response.data.error + '</p></div>');
|
|
$button.prop('disabled', false).text('Sync ' + type.charAt(0).toUpperCase() + type.slice(1));
|
|
}
|
|
},
|
|
error: function () {
|
|
$status.html('<div class="notice notice-error"><p>Sync failed - network or server error</p></div>');
|
|
$button.prop('disabled', false).text('Sync ' + type.charAt(0).toUpperCase() + type.slice(1));
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Display final sync results
|
|
*/
|
|
function displaySyncResults($button, type, $status, accumulated, lastResult) {
|
|
var html = '<div class="notice notice-success">';
|
|
|
|
if (accumulated.staging_mode) {
|
|
html += '<h4>🔧 STAGING MODE - Simulation Complete</h4>';
|
|
html += '<p>No data was sent to Zoho CRM. This is a dry-run showing what would sync.</p>';
|
|
} else {
|
|
html += '<p><strong>✅ Sync completed successfully!</strong></p>';
|
|
}
|
|
|
|
if (lastResult.version) {
|
|
html += '<p><strong>Server Code Version:</strong> ' + lastResult.version + '</p>';
|
|
}
|
|
|
|
html += '<ul>' +
|
|
'<li>Total records: ' + accumulated.total + '</li>' +
|
|
'<li>Synced: ' + accumulated.synced + '</li>' +
|
|
'<li>Failed: ' + accumulated.failed + '</li>' +
|
|
'</ul>';
|
|
|
|
// Show test data for staging
|
|
if (accumulated.test_data && accumulated.test_data.length > 0) {
|
|
html += '<details>' +
|
|
'<summary>View test data (first 5 records)</summary>' +
|
|
'<pre style="background: #f0f0f0; padding: 10px; overflow: auto; max-height: 300px;">' +
|
|
JSON.stringify(accumulated.test_data.slice(0, 5), null, 2) +
|
|
'</pre>' +
|
|
'</details>';
|
|
}
|
|
|
|
// Debug info
|
|
if (lastResult.debug_info) {
|
|
html += '<details style="margin-top: 10px;">' +
|
|
'<summary>🔍 Debug: Mode Detection Info</summary>' +
|
|
'<div style="background: #f0f0f0; padding: 10px; font-size: 12px; margin-top: 5px;">';
|
|
|
|
if (typeof lastResult.debug_info.is_staging !== 'undefined') {
|
|
html += '<p><strong>Is Staging:</strong> ' + (lastResult.debug_info.is_staging ? '✅ YES' : '❌ NO') + '</p>';
|
|
}
|
|
if (lastResult.debug_info.site_url) {
|
|
html += '<p><strong>Site URL:</strong> ' + lastResult.debug_info.site_url + '</p>';
|
|
}
|
|
|
|
html += '<pre style="background: #e0e0e0; padding: 5px; margin-top: 5px; max-height: 150px; overflow: auto;">' +
|
|
JSON.stringify(lastResult.debug_info, null, 2) +
|
|
'</pre>' +
|
|
'</div>' +
|
|
'</details>';
|
|
}
|
|
|
|
// Show errors if any
|
|
if (accumulated.errors && accumulated.errors.length > 0) {
|
|
html += '<details style="margin-top: 10px; border: 2px solid #dc3232;">' +
|
|
'<summary style="font-weight: bold; color: #dc3232;">❌ Errors (' + accumulated.errors.length + ')</summary>' +
|
|
'<pre style="background: #fff0f0; padding: 10px; overflow: auto; max-height: 300px;">' +
|
|
JSON.stringify(accumulated.errors.slice(0, 20), null, 2) +
|
|
'</pre>' +
|
|
'</details>';
|
|
}
|
|
|
|
// Show API responses preview
|
|
if (accumulated.responses && accumulated.responses.length > 0) {
|
|
html += '<details style="margin-top: 10px;">' +
|
|
'<summary>📡 Raw API Responses (first 10)</summary>' +
|
|
'<pre style="background: #f0f0f0; padding: 10px; overflow: auto; max-height: 200px;">' +
|
|
JSON.stringify(accumulated.responses.slice(0, 10), null, 2) +
|
|
'</pre>' +
|
|
'</details>';
|
|
}
|
|
|
|
html += '</div>';
|
|
$status.html(html);
|
|
$button.prop('disabled', false).text('Sync ' + type.charAt(0).toUpperCase() + type.slice(1));
|
|
}
|
|
|
|
// Sync button click handler
|
|
$('.sync-button').on('click', function () {
|
|
var $button = $(this);
|
|
var type = $button.data('type');
|
|
var $status = $('#' + type + '-status');
|
|
|
|
$button.prop('disabled', true).text('Syncing...');
|
|
$status.html('<p>Starting sync for ' + type + '...</p>');
|
|
|
|
// Start sync with batch progress
|
|
syncWithProgress($button, type, $status, 0, null);
|
|
});
|
|
|
|
// Save settings
|
|
$('#zoho-settings-form').on('submit', function (e) {
|
|
e.preventDefault();
|
|
|
|
var $form = $(this);
|
|
var $button = $form.find('button[type="submit"]');
|
|
|
|
$button.prop('disabled', true).text('Saving...');
|
|
|
|
$.ajax({
|
|
url: hvacZoho.ajaxUrl,
|
|
method: 'POST',
|
|
data: {
|
|
action: 'hvac_zoho_save_settings',
|
|
nonce: hvacZoho.nonce,
|
|
auto_sync: $form.find('input[name="auto_sync"]').is(':checked') ? '1' : '0',
|
|
sync_frequency: $form.find('select[name="sync_frequency"]').val()
|
|
},
|
|
success: function (response) {
|
|
if (response.success) {
|
|
// Reload page to show updated status
|
|
window.location.reload();
|
|
} else {
|
|
// Use toast notification instead of alert
|
|
if (window.HVACToast) {
|
|
HVACToast.error('Error saving settings: ' + response.data.message);
|
|
} else {
|
|
alert('Error saving settings: ' + response.data.message);
|
|
}
|
|
$button.prop('disabled', false).text('Save Settings');
|
|
}
|
|
},
|
|
error: function () {
|
|
// Use toast notification instead of alert
|
|
if (window.HVACToast) {
|
|
HVACToast.error('Error saving settings');
|
|
} else {
|
|
alert('Error saving settings');
|
|
}
|
|
$button.prop('disabled', false).text('Save Settings');
|
|
}
|
|
});
|
|
});
|
|
|
|
// =====================================================
|
|
// Run Scheduled Sync Now Handler
|
|
// =====================================================
|
|
$('#run-scheduled-sync-now').on('click', function () {
|
|
var $button = $(this);
|
|
var $status = $('#scheduled-sync-status');
|
|
|
|
$button.prop('disabled', true).text('Running...');
|
|
$status.html('<p>Starting scheduled sync...</p>');
|
|
|
|
$.ajax({
|
|
url: hvacZoho.ajaxUrl,
|
|
method: 'POST',
|
|
data: {
|
|
action: 'hvac_zoho_run_scheduled_sync',
|
|
nonce: hvacZoho.nonce
|
|
},
|
|
success: function (response) {
|
|
if (response.success) {
|
|
var result = response.data.result;
|
|
var html = '<div class="notice notice-success">';
|
|
|
|
if (result.events && result.events.staging_mode) {
|
|
html += '<h4>🔧 STAGING MODE - Simulation Complete</h4>';
|
|
html += '<p>No data was sent to Zoho CRM.</p>';
|
|
} else {
|
|
html += '<p><strong>✅ Scheduled sync completed!</strong></p>';
|
|
}
|
|
|
|
html += '<ul>';
|
|
html += '<li>Total synced: ' + (result.total_synced || 0) + '</li>';
|
|
html += '<li>Total failed: ' + (result.total_failed || 0) + '</li>';
|
|
html += '<li>Duration: ' + (result.duration_seconds || 0) + ' seconds</li>';
|
|
html += '</ul>';
|
|
|
|
// Show details per type
|
|
html += '<details><summary>Details by type</summary><ul>';
|
|
['events', 'users', 'attendees', 'rsvps', 'purchases'].forEach(function (type) {
|
|
if (result[type]) {
|
|
html += '<li><strong>' + type + ':</strong> ' +
|
|
(result[type].synced || 0) + ' synced, ' +
|
|
(result[type].failed || 0) + ' failed</li>';
|
|
}
|
|
});
|
|
html += '</ul></details>';
|
|
|
|
html += '</div>';
|
|
$status.html(html);
|
|
} else {
|
|
$status.html('<div class="notice notice-error"><p>Sync failed: ' + response.data.message + '</p></div>');
|
|
}
|
|
},
|
|
error: function () {
|
|
$status.html('<div class="notice notice-error"><p>Error running scheduled sync</p></div>');
|
|
},
|
|
complete: function () {
|
|
$button.prop('disabled', false).text('🔄 Run Sync Now');
|
|
}
|
|
});
|
|
});
|
|
|
|
// =====================================================
|
|
// Diagnostic Test Handler
|
|
// =====================================================
|
|
$('#diagnostic-test').on('click', function () {
|
|
var $button = $(this);
|
|
$button.prop('disabled', true).text('Testing...');
|
|
|
|
// Remove existing notices
|
|
$('.notice').remove();
|
|
|
|
// Test 1: Simple GET
|
|
var runSimpleTest = function () {
|
|
return $.ajax({
|
|
url: hvacZoho.ajaxUrl,
|
|
method: 'POST',
|
|
data: {
|
|
action: 'hvac_zoho_simple_test'
|
|
}
|
|
});
|
|
};
|
|
|
|
// Test 2: Payload Test (simulates credentials)
|
|
var runPayloadTest = function () {
|
|
var fakeId = '1000.' + new Array(20).join('a');
|
|
var fakeSecret = new Array(30).join('b');
|
|
|
|
return $.ajax({
|
|
url: hvacZoho.ajaxUrl,
|
|
method: 'POST',
|
|
data: {
|
|
action: 'hvac_zoho_simple_test',
|
|
test_payload: 'SIMULATED_CREDENTIALS',
|
|
zoho_client_id: fakeId,
|
|
zoho_client_secret: fakeSecret
|
|
}
|
|
});
|
|
};
|
|
|
|
// Execute tests sequence
|
|
runSimpleTest()
|
|
.then(function (response) {
|
|
if (response.success) {
|
|
console.log('Simple test passed');
|
|
return runPayloadTest();
|
|
} else {
|
|
return $.Deferred().reject({ status: 200, statusText: 'OK', responseJSON: response });
|
|
}
|
|
})
|
|
.then(function (response) {
|
|
if (response.success) {
|
|
// Success!
|
|
var successHtml = '<div class="notice notice-success is-dismissible">' +
|
|
'<p><strong>✅ Diagnostic Test Passed</strong></p>' +
|
|
'<p>AJAX requests are working correctly. No WAF blocking detected for credential-like data.</p>' +
|
|
'</div>';
|
|
$('h1').after(successHtml);
|
|
} else {
|
|
return $.Deferred().reject({ status: 200, statusText: 'OK', responseJSON: response });
|
|
}
|
|
})
|
|
.fail(function (xhr) {
|
|
var errorHtml = '<div class="notice notice-error is-dismissible">' +
|
|
'<p><strong>❌ Diagnostic Test Failed</strong></p>';
|
|
|
|
if (xhr.status === 400 || xhr.status === 403) {
|
|
errorHtml += '<p><strong>WAF Blocking Detected!</strong></p>';
|
|
errorHtml += '<p>The server returned ' + xhr.status + ' when sending data.</p>';
|
|
} else {
|
|
errorHtml += '<p>Status: ' + (xhr.status || 'Unknown') + '</p>';
|
|
if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
|
|
errorHtml += '<p>Message: ' + xhr.responseJSON.data.message + '</p>';
|
|
}
|
|
}
|
|
|
|
errorHtml += '</div>';
|
|
$('h1').after(errorHtml);
|
|
})
|
|
.always(function () {
|
|
$button.prop('disabled', false).text('🏥 Run Diagnostic Test');
|
|
});
|
|
});
|
|
}); |