diff --git a/.eslintrc.js b/.eslintrc.js index b6b435aee..e72b01f76 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,7 +3,7 @@ module.exports = { extends: [ 'plugin:@wordpress/eslint-plugin/recommended' ], plugins: [ 'import' ], globals: { - wp: 'off', + wp: 'readonly', ajaxurl: 'readonly', FormData: 'readonly', }, diff --git a/assets/js/plugin-check-admin.js b/assets/js/plugin-check-admin.js index 3c3a98322..4e4191cc4 100644 --- a/assets/js/plugin-check-admin.js +++ b/assets/js/plugin-check-admin.js @@ -1,11 +1,14 @@ ( function ( pluginCheck ) { const checkItButton = document.getElementById( 'plugin-check__submit' ); + const resultsContainer = document.getElementById( 'plugin-check__results' ); + const spinner = document.getElementById( 'plugin-check__spinner' ); const pluginsList = document.getElementById( 'plugin-check__plugins-dropdown' ); + const templates = {}; // Return early if the elements cannot be found on the page. - if ( ! checkItButton || ! pluginsList ) { + if ( ! checkItButton || ! pluginsList || ! resultsContainer || ! spinner ) { console.error( 'Missing form elements on page' ); return; } @@ -13,18 +16,46 @@ checkItButton.addEventListener( 'click', ( e ) => { e.preventDefault(); + resetResults(); + checkItButton.disabled = true; + spinner.classList.add( 'is-active' ); + getChecksToRun() .then( setUpEnvironment ) .then( runChecks ) .then( cleanUpEnvironment ) .then( ( data ) => { console.log( data.message ); + + resetForm(); } ) .catch( ( error ) => { console.error( error ); + + resetForm(); } ); } ); + /** + * Reset the results container. + * + * @since n.e.x.t + */ + function resetResults() { + // Empty the results container. + resultsContainer.innerText = ''; + } + + /** + * Resets the form controls once checks have completed or failed. + * + * @since n.e.x.t + */ + function resetForm() { + spinner.classList.remove( 'is-active' ); + checkItButton.disabled = false; + } + /** * Setup the runtime environment if needed. * @@ -88,8 +119,6 @@ throw new Error( 'Response contains no data.' ); } - console.log( responseData.data.message ); - return responseData.data; } ); } @@ -139,8 +168,8 @@ async function runChecks( data ) { for ( let i = 0; i < data.checks.length; i++ ) { try { - const result = await runCheck( data.plugin, data.checks[ i ] ); - console.log( result ); + const results = await runCheck( data.plugin, data.checks[ i ] ); + renderResults( results ); } catch ( e ) { // Ignore for now. } @@ -207,4 +236,109 @@ return data; } + + /** + * Renders results for each check on the page. + * + * @since n.e.x.t + * + * @param {Object} results The results object. + */ + function renderResults( results ) { + const { errors, warnings } = results; + + // Render errors and warnings for files. + for ( const file in errors ) { + if ( warnings[ file ] ) { + renderFileResults( file, errors[ file ], warnings[ file ] ); + delete warnings[ file ]; + } else { + renderFileResults( file, errors[ file ], [] ); + } + } + + // Render remaining files with only warnings. + for ( const file in warnings ) { + renderFileResults( file, [], warnings[ file ] ); + } + + resultsContainer.innerHTML += renderTemplate( + 'plugin-check-results-complete' + ); + } + + /** + * Renders the file results table. + * + * @since n.e.x.t + * + * @param {string} file The file name for the results. + * @param {Object} errors The file errors. + * @param {Object} warnings The file warnings. + */ + function renderFileResults( file, errors, warnings ) { + const index = Date.now(); + + // Render the file table. + resultsContainer.innerHTML += renderTemplate( + 'plugin-check-results-table', + { file, index } + ); + const resultsTable = document.getElementById( + 'plugin-check__results-body-' + index + ); + + // Render results to the table. + renderResultRows( 'ERROR', errors, resultsTable ); + renderResultRows( 'WARNING', warnings, resultsTable ); + } + + /** + * Renders a result row onto the file table. + * + * @since n.e.x.t + * + * @param {string} type The result type. Either ERROR or WARNING. + * @param {Object} results The results object. + * @param {Object} table The HTML table to append a result row to. + */ + function renderResultRows( type, results, table ) { + // Loop over each result by the line, column and messages. + for ( const line in results ) { + for ( const column in results[ line ] ) { + for ( let i = 0; i < results[ line ][ column ].length; i++ ) { + const message = results[ line ][ column ][ i ].message; + const code = results[ line ][ column ][ i ].code; + + table.innerHTML += renderTemplate( + 'plugin-check-results-row', + { + line, + column, + type, + message, + code, + } + ); + } + } + } + } + + /** + * Renders the template with data. + * + * @since n.e.x.t + * + * @param {string} templateSlug The template slug + * @param {Object} data Template data. + * @return {string} Template HTML. + */ + function renderTemplate( templateSlug, data ) { + if ( ! templates[ templateSlug ] ) { + templates[ templateSlug ] = wp.template( templateSlug ); + } + const template = templates[ templateSlug ]; + return template( data ); + } } )( PLUGIN_CHECK ); /* global PLUGIN_CHECK */ diff --git a/includes/Admin/Admin_Page.php b/includes/Admin/Admin_Page.php index c16a3e6cc..5e77751c9 100644 --- a/includes/Admin/Admin_Page.php +++ b/includes/Admin/Admin_Page.php @@ -71,6 +71,7 @@ public function add_page() { */ public function initialize_page() { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); + add_action( 'admin_footer', array( $this, 'admin_footer' ) ); } /** @@ -82,7 +83,9 @@ public function enqueue_scripts() { wp_enqueue_script( 'plugin-check-admin', WP_PLUGIN_CHECK_PLUGIN_DIR_URL . 'assets/js/plugin-check-admin.js', - array(), + array( + 'wp-util', + ), WP_PLUGIN_CHECK_VERSION, true ); @@ -154,4 +157,44 @@ public function filter_plugin_action_links( $actions, $plugin_file ) { return $actions; } + + /** + * Render the results table templates in the footer. + * + * @since n.e.x.t + */ + public function admin_footer() { + ob_start(); + require WP_PLUGIN_CHECK_PLUGIN_DIR_PATH . '/templates/results-table.php'; + $results_table_template = ob_get_clean(); + wp_print_inline_script_tag( + $results_table_template, + array( + 'id' => 'tmpl-plugin-check-results-table', + 'type' => 'text/template', + ) + ); + + ob_start(); + require WP_PLUGIN_CHECK_PLUGIN_DIR_PATH . '/templates/results-row.php'; + $results_row_template = ob_get_clean(); + wp_print_inline_script_tag( + $results_row_template, + array( + 'id' => 'tmpl-plugin-check-results-row', + 'type' => 'text/template', + ) + ); + + ob_start(); + require WP_PLUGIN_CHECK_PLUGIN_DIR_PATH . '/templates/results-complete.php'; + $results_row_template = ob_get_clean(); + wp_print_inline_script_tag( + $results_row_template, + array( + 'id' => 'tmpl-plugin-check-results-complete', + 'type' => 'text/template', + ) + ); + } } diff --git a/templates/admin-page.php b/templates/admin-page.php index c35098ee3..3657428cf 100644 --- a/templates/admin-page.php +++ b/templates/admin-page.php @@ -32,6 +32,7 @@ + @@ -41,4 +42,6 @@ +
+ diff --git a/templates/results-complete.php b/templates/results-complete.php new file mode 100644 index 000000000..3fd88c8f2 --- /dev/null +++ b/templates/results-complete.php @@ -0,0 +1 @@ +

diff --git a/templates/results-row.php b/templates/results-row.php new file mode 100644 index 000000000..8a3b6d6b1 --- /dev/null +++ b/templates/results-row.php @@ -0,0 +1,18 @@ + + + {{data.line}} + + + {{data.column}} + + + {{data.type}} + + + {{data.code}} + + + {{data.message}} + + + diff --git a/templates/results-table.php b/templates/results-table.php new file mode 100644 index 000000000..7af4860af --- /dev/null +++ b/templates/results-table.php @@ -0,0 +1,24 @@ +

{{ data.file }}

+ + + + + + + + + + + +
+ + + + + + + + + +
+