Advanced Web Server Manager
Complete File Manager & Terminal - Standalone Version
By Sid Gifari | Gifari Industries
Current path:
/
/
home
/
qtdcvxyp
/
public_html
/
wp-content
/
plugins
/
formlayer-pro
/
main
/
settings
✏️
Editing: ui.php
<?php /* * FormLayer Pro * https://formlayer.net * (c) FormLayer Team */ namespace FormLayerPro\Settings; if(!defined('ABSPATH')){ exit; } class UI{ static function render_int_card( $name, $desc, $logo, $slug, $tag = '', $connected = false){ $doc_urls = [ 'mailchimp' => 'https://formlayer.net/doc-article?article=mailchimp', 'slack' => 'https://formlayer.net/doc-article?article=slack-discord', 'discord' => 'https://formlayer.net/doc-article?article=slack-discord', 'sheets' => 'https://formlayer.net/doc-article?article=google-sheets', 'notion' => 'https://formlayer.net/doc-article?article=notion', 'trello' => 'https://formlayer.net/doc-article?article=trello', ]; $doc_url = isset($doc_urls[$slug]) ? $doc_urls[$slug] : 'https://formlayer.net/docs'; echo '<div class="formlayer-integration-card" data-slug="' . esc_attr($slug) . '"> <div class="formlayer-card-header"> <div class="formlayer-int-icon" style="background:none; padding:0;"> <img src="'.esc_url(FORMLAYER_PRO_ASSETS_URL . '/img/' . $logo ).'" alt="'.esc_attr($name).'" style="width:48px; height:48px; object-fit:contain;"> </div>'; // Tag if(!empty($tag)){ echo '<span class="formlayer-int-tag">'.esc_html($tag).'</span>'; } echo '</div> <h3 class="formlayer-int-title">'.esc_html($name).'</h3> <p class="formlayer-int-desc">'.esc_html($desc ).'</p> <div class="formlayer-int-footer">'; // Button $all_settings = get_option('formlayer_integration_settings', []); $connected = !empty($all_settings[$slug]['enabled']); if($connected){ echo '<button class="formlayer-btn formlayer-btn-outline formlayer-configure-int" data-name="'.esc_attr($name).'" data-slug="'.esc_attr($slug).'">'.esc_html__('Connected', 'formlayer-pro').'</button>'; } else { echo '<button class="formlayer-btn formlayer-btn-action formlayer-configure-int" style="width: 100%;" data-name="'.esc_attr($name).'" data-slug="'.esc_attr($slug).'">'.esc_html__('Configure', 'formlayer-pro').'</button>'; } // Documentation link echo '<a href="'.esc_url($doc_url).'" class="formlayer-btn-link" target="_blank" rel="noopener noreferrer">'.esc_html__('Documentation', 'formlayer-pro').'</a>'; echo '</div> </div>'; } static function integrations(){ // Integration cards echo'<div class="formlayer-integrations-grid">'; self::render_int_card('Slack', __('Receive real-time notifications in your Slack channels whenever a form is submitted.', 'formlayer-pro'), 'slack-logo.png', 'slack', 'MOST POPULAR'); self::render_int_card('Google Sheets', __('Automatically sync every new entry to a specific spreadsheet. Perfect for reporting.', 'formlayer-pro'), 'sheets-logo.png', 'sheets'); self::render_int_card('Notion', __('Push form data into your Notion databases or create new pages automatically.', 'formlayer-pro'), 'notion-logo.png', 'notion'); self::render_int_card('Trello', __('Turn submissions into Trello cards. Ideal for lead management and support.', 'formlayer-pro'), 'trello-logo.png', 'trello'); self::render_int_card('Mailchimp', __('Subscribe users to your audience lists based on their form inputs.', 'formlayer-pro'), 'mailchimp-logo.png', 'mailchimp'); self::render_int_card('Discord', __('notifications Discord', 'formlayer-pro'), 'discord-logo.png', 'discord'); echo'</div>'; } static function render_form_integrations(){ echo '<div class="formlayer-pro-form-settings"> <div class="formlayer-settings-field"> <label>' . esc_html__('Active Integrations', 'formlayer-pro') . '</label> <p class="description" style="margin-bottom: 20px;">' . esc_html__('Enable and configure integrations for this specific form. Form settings override global settings.', 'formlayer-pro') . '</p> <div id="formlayer-active-integrations-container"> <!-- Slack --> <div class="formlayer-integration-setting-row" style="background:#f8fafc; border:1px solid #f1f5f9; border-radius:12px; padding:20px; margin-bottom:15px;"> <div style="display:flex; justify-content:space-between; align-items:center;"> <div style="display:flex; align-items:center; gap:12px;"> <img src="'.esc_url(FORMLAYER_PRO_ASSETS_URL . '/img/slack-logo.png').'" style="width:32px; height:32px;"> <span style="font-weight:700; font-size:16px;">Slack</span> </div> <label class="formlayer-switch"> <input type="checkbox" id="form-setting-int-slack-enabled"> <span class="slider round"></span> </label> </div> <div class="integration-row-content" id="slack-integration-fields" style="margin-top:20px; padding-top:20px; border-top:1px solid #edf2f7; display:none;"> <div class="formlayer-settings-field"> <label>' . esc_html__('Override Webhook URL', 'formlayer-pro') . '</label> <input type="text" id="form-setting-int-slack-webhook" class="formlayer-input" placeholder="Leave empty to use global webhook"> </div> </div> </div> <!-- Mailchimp --> <div class="formlayer-integration-setting-row" style="background:#f8fafc; border:1px solid #f1f5f9; border-radius:12px; padding:20px; margin-bottom:15px;"> <div style="display:flex; justify-content:space-between; align-items:center;"> <div style="display:flex; align-items:center; gap:12px;"> <img src="'.esc_url(FORMLAYER_PRO_ASSETS_URL . '/img/mailchimp-logo.png').'" style="width:32px; height:32px;"> <span style="font-weight:700; font-size:16px;">Mailchimp</span> </div> <label class="formlayer-switch"> <input type="checkbox" id="form-setting-int-mailchimp-enabled"> <span class="slider round"></span> </label> </div> <div class="integration-row-content" id="mailchimp-integration-fields" style="margin-top:20px; padding-top:20px; border-top:1px solid #edf2f7; display:none;"> <div class="formlayer-settings-field"> <label>' . esc_html__('Override Audience ID', 'formlayer-pro') . '</label> <input type="text" id="form-setting-int-mailchimp-list" class="formlayer-input" placeholder="Leave empty to use global list"> </div> </div> </div> <!-- Google Sheets --> <div class="formlayer-integration-setting-row" style="background:#f8fafc; border:1px solid #f1f5f9; border-radius:12px; padding:20px; margin-bottom:15px;"> <div style="display:flex; justify-content:space-between; align-items:center;"> <div style="display:flex; align-items:center; gap:12px;"> <img src="'.esc_url(FORMLAYER_PRO_ASSETS_URL . '/img/sheets-logo.png').'" style="width:32px; height:32px;"> <span style="font-weight:700; font-size:16px;">Google Sheets</span> </div> <label class="formlayer-switch"> <input type="checkbox" id="form-setting-int-sheets-enabled"> <span class="slider round"></span> </label> </div> <div class="integration-row-content" id="sheets-integration-fields" style="margin-top:20px; padding-top:20px; border-top:1px solid #edf2f7; display:none;"> <div class="formlayer-settings-field"> <label>' . esc_html__('Spreadsheet ID', 'formlayer-pro') . '</label> <input type="text" id="form-setting-int-sheets-id" class="formlayer-input" placeholder="e.g. 1a2b3c4d..."> </div> <div class="formlayer-settings-field" style="margin-top:15px;"> <label>' . esc_html__('Sheet Name', 'formlayer-pro') . '</label> <input type="text" id="form-setting-int-sheets-name" class="formlayer-input" placeholder="e.g. Sheet1"> </div> </div> </div> <!-- Notion --> <div class="formlayer-integration-setting-row" style="background:#f8fafc; border:1px solid #f1f5f9; border-radius:12px; padding:20px; margin-bottom:15px;"> <div style="display:flex; justify-content:space-between; align-items:center;"> <div style="display:flex; align-items:center; gap:12px;"> <img src="'.esc_url(FORMLAYER_PRO_ASSETS_URL . '/img/notion-logo.png').'" style="width:32px; height:32px;"> <span style="font-weight:700; font-size:16px;">Notion</span> </div> <label class="formlayer-switch"> <input type="checkbox" id="form-setting-int-notion-enabled"> <span class="slider round"></span> </label> </div> <div class="integration-row-content" id="notion-integration-fields" style="margin-top:20px; padding-top:20px; border-top:1px solid #edf2f7; display:none;"> <div class="formlayer-settings-field"> <label>' . esc_html__('Override Database ID', 'formlayer-pro') . '</label> <input type="text" id="form-setting-int-notion-db" class="formlayer-input" placeholder="Leave empty to use global database"> </div> </div> </div> <!-- Trello --> <div class="formlayer-integration-setting-row" style="background:#f8fafc; border:1px solid #f1f5f9; border-radius:12px; padding:20px; margin-bottom:15px;"> <div style="display:flex; justify-content:space-between; align-items:center;"> <div style="display:flex; align-items:center; gap:12px;"> <img src="'.esc_url(FORMLAYER_PRO_ASSETS_URL . '/img/trello-logo.png').'" style="width:32px; height:32px;"> <span style="font-weight:700; font-size:16px;">Trello</span> </div> <label class="formlayer-switch"> <input type="checkbox" id="form-setting-int-trello-enabled"> <span class="slider round"></span> </label> </div> <div class="integration-row-content" id="trello-integration-fields" style="margin-top:20px; padding-top:20px; border-top:1px solid #edf2f7; display:none;"> <div class="formlayer-settings-field"> <label>' . esc_html__('List ID', 'formlayer-pro') . '</label> <input type="text" id="form-setting-int-trello-list" class="formlayer-input" placeholder="Enter Trello List ID"> </div> </div> </div> <!-- Discord --> <div class="formlayer-integration-setting-row" style="background:#f8fafc; border:1px solid #f1f5f9; border-radius:12px; padding:20px; margin-bottom:15px;"> <div style="display:flex; justify-content:space-between; align-items:center;"> <div style="display:flex; align-items:center; gap:12px;"> <img src="'.esc_url(FORMLAYER_PRO_ASSETS_URL . '/img/discord-logo.png').'" style="width:32px; height:32px;"> <span style="font-weight:700; font-size:16px;">Discord</span> </div> <label class="formlayer-switch"> <input type="checkbox" id="form-setting-int-discord-enabled"> <span class="slider round"></span> </label> </div> <div class="integration-row-content" id="discord-integration-fields" style="margin-top:20px; padding-top:20px; border-top:1px solid #edf2f7; display:none;"> <div class="formlayer-settings-field"> <label>' . esc_html__('Override Webhook URL', 'formlayer-pro') . '</label> <input type="text" id="form-setting-int-discord-webhook" class="formlayer-input" placeholder="Leave empty to use global webhook"> </div> </div> </div> </div> </div> </div>'; } static function render_modal(){ echo '<div id="formlayer-integration-modal" class="formlayer-modal-overlay" style="display:none;"> <div class="formlayer-modal-content" style="max-width: 600px;"> <div class="formlayer-modal-header" style="border-bottom: 1px solid #f1f5f9; padding-bottom: 20px; margin-bottom: 25px; display: flex; justify-content: space-between; align-items: center;"> <div> <h3 id="int-modal-title" style="margin: 0; font-size: 22px; font-weight: 700; color: #1e293b;">' . esc_html__('Configure Integration', 'formlayer-pro') . '</h3> <p id="int-modal-desc" style="margin: 6px 0 0 0; font-size: 14px; color: #64748b;">' . esc_html__('Enter your credentials to connect.', 'formlayer-pro') . '</p> </div> </div> <div id="int-settings-fields" class="formlayer-settings-body"> <!-- Fields will be injected here via JS --> </div> <div class="formlayer-modal-footer" style="margin-top: 30px; padding-top: 25px; border-top: 1px solid #f1f5f9; display: flex; justify-content: flex-end; gap: 12px;"> <button class="formlayer-btn formlayer-btn-outline" id="close-int-modal">' . esc_html__('Cancel', 'formlayer-pro') . '</button> <button class="formlayer-btn formlayer-btn-primary" id="save-int-settings">' . esc_html__('Save & Connect', 'formlayer-pro') . '</button> </div> </div> </div>'; } static function turnstile($settings){ echo'<div class="pane-header"> <h4 style="margin: 0; font-size: 15px;">Cloudflare Turnstile Configuration</h4> <p>' . esc_html__('Cloudflare Turnstile provides a seamless, non-intrusive CAPTCHA experience. Get your keys from the Cloudflare Dashboard.', 'formlayer-pro') . '</p> </div> <div class="formlayer-setting-row-v"> <label>' . esc_html__('Site Key', 'formlayer-pro') . '</label> <input type="text" name="captcha_t_site_key" class="formlayer-input" value="' . esc_attr($settings['captcha_t_site_key']) . '" placeholder="Enter your Turnstile site key"> </div> <div class="formlayer-setting-row-v"> <label>' . esc_html__('Secret Key', 'formlayer-pro') . '</label> <input type="password" name="captcha_t_secret_key" class="formlayer-input" value="' . esc_attr($settings['captcha_t_secret_key']) . '" placeholder="••••••••••••••••"> </div> <div class="formlayer-setting-row-v"> <label>' . esc_html__('Default Theme', 'formlayer-pro') . '</label> <select name="captcha_t_theme" class="formlayer-select"> <option value="light" ' . selected($settings['captcha_t_theme'], 'light', false) . '>Light</option> <option value="dark" ' . selected($settings['captcha_t_theme'], 'dark', false) . '>Dark</option> </select> </div>'; } static function recaptcha($settings){ echo'<div class="pane-header"> <h4 style="margin: 0; font-size: 15px;">Google reCAPTCHA Configuration</h4> <p>' . esc_html__('Google reCAPTCHA is a widely used spam protection service. Use either v2 keys here.', 'formlayer-pro') . '</p> </div> <div class="formlayer-setting-row-v"> <label>' . esc_html__('reCAPTCHA Site Key', 'formlayer-pro') . '</label> <input type="text" name="captcha_r_site_key" class="formlayer-input" value="' . esc_attr($settings['captcha_r_site_key']) . '"> </div> <div class="formlayer-setting-row-v"> <label>' . esc_html__('reCAPTCHA Secret Key', 'formlayer-pro') . '</label> <input type="password" name="captcha_r_secret_key" class="formlayer-input" value="' . esc_attr($settings['captcha_r_secret_key']) . '"> </div> <div class="formlayer-setting-row-v"> <label>' . esc_html__('Default Theme', 'formlayer-pro') . '</label> <select name="captcha_r_theme" class="formlayer-select"> <option value="light" ' . selected($settings['captcha_r_theme'], 'light', false) . '>Light</option> <option value="dark" ' . selected($settings['captcha_r_theme'], 'dark', false) . '>Dark</option> </select> </div>'; } static function tools(){ $forms = get_posts([ 'post_type' => 'formlayer_form', 'posts_per_page' => -1, 'post_status' => 'any' ]); $checkboxes_html = ''; foreach($forms as $form){ $display_id = get_post_meta($form->ID, '_formlayer_display_id', true); $display_id = $display_id ? $display_id : $form->ID; $checkboxes_html .= ' <label class="formlayer-export-form-checkbox-label" style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; background: #fff; border: 1px solid #e2e8f0; border-radius: 6px; cursor: pointer; user-select: none; transition: all 0.2s;"> <input type="checkbox" class="formlayer-export-form-checkbox" value="' . esc_attr($form->ID) . '" style="margin: 0; width: 16px; height: 16px; accent-color: #3b82f6;"> <span style="font-weight: 600; color: #334155; font-size: 13px;">' . esc_html(get_the_title($form->ID)) . '</span> <span style="color: #64748b; font-size: 11px; margin-left: auto; background: #f1f5f9; padding: 2px 6px; border-radius: 4px;">ID: #' . esc_html($display_id) . '</span> </label>'; } echo '<div class="formlayer-transfer-view"> <div style="grid-template-columns: 1fr 1fr; gap: 30px;"> <!-- Export Card --> <div class="formlayer-settings-card"> <div class="formlayer-settings-header"> <div style="display: flex; align-items: center; gap: 12px;"> <div style="background: #eff6ff; color: #3b82f6; width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center;"> <span class="dashicons dashicons-external"></span> </div> <div> <h3 style="margin: 0; font-size: 18px; font-weight: 700;">' . esc_html__('Export Forms', 'formlayer-pro') . '</h3> <p style="margin: 4px 0 0 0; font-size: 13px; color: var(--formlayer-text-muted);">' . esc_html__('Download your form configurations as a JSON file.', 'formlayer-pro') . '</p> </div> </div> </div> <div class="formlayer-settings-body" style="padding: 24px 32px 32px 32px;"> <div class="formlayer-setting-row-v" style="display: block;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> <label style="font-weight: 600; font-size: 14px; color: #334155; margin: 0;">' . esc_html__('Select Forms to Export', 'formlayer-pro') . '</label> <div style="display: flex; gap: 8px;"> <button type="button" class="formlayer-export-select-all button button-small" style="font-size: 11px; height: 26px; line-height: 24px;">' . esc_html__('Select All', 'formlayer-pro') . '</button> <button type="button" class="formlayer-export-deselect-all button button-small" style="font-size: 11px; height: 26px; line-height: 24px;">' . esc_html__('Clear', 'formlayer-pro') . '</button> </div> </div> <div class="formlayer-export-forms-grid" style="max-height: 200px; overflow-y: auto; border: 1px solid #cbd5e1; border-radius: 8px; padding: 12px; background: #fafafa; display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px;"> ' . $checkboxes_html . ' </div> <p class="description">' . esc_html__('Select individual forms using the checkboxes above. If no forms are selected, all forms will be exported by default.', 'formlayer-pro') . '</p> </div> <div style="margin-top: 24px;"> <button id="formlayer-btn-export-forms" class="formlayer-btn formlayer-btn-primary" style="width: 100%; justify-content: center; height: 42px;"> <span class="dashicons dashicons-download" style="font-size: 18px; margin-top: 2px;"></span> ' . esc_html__('Export Selected Forms', 'formlayer-pro') . ' </button> </div> </div> </div> <!-- Import Card --> <div class="formlayer-settings-card"> <div class="formlayer-settings-header"> <div style="display: flex; align-items: center; gap: 12px;"> <div style="background: #f0fdf4; color: #22c55e; width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center;"> <span class="dashicons dashicons-upload"></span> </div> <div> <h3 style="margin: 0; font-size: 18px; font-weight: 700;">' . esc_html__('Import Forms', 'formlayer-pro') . '</h3> <p style="margin: 4px 0 0 0; font-size: 13px; color: var(--formlayer-text-muted);">' . esc_html__('Upload a FormLayer JSON file to import forms.', 'formlayer-pro') . '</p> </div> </div> </div> <div class="formlayer-settings-body" style="padding: 24px 32px 32px 32px;"> <div class="formlayer-import-dropzone" style="border: 2px dashed #e2e8f0; border-radius: 12px; padding: 40px 20px; text-align: center; background: #f8fafc; cursor: pointer; transition: all 0.2s;" onclick="document.getElementById(\'formlayer-import-file\').click()"> <span class="dashicons dashicons-cloud-upload" style="font-size: 48px; width: 48px; height: 48px; color: #94a3b8; margin-bottom: 12px;"></span> <h4 style="margin: 0; font-size: 15px; color: #475569;">' . esc_html__('Click to browse or drag & drop JSON file', 'formlayer-pro') . '</h4> <p style="margin: 8px 0 0 0; font-size: 12px; color: #94a3b8;">' . esc_html__('Only .json files exported from FormLayer are supported.', 'formlayer-pro') . '</p> <input type="file" id="formlayer-import-file" style="display: none;" accept=".json"> </div> <div id="formlayer-import-file-info" style="margin-top: 15px; display: none; align-items: center; gap: 8px; color: #475569; font-size: 13px; background: #eff6ff; padding: 10px 15px; border-radius: 8px;"> <span class="dashicons dashicons-media-text" style="color: #3b82f6;"></span> <span id="formlayer-import-filename"></span> <span class="dashicons dashicons-no-alt" id="formlayer-import-remove" style="margin-left: auto; cursor: pointer; color: #ef4444;" title="' . esc_attr__('Remove', 'formlayer-pro') . '"></span> </div> <div style="margin-top: 24px;"> <button id="formlayer-btn-import-forms" class="formlayer-btn formlayer-btn-action" style="width: 100%; justify-content: center; height: 42px;" disabled> <span class="dashicons dashicons-migrate" style="font-size: 18px; margin-top: 2px;"></span> ' . esc_html__('Import Forms Now', 'formlayer-pro') . ' </button> </div> <div id="formlayer-import-status" style="margin-top: 15px;"></div> </div> </div> </div> </div>'; } static function entries(){ global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $total_entries = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}formlayer_entries"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $today_entries = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}formlayer_entries WHERE DATE(created_at) = CURDATE()"); $forms = get_posts([ 'post_type' => 'formlayer_form', 'posts_per_page' => -1, 'post_status' => 'any' ]); $page = 1; $per_page = 10; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $total_entries = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}formlayer_entries"); $total_pages = ceil($total_entries / $per_page); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $recent_entries = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}formlayer_entries ORDER BY created_at DESC LIMIT 10"); echo '<div class="formlayer-entries-view"> <div class="formlayer-entries-header" style="margin-bottom: 24px;"> <div class="formlayer-entries-filter-bar"> <div class="formlayer-entries-filter-left"> <div class="formlayer-search-wrap formlayer-entries-search-wrapper"> <span class="dashicons dashicons-search formlayer-entries-search-icon"></span> <input type="text" id="formlayer-entries-search" class="formlayer-entries-search-input-el" placeholder="' . esc_attr__('Search entries...', 'formlayer-pro') . '"> </div> <select id="formlayer-entries-filter-form" class="formlayer-select formlayer-select-compact"> <option value="">' . esc_html__('All Forms', 'formlayer-pro') . '</option>'; foreach($forms as $form){ echo '<option value="' . esc_attr($form->ID) . '">' . esc_html(get_the_title($form->ID)) . '</option>'; } echo'</select> <select id="formlayer-entries-filter-status" class="formlayer-select formlayer-select-compact"> <option value="">' . esc_html__('All Status', 'formlayer-pro') . '</option> <option value="read">' . esc_html__('Read', 'formlayer-pro') . '</option> <option value="unread">' . esc_html__('Unread', 'formlayer-pro') . '</option> </select> </div> <div style="display: flex; gap: 12px;"> <button id="formlayer-btn-export-entries" class="formlayer-btn formlayer-btn-outline formlayer-export-btn"> <span class="dashicons dashicons-migrate" style="font-size: 16px; margin-top: 2px;"></span> ' . esc_html__('Export (CSV)', 'formlayer-pro') . ' </button> </div> </div> </div>'; echo '<div class="formlayer-table-card formlayer-entries-table-card"> <div class="formlayer-entries-table-actions"> <select id="formlayer-entries-bulk-action" class="formlayer-select formlayer-select-compact" style="min-width: 140px;"> <option value="">' . esc_html__('Bulk Actions', 'formlayer-pro') . '</option> <option value="mark_read">' . esc_html__('Mark as Read', 'formlayer-pro') . '</option> <option value="mark_unread">' . esc_html__('Mark as Unread', 'formlayer-pro') . '</option> <option value="delete">' . esc_html__('Delete Permanently', 'formlayer-pro') . '</option> </select> <button id="formlayer-entries-apply-bulk" class="formlayer-btn formlayer-btn-outline" style="height: 34px; padding: 0 15px; font-size: 13px;">' . esc_html__('Apply', 'formlayer-pro') . '</button> </div> <div style="padding: 30px;"> <table class="formlayer-table"> <thead> <tr> <th style="width: 40px;"><input type="checkbox" id="formlayer-entries-select-all"></th> <th>' . esc_html__('ID', 'formlayer-pro') . '</th> <th>' . esc_html__('Status', 'formlayer-pro') . '</th> <th>' . esc_html__('Form Name', 'formlayer-pro') . '</th> <th>' . esc_html__('Submited At', 'formlayer-pro') . '</th> <th style="text-align: right; padding-right: 32px;">' . esc_html__('Actions', 'formlayer-pro') . '</th> </tr> </thead> <tbody id="formlayer-entries-tbody">'; if (empty($recent_entries)) { echo '<tr><td colspan="6" style="text-align:center; padding:80px 0; color:var(--formlayer-text-muted);"> <div style="font-size: 40px; margin-bottom: 20px;">📂</div> <div style="font-weight: 600; font-size: 16px;">' . esc_html__('No submissions found', 'formlayer-pro') . '</div> <p>' . esc_html__('Wait for your first form submission to see the data here.', 'formlayer-pro') . '</p> </td></tr>'; } else { foreach ($recent_entries as $entry) { $form = get_post($entry->form_id); $form_title = $form ? get_the_title($form->ID) : 'Unknown Form'; $data_raw = $entry->data; $data = json_decode($data_raw, true); if ($data === null && !empty($data_raw)) { $data = json_decode(stripslashes($data_raw), true); } $field_labels = \FormLayer\Util::get_form_field_labels($entry->form_id); $summary = []; if (is_array($data)) { foreach (array_slice($data, 0, 6) as $k => $v) { if (empty($v) || $k === '__source_url') { continue; } $label = isset($field_labels[$k]) ? $field_labels[$k] : ucfirst(str_replace(['field_', '_'], ['', ' '], $k)); if(is_array($v)){ $v = implode(', ', array_map('strval', $v)); } $summary[] = '<strong>' . esc_html($label) . ':</strong> ' . esc_html(mb_strimwidth(wp_strip_all_tags($v), 0, 40, '...')); } } if(empty($summary)){ $data_html = '<span style="color:#94a3b8; font-style:italic;">' . esc_html__('No displayable data', 'formlayer-pro') . '</span>'; if (!empty($data_raw)) { $data_html = esc_html(mb_strimwidth(wp_strip_all_tags($data_raw), 0, 100, '...')); } } else { $data_html = implode(' <span style="color:#e2e8f0; margin:0 4px;">|</span> ', $summary); } $status_class = !empty($entry->status) ? $entry->status : 'unread'; $status_label = ucfirst($status_class); echo'<tr data-entry-id="' . esc_attr($entry->id) . '" class="entry-row-' . esc_attr($status_class) . '"> <td><input type="checkbox" class="entry-cb" value="' . esc_attr($entry->id) . '"></td> <td style="color: #64748b; font-weight: 500;">#' . esc_html($entry->id) . '</td> <td><span class="formlayer-badge status-' . esc_attr($status_class) . '">' . esc_html($status_label) . '</span></td> <td style="font-weight: 600;">' . esc_html($form_title) . '</td> <td style="color: #64748b; font-size: 13px;">' . esc_html(gmdate('M j, Y h:i A', strtotime($entry->created_at))) . '</td> <td style="text-align: right; padding-right: 32px;"> <div class="formlayer-entry-row-actions"> <button class="formlayer-toggle-status" data-entry-id="' . esc_attr($entry->id) . '" data-status="' . ($status_class === 'read' ? 'unread' : 'read') . '" title="Mark as ' . ($status_class === 'read' ? 'Unread' : 'Read') . '" style="background: none; border: none; color: ' . ($status_class === 'read' ? '#94a3b8' : 'var(--fl-primary)') . '; cursor: pointer; transition: color 0.2s;"> <span class="dashicons dashicons-' . ($status_class === 'read' ? 'marker' : 'email-alt') . '"></span> </button> <button class="formlayer-view-entry" data-entry-id="' . esc_attr($entry->id) . '" title="View Details" style="background: none; border: none; color: #94a3b8; cursor: pointer; transition: color 0.2s;"> <span class="dashicons dashicons-visibility"></span> </button> <button class="formlayer-delete-entry" data-entry-id="' . esc_attr($entry->id) . '" title="Delete" style="background: none; border: none; color: #94a3b8; cursor: pointer; transition: color 0.2s;"> <span class="dashicons dashicons-trash"></span> </button> </div> </td> </tr>'; } } echo '</tbody> </table> </div> <div class="formlayer-table-footer formlayer-table-footer-wrap"> <div class="formlayer-pagination-info" style="color: #64748b; font-size: 13px;"> Showing <span id="formlayer-entries-count-current">' . count($recent_entries) . '</span> of <span id="formlayer-entries-total">' . intval($total_entries) . '</span> entries </div> <div class="formlayer-pagination-controls" data-total-pages="'.esc_html($total_pages).'" style="display: flex; gap: 8px;"> <button id="formlayer-pagination-prev" class="formlayer-btn formlayer-btn-outline" style="padding: 0 12px; height: 32px;" disabled><span class="dashicons dashicons-arrow-left-alt2"></span> Prev</button> <button id="formlayer-pagination-next" class="formlayer-btn formlayer-btn-outline" style="padding: 0 12px; height: 32px;" ' . ($total_pages <= 1 ? 'disabled' : '') . '>Next <span class="dashicons dashicons-arrow-right-alt2"></span></button> </div> </div> </div> </div>'; } static function reports(){ global $wpdb; $forms = get_posts([ 'post_type' => 'formlayer_form', 'posts_per_page' => -1, 'post_status' => 'any' ]); echo '<div class="formlayer-reports-view"> <!-- Consistent Filter Bar Layout --> <div class="formlayer-reports-filter-bar" style="margin-bottom: 24px;"> <div class="formlayer-reports-filter-left" style="display: flex; align-items: center; gap: 15px;"> <span class="dashicons dashicons-filter" style="color: var(--formlayer-text-muted); font-size: 18px; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center;"></span> <select id="formlayer-reports-filter-form" class="formlayer-select formlayer-select-compact" style="min-width: 200px; height: 38px;"> <option value="">' . esc_html__('All Forms', 'formlayer-pro') . '</option>'; foreach($forms as $form){ echo '<option value="' . esc_attr($form->ID) . '">' . esc_html(get_the_title($form->ID)) . '</option>'; } echo '</select> <select id="formlayer-reports-filter-range" class="formlayer-select formlayer-select-compact" style="min-width: 150px; height: 38px;"> <option value="7">' . esc_html__('Last 7 Days', 'formlayer-pro') . '</option> <option value="30" selected>' . esc_html__('Last 30 Days', 'formlayer-pro') . '</option> <option value="90">' . esc_html__('Last 90 Days', 'formlayer-pro') . '</option> <option value="0">' . esc_html__('All Time', 'formlayer-pro') . '</option> </select> </div> </div> <!-- Stat Cards --> <div class="formlayer-stats-grid" style="margin-bottom:24px;"> <div class="formlayer-stat-card stat-total"> <div class="formlayer-stat-icon"><span class="dashicons dashicons-email-alt"></span></div> <div> <span class="formlayer-stat-label">' . esc_html__('Total Submissions', 'formlayer-pro') . '</span> <span class="formlayer-stat-value" id="reports-stat-total">0</span> </div> </div> <div class="formlayer-stat-card stat-unread"> <div class="formlayer-stat-icon"><span class="dashicons dashicons-warning"></span></div> <div> <span class="formlayer-stat-label">' . esc_html__('Unread Entries', 'formlayer-pro') . '</span> <span class="formlayer-stat-value" id="reports-stat-unread">0</span> </div> </div> <div class="formlayer-stat-card stat-read"> <div class="formlayer-stat-icon"><span class="dashicons dashicons-yes-alt"></span></div> <div> <span class="formlayer-stat-label">' . esc_html__('Read Entries', 'formlayer-pro') . '</span> <span class="formlayer-stat-value" id="reports-stat-read">0</span> </div> </div> <div class="formlayer-stat-card stat-conversion"> <div class="formlayer-stat-icon"><span class="dashicons dashicons-chart-line"></span></div> <div> <span class="formlayer-stat-label">' . esc_html__('Conversion Rate', 'formlayer-pro') . '</span> <span class="formlayer-stat-value" id="reports-stat-conversion">0%</span> </div> </div> </div> <!-- Row 1: Trend + Device --> <div class="formlayer-reports-charts-grid" style="margin-bottom:24px;"> <div class="formlayer-reports-chart-card"> <div class="formlayer-reports-chart-card-header"> <h3 class="formlayer-reports-chart-card-title"> <span class="dashicons dashicons-chart-line" style="color:var(--formlayer-primary);"></span> ' . esc_html__('Submission Trend', 'formlayer-pro') . ' </h3> <div class="formlayer-trend-tabs"> <button class="formlayer-trend-tab active" data-mode="daily">' . esc_html__('Daily', 'formlayer-pro') . '</button> <button class="formlayer-trend-tab" data-mode="weekly">' . esc_html__('Weekly', 'formlayer-pro') . '</button> <button class="formlayer-trend-tab" data-mode="monthly">' . esc_html__('Monthly', 'formlayer-pro') . '</button> </div> </div> <div class="formlayer-reports-chart-container"><canvas id="reports-chart-trend"></canvas></div> </div> <div class="formlayer-reports-chart-card"> <h3 class="formlayer-reports-chart-card-title"> <span class="dashicons dashicons-smartphone" style="color:var(--formlayer-primary);"></span> ' . esc_html__('Device Type', 'formlayer-pro') . ' </h3> <div class="formlayer-reports-chart-container" style="height:200px;"><canvas id="reports-chart-device"></canvas></div> <div id="reports-device-legend" class="formlayer-device-legend"></div> </div> </div> <div class="formlayer-reports-charts-grid" style="margin-bottom:24px;"> <div class="formlayer-reports-chart-card"> <h3 class="formlayer-reports-chart-card-title"> <span class="dashicons dashicons-forms" style="color:var(--formlayer-primary);"></span>' . esc_html__('Top Performing Forms', 'formlayer-pro') . ' </h3> <div class="formlayer-reports-chart-container"><canvas id="reports-chart-form"></canvas></div> </div> <div class="formlayer-reports-chart-card"> <h3 class="formlayer-reports-chart-card-title"> <span class="dashicons dashicons-calendar-alt" style="color:var(--formlayer-primary);"></span> ' . esc_html__('Submission Heatmap', 'formlayer-pro') . ' </h3> <p style="font-size:12px;color:#94a3b8;margin:-10px 0 14px;">' . esc_html__('Peak engagement days & hours', 'formlayer-pro') . '</p> <div id="reports-heatmap-container" class="formlayer-heatmap-wrap"></div> </div> </div> <!-- Row 4: Form Performance Table --> <div class="formlayer-reports-chart-card" style="margin-bottom:24px;"> <h3 class="formlayer-reports-chart-card-title"> <span class="dashicons dashicons-editor-table" style="color:var(--formlayer-primary);"></span> ' . esc_html__('Form Performance', 'formlayer-pro') . ' </h3> <div style="overflow-x:auto;"> <table class="formlayer-table formlayer-perf-table"> <thead><tr> <th>' . esc_html__('Form', 'formlayer-pro') . '</th> <th>' . esc_html__('Views (est.)', 'formlayer-pro') . '</th> <th>' . esc_html__('Submissions', 'formlayer-pro') . '</th> <th>' . esc_html__('Conversion', 'formlayer-pro') . '</th> <th style="min-width:120px;">' . esc_html__('Rate Bar', 'formlayer-pro') . '</th> </tr></thead> <tbody id="reports-form-table-body"> <tr><td colspan="5" style="text-align:center;padding:30px;color:#94a3b8;">' . esc_html__('Loading…', 'formlayer-pro') . '</td></tr> </tbody> </table> </div> </div> </div>'; } static function email_confirmation_section(){ echo '<!-- Email Confirmation Section --> <div class="formlayer-settings-field"> <label>' . esc_html__('Enabled', 'formlayer-pro') . '</label> <div class="formlayer-switch-wrapper"> <label class="formlayer-switch"> <input type="checkbox" id="form-setting-email-conf-enabled"> <span class="slider round"></span> </label> </div> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> <div class="formlayer-settings-field"> <label>' . esc_html__('Send To Email Field', 'formlayer-pro') . '</label> <input type="text" id="form-setting-email-conf-email" class="formlayer-input" placeholder="e.g. {email}"> </div> <div class="formlayer-settings-field"> <label>' . esc_html__('Reply To', 'formlayer-pro') . '</label> <input type="text" id="form-setting-email-conf-replyto" class="formlayer-input" placeholder="{admin_email}"> </div> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> <div class="formlayer-settings-field"> <label>' . esc_html__('From Name', 'formlayer-pro') . '</label> <input type="text" id="form-setting-email-conf-fromname" class="formlayer-input" placeholder="FormLayer"> </div> <div class="formlayer-settings-field"> <label>' . esc_html__('From Email', 'formlayer-pro') . '</label> <input type="text" id="form-setting-email-conf-fromemail" class="formlayer-input" placeholder="{admin_email}"> </div> </div> <div class="formlayer-settings-field"> <label>' . esc_html__('BCC', 'formlayer-pro') . '</label> <input type="text" id="form-setting-email-conf-bcc" class="formlayer-input" placeholder="comma separated emails"> </div> <div class="formlayer-settings-field"> <label>' . esc_html__('Subject', 'formlayer-pro') . '</label> <input type="text" id="form-setting-email-conf-subject" class="formlayer-input" placeholder="Thank you for your submission!"> </div> <div class="formlayer-settings-field"> <label>' . esc_html__('Message Format', 'formlayer-pro') . '</label> <select id="form-setting-email-conf-format" class="formlayer-select"> <option value="html">HTML (Recommended)</option> <option value="plain">Plain Text</option> </select> </div> <div class="formlayer-settings-field"> <label style="display:flex; justify-content:space-between;"> <span>' . esc_html__('Message Body', 'formlayer-pro') . '</span> </label> <textarea id="form-setting-email-conf-message" class="formlayer-input" style="height:120px;"></textarea> <div class="formlayer-merge-tags-wrapper" style="margin-top: 10px; background: #f8fafc; padding: 10px; border-radius: 6px; border: 1px solid #e2e8f0;"> <div style="font-size: 12px; font-weight: 600; margin-bottom: 8px; color: #475569;">Available Merge Tags (Click to insert)</div> <div id="formlayer-email-conf-dynamic-merge-tags" style="display: flex; flex-wrap: wrap; gap: 6px;"></div> </div> </div>'; } }
💾 Save Changes
❌ Cancel