diff --git a/assets/src/js/admin/main.js b/assets/src/js/admin/main.js index 0a524314..ce133e77 100644 --- a/assets/src/js/admin/main.js +++ b/assets/src/js/admin/main.js @@ -72,6 +72,11 @@ document.addEventListener('DOMContentLoaded', () => { this.stepElems[i].addEventListener('click', this.saveOptionOnNext); } } + + /** + * Run once on pageload. + */ + this.showMessages(); }, /** @@ -121,63 +126,7 @@ document.addEventListener('DOMContentLoaded', () => { form.append('is_list', button.dataset.list); form.append('_nonce', plausible.nonce); - let result = plausible.ajax(form, null); - - result.then(function (response) { - if (response.success === false) { - plausible.toggleOption(e, false); - - return; - } - - let is_wizard = document.getElementById('plausible-analytics-wizard'); - - if (is_wizard !== null) { - return; - } - - if (response.additional !== undefined) { - plausible.renderAdditionalMessages(response.additional, e.target); - } else { - plausible.removeAdditionalMessage(e.target); - } - }); - }, - - /** - * Renders a HTML box containing additional information about the enabled option. - * - * @param html - * @param target - */ - renderAdditionalMessages: function (html, target) { - let container = target.closest('.plausible-analytics-group'); - - container.innerHTML += html; - }, - - /** - * Removes the additional information box when the option is disabled. - * - * @param target - */ - removeAdditionalMessage: function (target) { - let container = target.closest('.plausible-analytics-group'); - let additionalMessage; - - if (container.children.length > 0) { - for (let i = 0; i < container.children.length; i++) { - if (container.children[i].classList.contains('plausible-analytics-hook')) { - additionalMessage = container.children[i]; - - break; - } - } - } - - if (additionalMessage !== undefined) { - container.removeChild(additionalMessage); - } + plausible.ajax(form); }, /** @@ -203,7 +152,7 @@ document.addEventListener('DOMContentLoaded', () => { button.children[0].classList.remove('hidden'); button.setAttribute('disabled', 'disabled'); - plausible.ajax(form, button, null); + plausible.ajax(form, button); }, /** @@ -228,7 +177,7 @@ document.addEventListener('DOMContentLoaded', () => { data.append('options', JSON.stringify(options)); data.append('_nonce', plausible.nonce); - plausible.ajax(data, null, false); + plausible.ajax(data); } }, @@ -296,7 +245,7 @@ document.addEventListener('DOMContentLoaded', () => { data.append('action', 'plausible_analytics_show_wizard'); data.append('_nonce', e.target.dataset.nonce); - plausible.ajax(data, null); + plausible.ajax(data); }, /** @@ -364,14 +313,15 @@ document.addEventListener('DOMContentLoaded', () => { }, /** - * Do AJAX request and (optionally) show a notice or (optionally) reload the page. + * Do AJAX request. * * @param data * @param button + * @param showMessages * * @return object */ - ajax: function (data, button = null) { + ajax: function (data, button = null, showMessages = true) { return fetch( ajaxurl, { @@ -390,14 +340,8 @@ document.addEventListener('DOMContentLoaded', () => { return false; }).then(response => { - if (response.success === true) { - if (response.data !== undefined && response.data.message !== undefined) { - plausible.notice(response.data.message); - } - } else { - if (response.data !== undefined && response.data.message !== undefined) { - plausible.notice(response.data.message, true); - } + if (showMessages === true) { + plausible.showMessages(); } let event = new CustomEvent('plausibleAjaxDone', {detail: response}); @@ -408,19 +352,66 @@ document.addEventListener('DOMContentLoaded', () => { }); }, + /** + * Show messages on screen. + */ + showMessages: function () { + let messages = plausible.fetchMessages(); + + messages.then(function (messages) { + if (messages.error !== false) { + plausible.showMessage(messages.error, 'error'); + } else if (messages.notice !== false) { + plausible.showMessage(messages.notice, 'notice'); + } else if (messages.success !== false) { + plausible.showMessage(messages.success, 'success'); + } + + if (messages.additional.length === 0) { + return; + } + + if (messages.additional.id !== undefined && messages.additional.message) { + plausible.showAdditionalMessage(messages.additional.message, messages.additional.id); + } else if (messages.additional.id !== undefined && messages.additional.message === '') { + plausible.removeAdditionalMessage(messages.additional.id); + } + }); + }, + + /** + * Fetch the messages for display. + */ + fetchMessages: function () { + let data = new FormData(); + data.append('action', 'plausible_analytics_messages'); + + let result = plausible.ajax(data, null, false); + + return result.then(function (response) { + return response; + }); + }, + /** * Displays a notice or error message. * * @param message - * @param isError + * @param type error|warning|success Defaults to success. */ - notice: function (message, isError = false) { - if (isError === true) { + showMessage: function (message, type = 'success') { + if (type === 'error') { document.getElementById('icon-error').classList.remove('hidden'); - document.getElementById('icon-success').classList += ' hidden'; + document.getElementById('icon-success').classList.add('hidden'); + document.getElementById('icon-notice').classList.add('hidden'); + } else if (type === 'notice') { + document.getElementById('icon-notice').classList.remove('hidden'); + document.getElementById('icon-error').classList.add('hidden'); + document.getElementById('icon-success').classList.add('hidden'); } else { document.getElementById('icon-success').classList.remove('hidden'); - document.getElementById('icon-error').classList += ' hidden'; + document.getElementById('icon-error').classList.add('hidden'); + document.getElementById('icon-notice').classList.add('hidden'); } let notice = document.getElementById('plausible-analytics-notice'); @@ -433,7 +424,7 @@ document.addEventListener('DOMContentLoaded', () => { notice.classList.replace('opacity-0', 'opacity-100'); }, 200) - if (isError === false) { + if (type !== 'error') { setTimeout(function () { notice.classList.replace('opacity-100', 'opacity-0'); setTimeout(function () { @@ -441,6 +432,43 @@ document.addEventListener('DOMContentLoaded', () => { }, 200) }, 2000); } + }, + /** + * Renders a HTML box containing additional information about the enabled option. + * + * @param html + * @param target + */ + showAdditionalMessage: function (html, target) { + let targetElem = document.querySelector(`[name='${target}']`); + let container = targetElem.closest('.plausible-analytics-group'); + + container.innerHTML += html; + }, + + /** + * Removes the additional information box when the option is disabled. + * + * @param target + */ + removeAdditionalMessage: function (target) { + let targetElem = document.querySelector(`[name="${target}"]`); + let container = targetElem.closest('.plausible-analytics-group'); + let additionalMessage; + + if (container.children.length > 0) { + for (let i = 0; i < container.children.length; i++) { + if (container.children[i].classList.contains('plausible-analytics-hook')) { + additionalMessage = container.children[i]; + + break; + } + } + } + + if (additionalMessage !== undefined) { + container.removeChild(additionalMessage); + } } } diff --git a/src/Admin/Messages.php b/src/Admin/Messages.php index c9cc9c4b..40bc52e8 100644 --- a/src/Admin/Messages.php +++ b/src/Admin/Messages.php @@ -1,6 +1,7 @@ $message ], $expiration ); } } diff --git a/src/Admin/Settings/API.php b/src/Admin/Settings/API.php index 126a8be5..b9c23199 100644 --- a/src/Admin/Settings/API.php +++ b/src/Admin/Settings/API.php @@ -377,23 +377,17 @@ class="plausible-analytics-wizard-completed-step flex hidden items-start mb-6"> * @return void */ private function render_notices_field() { - /** - * If this var contains a value, the notice box will be shown on next pageloads until the transient is expired. - */ - $show_error = get_transient( 'plausible_analytics_error' ); - $show_notice = get_transient( 'plausible_analytics_notice' ); ?>
+ class="hidden max-w-sm w-full bg-white dark:bg-gray-800 shadow-lg rounded-lg pointer-events-auto transition-opacity ease-in-out duration-200 opacity-0">
-
+ + -
+ + -
+ +
- -

- -

+ +

diff --git a/src/Admin/Settings/Hooks.php b/src/Admin/Settings/Hooks.php index 50dd862e..d250fbae 100644 --- a/src/Admin/Settings/Hooks.php +++ b/src/Admin/Settings/Hooks.php @@ -29,8 +29,6 @@ public function __construct() { * @return void */ private function init_hooks() { - add_action( 'plausible_analytics_toggle_option_message', [ $this, 'maybe_modify_option_message' ], 9, 3 ); - add_action( 'plausible_analytics_toggle_option_message', [ $this, 'maybe_render_additional_message' ], 10, 3 ); add_action( 'plausible_analytics_settings_api_connect_button', [ $this, 'connect_button' ] ); add_action( 'plausible_analytics_settings_api_token_missing', [ $this, 'missing_api_token_warning' ] ); add_action( 'plausible_analytics_settings_option_not_available_in_ce', [ $this, 'option_na_in_ce' ] ); @@ -40,59 +38,6 @@ private function init_hooks() { add_action( 'plausible_analytics_settings_option_disabled_by_proxy', [ $this, 'option_disabled_by_proxy' ] ); } - /** - * We modify the response message here, because otherwise the response to enabling the Proxy option would be "Enable proxy enabled." Sounds - * weird, doesn't it? - * - * @param $response - * @param $option_name - * @param $toggle_status - * - * @return mixed - */ - public function maybe_modify_option_message( $response, $option_name, $toggle_status ) { - if ( $option_name === 'proxy_enabled' ) { - $response[ 'message' ] = __( 'Proxy enabled.', 'plausible-analytics' ); - - if ( ! $toggle_status ) { - $response[ 'message' ] = __( 'Proxy disabled.', 'plausible-analytics' ); - } - } - - return $response; - } - - /** - * Adds the 'additional' array element to $message if applicable. - * - * @param $response - * @param $option_name - * @param $toggle_status - * - * @return array - */ - public function maybe_render_additional_message( $response, $option_name, $toggle_status ) { - if ( ! $toggle_status ) { - return $response; - } - - $additional_message_html = ''; - - if ( $option_name === 'proxy_enabled' ) { - $additional_message_html = $this->render_hook_field( Page::PROXY_WARNING_HOOK ); - } - - if ( $option_name === 'enable_analytics_dashboard' ) { - $additional_message_html = $this->render_hook_field( Page::ENABLE_ANALYTICS_DASH_NOTICE ); - } - - if ( ! $additional_message_html ) { - return $response; - } - - return array_merge( $response, [ 'additional' => $additional_message_html ] ); - } - /** * Display connect button. * diff --git a/src/Ajax.php b/src/Ajax.php index 25fccd24..92a15633 100644 --- a/src/Ajax.php +++ b/src/Ajax.php @@ -10,7 +10,7 @@ namespace Plausible\Analytics\WP; use Plausible\Analytics\WP\Admin\Messages; -use Plausible\Analytics\WP\Admin\Settings\API; +use Plausible\Analytics\WP\Admin\Settings\Hooks; use Plausible\Analytics\WP\Admin\Settings\Page; use Plausible\Analytics\WP\Client\ApiException; @@ -30,12 +30,43 @@ public function __construct() { * @return void */ private function init() { + add_action( 'wp_ajax_plausible_analytics_messages', [ $this, 'fetch_messages' ] ); add_action( 'wp_ajax_plausible_analytics_quit_wizard', [ $this, 'quit_wizard' ] ); add_action( 'wp_ajax_plausible_analytics_show_wizard', [ $this, 'show_wizard' ] ); add_action( 'wp_ajax_plausible_analytics_toggle_option', [ $this, 'toggle_option' ] ); add_action( 'wp_ajax_plausible_analytics_save_options', [ $this, 'save_options' ] ); } + /** + * Returns an array of messages fetched from transients for display by JS. + */ + public function fetch_messages() { + $notice = get_transient( Messages::NOTICE_TRANSIENT ); + $error = get_transient( Messages::ERROR_TRANSIENT ); + $success = get_transient( Messages::SUCCESS_TRANSIENT ); + $additional = get_transient( Messages::ADDITIONAL_TRANSIENT ) ?: []; + $additional_message = []; + + if ( ! empty( $additional ) ) { + $additional_message = [ + 'id' => array_key_first( $additional ), + 'message' => $additional[ array_key_first( $additional ) ], + ]; + } + + $messages = apply_filters( + 'plausible_analytics_messages', + [ + 'notice' => $notice, + 'error' => $error, + 'success' => $success, + 'additional' => $additional_message, + ] + ); + + wp_send_json_success( $messages, 200 ); + } + /** * Mark the wizard as finished, so it won't appear again, and optionally redirect. * @@ -45,7 +76,9 @@ public function quit_wizard() { $request_data = $this->clean( $_REQUEST ); if ( ! current_user_can( 'manage_options' ) || wp_verify_nonce( $request_data[ '_nonce' ], 'plausible_analytics_quit_wizard' ) < 1 ) { - wp_send_json_error( __( 'Not allowed.', 'plausible-analytics' ), 403 ); + Messages::set_error( __( 'Not allowed', 'plausible-analytics' ) ); + + wp_send_json_error( null, 403 ); } update_option( 'plausible_analytics_wizard_done', true ); @@ -122,7 +155,9 @@ public function show_wizard() { $request_data = $this->clean( $_REQUEST ); if ( ! current_user_can( 'manage_options' ) || wp_verify_nonce( $request_data[ '_nonce' ], 'plausible_analytics_show_wizard' ) < 1 ) { - wp_send_json_error( __( 'Not allowed.', 'plausible-analytics' ), 403 ); + Messages::set_error( __( 'Not allowed.', 'plausible-analytics' ) ); + + wp_send_json_error( null, 403 ); } delete_option( 'plausible_analytics_wizard_done' ); @@ -177,16 +212,41 @@ public function toggle_option() { $option_label = $post_data[ 'option_label' ]; $toggle_status = $post_data[ 'toggle_status' ] === 'on' ? __( 'enabled', 'plausible-analytics' ) : __( 'disabled', 'plausible-analytics' ); - $message = apply_filters( - 'plausible_analytics_toggle_option_message', - [ - 'message' => sprintf( '%s %s.', $option_label, $toggle_status ), - ], - $post_data[ 'option_name' ], - $post_data[ 'toggle_status' ] - ); - wp_send_json_success( $message, 200 ); + Messages::set_success( sprintf( '%s %s.', $option_label, $toggle_status ) ); + + $additional = $this->maybe_render_additional_message( $post_data[ 'option_name' ], $post_data[ 'toggle_status' ] ); + + Messages::set_additional( $additional, $post_data[ 'option_name' ] ); + + wp_send_json_success( null, 200 ); + } + + /** + * Adds the 'additional' array element to $message if applicable. + * + * @param $option_name + * @param $toggle_status + * + * @return string + */ + private function maybe_render_additional_message( $option_name, $toggle_status ) { + if ( ! $toggle_status ) { + return ''; + } + + $additional_message_html = ''; + $hooks = new Hooks(); + + if ( $option_name === 'proxy_enabled' ) { + $additional_message_html = $hooks->render_hook_field( Page::PROXY_WARNING_HOOK ); + } + + if ( $option_name === 'enable_analytics_dashboard' ) { + $additional_message_html = $hooks->render_hook_field( Page::ENABLE_ANALYTICS_DASH_NOTICE ); + } + + return $additional_message_html; } /** @@ -201,13 +261,17 @@ public function save_options() { $settings = Helpers::get_settings(); if ( ! current_user_can( 'manage_options' ) || wp_verify_nonce( $post_data[ '_nonce' ], 'plausible_analytics_toggle_option' ) < 1 ) { - wp_send_json_error( __( 'Forbidden', 'plausible-analytics' ), 403 ); + Messages::set_error( __( 'Not allowed.', 'plausible-analytics' ) ); + + wp_send_json_error( null, 403 ); } $options = json_decode( $post_data[ 'options' ] ); if ( empty( $options ) ) { - wp_send_json_error( __( 'No options found to save.', 'plausible-analytics' ), 400 ); + Messages::set_error( __( 'No options found to save.', 'plausible-analytics' ) ); + + wp_send_json_error( null, 400 ); } foreach ( $options as $option ) { @@ -222,7 +286,9 @@ public function save_options() { update_option( 'plausible_analytics_settings', $settings ); - wp_send_json_success( __( 'Settings saved.', 'plausible-analytics' ), 200 ); + Messages::set_success( __( 'Settings saved.', 'plausible-analytics' ) ); + + wp_send_json_success( null, 200 ); } /** @@ -238,16 +304,13 @@ private function validate_api_token( $token = '' ) { if ( ! $client->validate_api_token() ) { Messages::set_error( - sprintf( - __( - 'Oops! The API token you used is invalid. Please click here to generate a new token.', - 'plausible-analytics' - ), - '' + __( + 'Oops! The API token you used is invalid. Please click here to generate a new token.', + 'plausible-analytics' ) ); - wp_send_json_error( __( 'Invalid API token.', 'plausible-analytics' ) ); + wp_send_json_error( null, 400 ); } } }