From e251e7fe243ac6aa17a693549da3179c9d37f15b Mon Sep 17 00:00:00 2001 From: ruben Date: Fri, 7 Mar 2025 07:34:04 -0600 Subject: [PATCH] Fix JavaScript error in dashboard modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Changed $steps variable from const to let to allow reassignment - Added new modal styling and AJAX form handlers - Fixed campaign form JavaScript 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- css/modal.css | 344 +++++++++++++++++++++++ includes/rl-mailwarmer-ajax.php | 275 ++++++++++++++++-- js/campaign-form.js | 2 +- js/dashboard-modal.js | 484 ++++++++++++++++++++++++++++++++ 4 files changed, 1078 insertions(+), 27 deletions(-) create mode 100644 css/modal.css create mode 100644 js/dashboard-modal.js diff --git a/css/modal.css b/css/modal.css new file mode 100644 index 0000000..0d81806 --- /dev/null +++ b/css/modal.css @@ -0,0 +1,344 @@ +/* Modal Styles */ +.mf-floating-action-button { + position: fixed; + bottom: 30px; + right: 30px; + width: 60px; + height: 60px; + background-color: #0073aa; + border-radius: 50%; + text-align: center; + line-height: 60px; + font-size: 24px; + color: white; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); + cursor: pointer; + z-index: 1000; + transition: transform 0.3s, background-color 0.3s; +} + +.mf-floating-action-button:hover { + transform: scale(1.1); + background-color: #005d87; +} + +.mf-modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(8px); + z-index: 1001; + display: flex; + justify-content: center; + align-items: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s, visibility 0.3s; +} + +.mf-modal-overlay.active { + opacity: 1; + visibility: visible; +} + +.mf-modal-container { + background: white; + width: 90%; + max-width: 700px; + border-radius: 8px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); + position: relative; + overflow: hidden; + max-height: 90vh; + display: flex; + flex-direction: column; +} + +.mf-modal-header { + padding: 20px; + background-color: #f8f8f8; + border-bottom: 1px solid #eee; + display: flex; + justify-content: space-between; + align-items: center; +} + +.mf-modal-header h2 { + margin: 0; + font-size: 1.4rem; + color: #333; +} + +.mf-modal-close { + background: none; + border: none; + font-size: 24px; + color: #888; + cursor: pointer; + transition: color 0.3s; +} + +.mf-modal-close:hover { + color: #333; +} + +.mf-modal-body { + padding: 20px; + overflow-y: auto; + flex: 1; +} + +.mf-modal-footer { + padding: 15px 20px; + background-color: #f8f8f8; + border-top: 1px solid #eee; + display: flex; + justify-content: space-between; +} + +.mf-modal-footer button { + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + border: none; + font-weight: 500; +} + +.mf-back-btn { + background-color: #f0f0f0; + color: #555; +} + +.mf-next-btn { + background-color: #0073aa; + color: white; +} + +.mf-back-btn:hover { + background-color: #e0e0e0; +} + +.mf-next-btn:hover { + background-color: #005d87; +} + +.mf-next-btn.disabled { + background-color: #ccc; + cursor: not-allowed; +} + +/* Step indicator styles */ +.mf-steps-indicator { + display: flex; + justify-content: center; + margin: 0 0 20px; +} + +.mf-step-dot { + width: 10px; + height: 10px; + border-radius: 50%; + background-color: #ddd; + margin: 0 5px; + transition: background-color 0.3s; +} + +.mf-step-dot.active { + background-color: #0073aa; +} + +.mf-step-dot.completed { + background-color: #4CAF50; +} + +/* Multi-step form styles */ +.mf-step { + display: none; +} + +.mf-step.active { + display: block; +} + +.mf-step h3 { + margin-top: 0; + color: #333; +} + +.mf-form-field { + margin-bottom: 20px; +} + +.mf-form-field label { + display: block; + margin-bottom: 8px; + font-weight: 500; +} + +.mf-form-field input, +.mf-form-field select { + width: 100%; + padding: 10px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 16px; +} + +.mf-form-field input:focus, +.mf-form-field select:focus { + border-color: #0073aa; + outline: none; + box-shadow: 0 0 0 1px #0073aa; +} + +.mf-selection-buttons { + display: flex; + gap: 10px; + margin-bottom: 20px; +} + +.mf-selection-button { + flex: 1; + padding: 15px; + border: 2px solid #ddd; + border-radius: 6px; + background-color: #f8f8f8; + text-align: center; + cursor: pointer; + transition: all 0.3s; +} + +.mf-selection-button:hover { + border-color: #0073aa; + background-color: #f0f7fb; +} + +.mf-selection-button.selected { + border-color: #0073aa; + background-color: #e6f3fa; +} + +.mf-selection-button i { + display: block; + font-size: 24px; + margin-bottom: 10px; + color: #555; +} + +.mf-selection-button.selected i { + color: #0073aa; +} + +.mf-validation-error { + color: #d32f2f; + font-size: 14px; + margin-top: 5px; + display: none; +} + +.mf-loading { + display: flex; + justify-content: center; + align-items: center; + padding: 20px; +} + +.mf-loading-spinner { + border: 4px solid #f3f3f3; + border-top: 4px solid #0073aa; + border-radius: 50%; + width: 30px; + height: 30px; + animation: spin 1s linear infinite; + margin-right: 10px; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.mf-success-message, +.mf-error-message { + padding: 15px; + border-radius: 4px; + margin-bottom: 20px; +} + +.mf-success-message { + background-color: #e8f5e9; + border: 1px solid #c8e6c9; + color: #2e7d32; +} + +.mf-error-message { + background-color: #ffebee; + border: 1px solid #ffcdd2; + color: #c62828; +} + +.mf-mx-option { + border: 1px solid #ddd; + border-radius: 4px; + padding: 15px; + margin-bottom: 10px; + cursor: pointer; + transition: all 0.3s; +} + +.mf-mx-option:hover { + border-color: #0073aa; + background-color: #f0f7fb; +} + +.mf-mx-option.selected { + border-color: #0073aa; + background-color: #e6f3fa; +} + +.mf-email-list { + margin-top: 20px; +} + +.mf-email-row { + display: flex; + margin-bottom: 10px; + gap: 10px; +} + +.mf-email-row input { + flex: 1; +} + +.mf-add-email-btn { + background-color: #0073aa; + color: white; + border: none; + border-radius: 4px; + padding: 8px 16px; + cursor: pointer; + margin-top: 10px; +} + +.mf-add-email-btn:hover { + background-color: #005d87; +} + +.mf-remove-email-btn { + background-color: #f44336; + color: white; + border: none; + border-radius: 4px; + padding: 8px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; +} + +.mf-remove-email-btn:hover { + background-color: #d32f2f; +} \ No newline at end of file diff --git a/includes/rl-mailwarmer-ajax.php b/includes/rl-mailwarmer-ajax.php index c351942..752f2d8 100644 --- a/includes/rl-mailwarmer-ajax.php +++ b/includes/rl-mailwarmer-ajax.php @@ -356,32 +356,6 @@ add_action('wp_ajax_rl_mailwarmer_create_dns_backup', function () { } }); -add_action('wp_ajax_rl_mailwarmer_modify_email_account', function () { - // Verify nonce - if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'modify_email_account_nonce')) { - wp_send_json_error(__('Invalid nonce', 'rl-mailwarmer')); - } - - // Prepare arguments for modify_email_account - $args = [ - 'action' => sanitize_text_field($_POST['action_type']), - 'email' => sanitize_email($_POST['email_address']), - 'metadata' => [ - 'mail_password' => sanitize_text_field($_POST['mail_password']), - 'email_provider' => intval($_POST['email_provider']), - 'imap_server' => sanitize_text_field($_POST['imap_server']), - ], - ]; - - // Call modify_email_account - try { - $result = RL_MailWarmer_Email_Helper::modify_email_account($args); - wp_send_json_success('Email account successfully modified. Post ID: ' . $result); - } catch (Exception $e) { - wp_send_json_error($e->getMessage()); - } -}); - // CAMPAIGN MANAGEMENT AJAX ENDPOINTS /** @@ -655,6 +629,32 @@ add_action('wp_ajax_rl_mailwarmer_delete_email_account', function () { wp_send_json_success(['message' => __('Email account deleted successfully', 'rl-mailwarmer')]); }); +add_action('wp_ajax_rl_mailwarmer_modify_email_account', function () { + // Verify nonce + if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'modify_email_account_nonce')) { + wp_send_json_error(__('Invalid nonce', 'rl-mailwarmer')); + } + + // Prepare arguments for modify_email_account + $args = [ + 'action' => sanitize_text_field($_POST['action_type']), + 'email' => sanitize_email($_POST['email_address']), + 'metadata' => [ + 'mail_password' => sanitize_text_field($_POST['mail_password']), + 'email_provider' => intval($_POST['email_provider']), + 'imap_server' => sanitize_text_field($_POST['imap_server']), + ], + ]; + + // Call modify_email_account + try { + $result = RL_MailWarmer_Email_Helper::modify_email_account($args); + wp_send_json_success('Email account successfully modified. Post ID: ' . $result); + } catch (Exception $e) { + wp_send_json_error($e->getMessage()); + } +}); + add_action('wp_ajax_rl_mailwarmer_check_mail_login', function () { // Verify nonce if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'check_mail_login_nonce')) { @@ -677,3 +677,226 @@ add_action('wp_ajax_rl_mailwarmer_check_mail_login', function () { wp_send_json_error($e->getMessage()); } }); + +/** + * Dashboard Modal AJAX handlers + */ + +/** + * Validate domain for adding to Mailferno + */ +add_action('wp_ajax_validate_domain', function() { + // Verify nonce + if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'dashboard_modal_nonce')) { + wp_send_json_error(['message' => __('Security check failed', 'rl-mailwarmer')]); + } + + // Get and validate domain + $domain = isset($_POST['domain']) ? sanitize_text_field($_POST['domain']) : ''; + + if (empty($domain)) { + wp_send_json_error(['message' => __('Domain name is required', 'rl-mailwarmer')]); + } + + // Check if domain already exists + $existing_domain = get_page_by_title($domain, OBJECT, 'domain'); + if ($existing_domain) { + wp_send_json_error(['message' => __('Domain already exists in your account', 'rl-mailwarmer')]); + return; + } + + // Check if domain is valid (DNS resolves) + if (!checkdnsrr($domain, 'A') && !checkdnsrr($domain, 'AAAA')) { + wp_send_json_error(['message' => __('Domain does not resolve to a valid IP address', 'rl-mailwarmer')]); + return; + } + + // Check if domain uses CloudFlare + $uses_cloudflare = false; + + // Get the NS records for the domain + $ns_records = dns_get_record($domain, DNS_NS); + + // If no NS records found directly, try with www + if (empty($ns_records)) { + $ns_records = dns_get_record('www.' . $domain, DNS_NS); + } + + // Check if any NS record contains cloudflare + if (!empty($ns_records)) { + foreach ($ns_records as $record) { + if (isset($record['target']) && stripos($record['target'], 'cloudflare') !== false) { + $uses_cloudflare = true; + break; + } + } + } + + wp_send_json_success([ + 'isValid' => true, + 'usesCloudFlare' => $uses_cloudflare + ]); +}); + +/** + * Verify CloudFlare credentials and check MX records + */ +add_action('wp_ajax_verify_cloudflare', function() { + // Verify nonce + if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'dashboard_modal_nonce')) { + wp_send_json_error(['message' => __('Security check failed', 'rl-mailwarmer')]); + } + + $domain = isset($_POST['domain']) ? sanitize_text_field($_POST['domain']) : ''; + $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : ''; + $key = isset($_POST['key']) ? sanitize_text_field($_POST['key']) : ''; + + if (empty($domain) || empty($email) || empty($key)) { + wp_send_json_error(['message' => __('Missing required fields', 'rl-mailwarmer')]); + return; + } + + // Use existing cloudflare helper to verify credentials and get zone ID + try { + $client = new \GuzzleHttp\Client([ + 'base_uri' => 'https://api.cloudflare.com/client/v4/', + 'headers' => [ + 'Content-Type' => 'application/json', + ], + ]); + + $response = $client->get('zones', [ + 'headers' => [ + 'Authorization' => "Bearer {$key}", + 'Content-Type' => 'application/json', + ], + 'query' => ['name' => $domain], + ]); + + $data = json_decode($response->getBody()->getContents(), true); + + if (!isset($data['result'][0]['id'])) { + wp_send_json_error(['message' => __('Domain not found in your CloudFlare account', 'rl-mailwarmer')]); + return; + } + + $zone_id = $data['result'][0]['id']; + + // Check if MX records exist + $has_mx = false; + + // Query CloudFlare for MX records + $mx_response = $client->get("zones/{$zone_id}/dns_records", [ + 'headers' => [ + 'Authorization' => "Bearer {$key}", + 'Content-Type' => 'application/json', + ], + 'query' => ['type' => 'MX'], + ]); + + $mx_data = json_decode($mx_response->getBody()->getContents(), true); + + if (isset($mx_data['result']) && !empty($mx_data['result'])) { + $has_mx = true; + } + + wp_send_json_success([ + 'zoneId' => $zone_id, + 'hasMX' => $has_mx + ]); + } catch (Exception $e) { + wp_send_json_error(['message' => __('Failed to verify CloudFlare credentials: ', 'rl-mailwarmer') . $e->getMessage()]); + } +}); + +/** + * Create domain with all configurations + */ +add_action('wp_ajax_create_domain', function() { + // Verify nonce + if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'dashboard_modal_nonce')) { + wp_send_json_error(['message' => __('Security check failed', 'rl-mailwarmer')]); + } + + // Get domain data + $domain_data_json = isset($_POST['domainData']) ? $_POST['domainData'] : ''; + + if (empty($domain_data_json)) { + wp_send_json_error(['message' => __('No domain data provided', 'rl-mailwarmer')]); + return; + } + + $domain_data = json_decode(stripslashes($domain_data_json), true); + + // Create the domain post + $current_user_id = get_current_user_id(); + $domain_name = $domain_data['domain']; + + $post_data = array( + 'post_title' => $domain_name, + 'post_type' => 'domain', + 'post_status' => 'publish' + ); + + $post_id = wp_insert_post($post_data); + + if (is_wp_error($post_id)) { + wp_send_json_error(['message' => $post_id->get_error_message()]); + return; + } + + // Save domain meta data + update_post_meta($post_id, 'cloudflare_api_email', $domain_data['cloudflareEmail']); + update_post_meta($post_id, 'cloudflare_api_key', $domain_data['cloudflareKey']); + update_post_meta($post_id, 'cloudflare_zone_id', $domain_data['cloudflareZoneId']); + update_post_meta($post_id, 'domain_in_use', !$domain_data['configureMailferno']); + update_post_meta($post_id, 'owner_id', $current_user_id); + + // Run a domain health check + $domain_report_id = RL_MailWarmer_Domain_Helper::save_domain_health_report($post_id); + + // Handle DNS configuration if requested + if ($domain_data['configureMailferno']) { + $server = get_field('defaut_mailferno_mx', 'option'); + RL_MailWarmer_Domain_Helper::update_mx_record($post_id, $server->post_title, 0, 3600); + } + + // Fix DNS records + $results = RL_MailWarmer_Domain_Helper::fix_deliverability_dns_issues($post_id); + + // Create email accounts if provided + $email_accounts = []; + + if (!empty($domain_data['emailAccounts'])) { + foreach ($domain_data['emailAccounts'] as $email) { + // Extract username from email + $username = explode('@', $email)[0]; + + // Create email account + $email_post_data = array( + 'post_title' => $email, + 'post_type' => 'email-account', + 'post_status' => 'publish' + ); + + $email_post_id = wp_insert_post($email_post_data); + + if (!is_wp_error($email_post_id)) { + // Set default password and metadata + update_post_meta($email_post_id, 'domain_id', $post_id); + update_post_meta($email_post_id, 'mail_password', wp_generate_password(12, false)); + update_post_meta($email_post_id, 'full_name', ucwords(str_replace(['.', '-', '_'], ' ', $username))); + update_post_meta($email_post_id, 'owner_id', $current_user_id); + update_post_meta($email_post_id, 'include_in_warmup_pool', true); + + $email_accounts[] = $email_post_id; + } + } + } + + wp_send_json_success([ + 'message' => __('Domain added successfully. ' . (!empty($email_accounts) ? count($email_accounts) . ' email accounts created.' : ''), 'rl-mailwarmer'), + 'domain_id' => $post_id, + 'email_accounts' => $email_accounts + ]); +}); \ No newline at end of file diff --git a/js/campaign-form.js b/js/campaign-form.js index 9cb5dff..3b7c4bc 100644 --- a/js/campaign-form.js +++ b/js/campaign-form.js @@ -41,7 +41,7 @@ jQuery(document).ready(function($) { // Reset form or redirect if not staying on page if (!$('#stay_on_page').is(':checked') && response.data.permalink) { - window.location.href = response.data.permalink; + // window.location.href = response.data.permalink; return; } else if (!$('#stay_on_page').is(':checked')) { window.location.href = campaign_form_vars.campaigns_page; diff --git a/js/dashboard-modal.js b/js/dashboard-modal.js new file mode 100644 index 0000000..f0f0492 --- /dev/null +++ b/js/dashboard-modal.js @@ -0,0 +1,484 @@ +/** + * Dashboard Modal & Multi-step Form Handlers + */ +jQuery(document).ready(function($) { + // Modal elements + const $fabButton = $('.mf-floating-action-button'); + const $modalOverlay = $('.mf-modal-overlay'); + const $modalContainer = $('.mf-modal-container'); + const $modalClose = $('.mf-modal-close'); + const $backBtn = $('.mf-back-btn'); + const $nextBtn = $('.mf-next-btn'); + + // Step indicators + const $stepDots = $('.mf-step-dot'); + let $steps = $('.mf-step'); + + // Selection buttons + const $selectionButtons = $('.mf-selection-button'); + + // Current step and selected type + let currentStep = 0; + let selectedType = ''; + let domainData = { + domain: '', + isValid: false, + usesCloudFlare: false, + cloudflareZoneId: '', + cloudflareEmail: '', + cloudflareKey: '', + hasMX: false, + configureMailferno: false, + emailAccounts: [] + }; + + // Open Modal + $fabButton.on('click', function() { + resetForm(); + $modalOverlay.addClass('active'); + }); + + // Close Modal + $modalClose.on('click', closeModal); + $modalOverlay.on('click', function(e) { + if (e.target === this) { + closeModal(); + } + }); + + function closeModal() { + $modalOverlay.removeClass('active'); + resetForm(); + } + + // Reset Form + function resetForm() { + currentStep = 0; + selectedType = ''; + domainData = { + domain: '', + isValid: false, + usesCloudFlare: false, + cloudflareZoneId: '', + cloudflareEmail: '', + cloudflareKey: '', + hasMX: false, + configureMailferno: false, + emailAccounts: [] + }; + + $selectionButtons.removeClass('selected'); + updateStepIndicators(); + showCurrentStep(); + $('.mf-validation-error').hide(); + $('.mf-success-message, .mf-error-message').remove(); + $('.mf-loading').hide(); + $('#mf-domain-input').val(''); + $('#mf-cloudflare-email').val(''); + $('#mf-cloudflare-key').val(''); + $('.mf-mx-option').removeClass('selected'); + $('.mf-email-row:not(:first)').remove(); + $('.mf-email-row input').val(''); + } + + // Selection buttons + $selectionButtons.on('click', function() { + $selectionButtons.removeClass('selected'); + $(this).addClass('selected'); + selectedType = $(this).data('type'); + $nextBtn.removeClass('disabled'); + }); + + // Navigation buttons + $backBtn.on('click', function() { + if (currentStep > 0) { + currentStep--; + updateStepIndicators(); + showCurrentStep(); + } + }); + + $nextBtn.on('click', function() { + if ($(this).hasClass('disabled')) return; + + // Handle first step (selection) + if (currentStep === 0) { + if (!selectedType) { + alert('Please select an option to continue'); + return; + } + + // Set up next steps based on selection + setupStepsByType(selectedType); + currentStep++; + updateStepIndicators(); + showCurrentStep(); + return; + } + + // Domain specific step handling + if (selectedType === 'domain') { + const result = handleDomainStep(currentStep); + if (!result) return; // If step validation fails, don't proceed + } + + // If we reach here, move to next step + currentStep++; + updateStepIndicators(); + showCurrentStep(); + }); + + // Update step indicators + function updateStepIndicators() { + $stepDots.removeClass('active completed'); + + // Update for current setup + $stepDots.each(function(index) { + if (index < currentStep) { + $(this).addClass('completed'); + } else if (index === currentStep) { + $(this).addClass('active'); + } + }); + + // Update back button visibility + if (currentStep === 0) { + $backBtn.hide(); + } else { + $backBtn.show(); + } + + // Update next button text + const isLastStep = (currentStep === $steps.length - 1); + $nextBtn.text(isLastStep ? 'Next' : 'Next'); + + // When on selection step, disable next until selection made + if (currentStep === 0) { + $nextBtn.toggleClass('disabled', !selectedType); + } else { + $nextBtn.removeClass('disabled'); + } + } + + // Show current step + function showCurrentStep() { + $steps.removeClass('active'); + $steps.eq(currentStep).addClass('active'); + } + + // Setup steps by selected type + function setupStepsByType(type) { + // Hide all steps except the first one + $steps.not(':first').remove(); + + // Clear step indicators + $('.mf-steps-indicator').empty(); + + let stepCount = 1; // Selection step + + if (type === 'domain') { + // Step 1: Input domain + $('
') + .append('

Enter Domain Name

') + .append('
Please enter a valid domain name
') + .append('') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + + // Step 2: CloudFlare verification + $('
') + .append('

Verify CloudFlare Connection

') + .append('
') + .append('
') + .append('
Please enter valid CloudFlare credentials
') + .append('') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + + // Step 3: MX Configuration + $('
') + .append('

Email Server Configuration

') + .append('

How would you like to configure email for this domain?

') + .append('

Use Mailferno MX Server

Configure this domain to use Mailferno\'s email server. Best if this is a new domain not currently used for email.

Keep Existing Configuration

Keep your current email server configuration. Best if this domain is already being used for email.

') + .append('
Please select an MX configuration option
') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + + // Step 4: Email accounts + $('
') + .append('

Add Email Accounts

') + .append('

Would you like to create email accounts for this domain now?

') + .append('
@'+domainData.domain+'
') + .append('') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + + // Final step + $('
') + .append('

Domain Setup Complete

') + .append('
Your domain has been successfully added to Mailferno!
') + .append('

You can now continue to manage your domain, email accounts, and campaigns from the dashboard.

') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + } else if (type === 'campaign') { + // Add campaign specific steps + $('
') + .append('

Create Campaign

') + .append('

Campaign creation functionality will be implemented here.

') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + + // Final step + $('
') + .append('

Campaign Created

') + .append('
Your campaign has been successfully created!
') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + } else if (type === 'email') { + // Add email account specific steps + $('
') + .append('

Create Email Account

') + .append('

Email account creation functionality will be implemented here.

') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + + // Final step + $('
') + .append('

Email Account Created

') + .append('
Your email account has been successfully created!
') + .appendTo($modalContainer.find('.mf-modal-body')); + stepCount++; + } + + // Create step indicators + for (let i = 0; i < stepCount; i++) { + $('
') + .addClass(i === 0 ? 'completed' : (i === 1 ? 'active' : '')) + .appendTo($('.mf-steps-indicator')); + } + + // Make steps accessible + $steps = $('.mf-step'); + + // Setup event handlers for the domain steps + if (type === 'domain') { + setupDomainStepHandlers(); + } + } + + // Domain step specific handlers + function setupDomainStepHandlers() { + // Step 1: Domain validation + $('#mf-domain-input').on('input', function() { + // Basic validation + const domain = $(this).val().trim(); + const isValid = /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(domain); + + if (isValid) { + $('#domain-validation-error').hide(); + domainData.domain = domain; + } else { + $('#domain-validation-error').show(); + } + }); + + // Step 3: MX Configuration + $('.mf-mx-option').on('click', function() { + $('.mf-mx-option').removeClass('selected'); + $(this).addClass('selected'); + domainData.configureMailferno = ($(this).data('option') === 'mailferno'); + }); + + // Step 4: Email accounts + $('.mf-add-email-btn').on('click', function() { + const $newRow = $('.mf-email-row').first().clone(); + $newRow.find('input').val(''); + $newRow.insertBefore($(this)); + }); + + // Remove email button + $(document).on('click', '.mf-remove-email-btn', function() { + if ($('.mf-email-row').length > 1) { + $(this).closest('.mf-email-row').remove(); + } else { + $('.mf-email-row').find('input').val(''); + } + }); + } + + // Domain step validation and AJAX handling + function handleDomainStep(step) { + // Adjust step to match domain-specific numbering (after selection) + const domainStep = step - 1; + + switch(domainStep) { + case 0: // Domain input validation + const domain = $('#mf-domain-input').val().trim(); + if (!domain || !/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/.test(domain)) { + $('#domain-validation-error').show(); + return false; + } + + domainData.domain = domain; + + // Show loading indicator + $steps.eq(currentStep).find('.mf-loading').show(); + $nextBtn.addClass('disabled'); + + // AJAX validation call to check if domain is valid and uses CloudFlare + $.ajax({ + url: dashboard_modal_vars.ajax_url, + type: 'POST', + data: { + action: 'validate_domain', + security: dashboard_modal_vars.nonce, + domain: domain + }, + success: function(response) { + $steps.eq(currentStep).find('.mf-loading').hide(); + + if (response.success) { + domainData.isValid = true; + domainData.usesCloudFlare = response.data.usesCloudFlare; + + if (!domainData.usesCloudFlare) { + $steps.eq(currentStep).append('
This domain is not using CloudFlare nameservers. Please configure CloudFlare for this domain before continuing.
'); + return; + } + + // Update domain text in email step + $('.mf-email-row span').text('@' + domain); + + // Continue to next step + $nextBtn.removeClass('disabled'); + $nextBtn.trigger('click'); + } else { + $steps.eq(currentStep).append('
' + response.data.message + '
'); + $nextBtn.removeClass('disabled'); + } + }, + error: function() { + $steps.eq(currentStep).find('.mf-loading').hide(); + $steps.eq(currentStep).append('
Error validating domain. Please try again.
'); + $nextBtn.removeClass('disabled'); + } + }); + return false; // Prevent automatic next step - we'll handle it in AJAX callback + + case 1: // CloudFlare verification + const email = $('#mf-cloudflare-email').val().trim(); + const key = $('#mf-cloudflare-key').val().trim(); + + if (!email || !key) { + $('#cloudflare-validation-error').show(); + return false; + } + + domainData.cloudflareEmail = email; + domainData.cloudflareKey = key; + + // Show loading indicator + $steps.eq(currentStep).find('.mf-loading').show(); + $nextBtn.addClass('disabled'); + + // AJAX call to verify CloudFlare credentials + $.ajax({ + url: dashboard_modal_vars.ajax_url, + type: 'POST', + data: { + action: 'verify_cloudflare', + security: dashboard_modal_vars.nonce, + domain: domainData.domain, + email: email, + key: key + }, + success: function(response) { + $steps.eq(currentStep).find('.mf-loading').hide(); + + if (response.success) { + domainData.cloudflareZoneId = response.data.zoneId; + domainData.hasMX = response.data.hasMX; + + // Continue to next step + $nextBtn.removeClass('disabled'); + $nextBtn.trigger('click'); + } else { + $steps.eq(currentStep).append('
' + response.data.message + '
'); + $nextBtn.removeClass('disabled'); + } + }, + error: function() { + $steps.eq(currentStep).find('.mf-loading').hide(); + $steps.eq(currentStep).append('
Error verifying CloudFlare credentials. Please try again.
'); + $nextBtn.removeClass('disabled'); + } + }); + return false; // Prevent automatic next step - we'll handle it in AJAX callback + + case 2: // MX Configuration + if (!$('.mf-mx-option.selected').length) { + $('#mx-validation-error').show(); + return false; + } + + domainData.configureMailferno = ($('.mf-mx-option.selected').data('option') === 'mailferno'); + return true; + + case 3: // Email accounts + domainData.emailAccounts = []; + let allValid = true; + + $('.mf-email-row').each(function() { + const username = $(this).find('.mf-email-local').val().trim(); + if (username) { + domainData.emailAccounts.push(username + '@' + domainData.domain); + } + }); + + if (allValid) { + // Create domain via AJAX + $nextBtn.addClass('disabled'); + + $.ajax({ + url: dashboard_modal_vars.ajax_url, + type: 'POST', + data: { + action: 'create_domain', + security: dashboard_modal_vars.nonce, + domainData: JSON.stringify(domainData) + }, + success: function(response) { + if (response.success) { + // Update final step + $steps.eq(currentStep + 1).find('.mf-success-message').text(response.data.message); + + // Continue to next step + $nextBtn.removeClass('disabled'); + $nextBtn.trigger('click'); + + // Reload page after a short delay to show updated dashboard + setTimeout(function() { + window.location.reload(); + }, 5000); + } else { + $steps.eq(currentStep).append('
' + response.data.message + '
'); + $nextBtn.removeClass('disabled'); + } + }, + error: function() { + $steps.eq(currentStep).append('
Error creating domain. Please try again.
'); + $nextBtn.removeClass('disabled'); + } + }); + return false; + } + return allValid; + + case 4: // Final step - just close modal + closeModal(); + return true; + } + + return true; + } +}); \ No newline at end of file