diff --git a/CHANGELOG.md b/CHANGELOG.md index 0129999..35424d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,44 @@ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) β versi ## [Unreleased] +### Changed β Leave Feedback form (more options, multi-select, wired to email) +The right-column "Leave Feedback" form on the About page has been +expanded from two radio buttons to **seven checkboxes** (users can +pick more than one), a new optional message textarea, and a submit +button that **actually does something** β it AJAX-posts to a new +WP handler that emails the site admin via `wp_mail()`. + +**Form options (checkboxes β multi-select):** +- I have ideas to improve this plugin +- I need help with this plugin +- I found a bug +- I'd like to request a new feature +- I'd like to share my use case +- Just saying thanks π +- Other + +**Submission flow:** +1. Client-side: at least one checkbox OR a message is required; + otherwise an inline hint shows. +2. AJAX POST `wp_notes_submit_feedback` with topics[] + message + + nonce. +3. Server-side handler (`manage_options` capability + nonce checked) + sanitizes input, allow-lists the topic keys, then builds a plain- + text email and ships it to `get_option('admin_email')` via + `wp_mail()`. Reply-To is set to the submitting user's email so + the admin can reply directly. +4. Email body includes: sender (display name + email + WP login), + site URL, plugin version, the checked topics (pretty-labelled), + and the message. +5. Inline success message replaces the form on success; inline + error message lets the user retry on failure. + +The old radio-button + broken `toggleSection('feedback-form-...')` +logic that pointed at non-existent IDs has been replaced entirely. +The `toggleSection()` helper is kept defined but is now genuinely +unused on the About page β flagged for removal in a future Tier-2 +pass. + ### Changed β About page rewritten (content + layout) The About page (`Settings β WP Notes β About`) has been rewritten from "wall of nested toggle boxes with outdated content" to diff --git a/inc/wp-notes-about.php b/inc/wp-notes-about.php index c811934..c77d22d 100644 --- a/inc/wp-notes-about.php +++ b/inc/wp-notes-about.php @@ -164,9 +164,24 @@ function wp_notes_about_page() {
Thanks β your feedback has been sent. π
'; + } else { + statusEl.textContent = (res && res.data) ? String(res.data) : 'Sorry, something went wrong. Please try again.'; + statusEl.style.color = '#8a2424'; + btn.disabled = false; + btn.value = 'Submit Feedback'; + } + }) + .catch(function () { + statusEl.textContent = 'Network error β please try again in a moment.'; + statusEl.style.color = '#8a2424'; + btn.disabled = false; + btn.value = 'Submit Feedback'; + }); }); "; } +// Receive the "Leave Feedback" form from the About page and forward +// it to the site admin via wp_mail(). Topics is an array of short +// keys (improve / help / bug / feature / use-case / thanks / other); +// message is an optional free-text textarea. Sender info is taken +// from wp_get_current_user() so we never trust client-supplied +// identity. Capability-gated to manage_options because the About +// page is admin-only. +add_action('wp_ajax_wp_notes_submit_feedback', 'wp_notes_ajax_submit_feedback'); +function wp_notes_ajax_submit_feedback() { + if (!current_user_can('manage_options')) { + wp_send_json_error('Insufficient permissions.', 403); + } + check_ajax_referer('wp_notes_feedback_submit', 'nonce'); + + $allowed_topics = ['improve', 'help', 'bug', 'feature', 'use-case', 'thanks', 'other']; + $raw_topics = isset($_POST['topics']) && is_array($_POST['topics']) ? wp_unslash($_POST['topics']) : []; + $topics = array_values(array_intersect($allowed_topics, array_map('sanitize_key', $raw_topics))); + + $message = isset($_POST['message']) ? sanitize_textarea_field(wp_unslash($_POST['message'])) : ''; + + if (empty($topics) && $message === '') { + wp_send_json_error('Pick at least one topic or write a message.', 400); + } + + $user = wp_get_current_user(); + $site = get_bloginfo('name'); + $to = get_option('admin_email'); + + $topic_labels = [ + 'improve' => 'Ideas to improve the plugin', + 'help' => 'Needs help with the plugin', + 'bug' => 'Reporting a bug', + 'feature' => 'New feature request', + 'use-case' => 'Sharing a use case', + 'thanks' => 'Saying thanks', + 'other' => 'Other', + ]; + $topics_pretty = array_map(function ($t) use ($topic_labels) { return $topic_labels[$t] ?? $t; }, $topics); + + $subject = sprintf('[%s] WP Notes feedback from %s', $site, $user->display_name ?: $user->user_login); + $body = "Feedback received via WP Notes β About page\n"; + $body .= str_repeat('-', 48) . "\n\n"; + $body .= 'From: ' . ($user->display_name ?: $user->user_login) . ' <' . $user->user_email . ">\n"; + $body .= 'Site: ' . home_url() . "\n"; + $body .= 'Plugin: v' . WP_NOTES_VERSION . "\n\n"; + $body .= "Topics:\n"; + if (!empty($topics_pretty)) { + foreach ($topics_pretty as $label) { $body .= ' - ' . $label . "\n"; } + } else { + $body .= " (none selected)\n"; + } + $body .= "\nMessage:\n"; + $body .= $message !== '' ? $message . "\n" : "(no message provided)\n"; + + $headers = [ + 'Content-Type: text/plain; charset=UTF-8', + 'Reply-To: ' . sanitize_email($user->user_email), + ]; + + $sent = wp_mail($to, $subject, $body, $headers); + + if (!$sent) { + wp_send_json_error('Email could not be sent. Check the site mail configuration.', 500); + } + + wp_send_json_success(['delivered_to' => $to]); +} + // Persist a user's dismissal of the "No active/completed notes found" // empty-state notice so it doesn't reappear on the next page load. // Triggered by inline JS in wp_notes_add_inline_scripts() when the