diff --git a/assets/src/amp-validation/amp-validated-url-post-edit-screen.js b/assets/src/amp-validation/amp-validated-url-post-edit-screen.js index c2ff74bde4d..8ea1ed16343 100644 --- a/assets/src/amp-validation/amp-validated-url-post-edit-screen.js +++ b/assets/src/amp-validation/amp-validated-url-post-edit-screen.js @@ -8,6 +8,8 @@ import { __, _n, sprintf } from '@wordpress/i18n'; * Internal dependencies */ import setValidationErrorRowsSeenClass from './set-validation-error-rows-seen-class'; +import { handleCopyToClipboardButtons } from './copy-to-clipboard-buttons'; +import { getURLValidationTableRows } from './get-url-validation-table-rows'; /** * The id for the 'Showing x of y errors' notice. @@ -32,6 +34,7 @@ domReady( () => { handleBulkActions(); watchForUnsavedChanges(); setupStylesheetsMetabox(); + handleCopyToClipboardButtons(); } ); let beforeUnloadPromptAdded = false; @@ -389,13 +392,10 @@ const handleBulkActions = () => { const markingAsReviewed = target.classList.contains( 'reviewed' ); - [ ...document.querySelectorAll( 'select.amp-validation-error-status' ) ].forEach( ( select ) => { - const row = select.closest( 'tr' ); - if ( row.querySelector( '.check-column input[type=checkbox]' ).checked ) { - row.querySelector( 'input[type=checkbox].amp-validation-error-status-review' ).checked = markingAsReviewed; - row.classList.toggle( 'new', ! markingAsReviewed ); - addBeforeUnloadPrompt(); - } + getURLValidationTableRows( { checkedOnly: true } ).forEach( ( row ) => { + row.querySelector( 'input[type=checkbox].amp-validation-error-status-review' ).checked = markingAsReviewed; + row.classList.toggle( 'new', ! markingAsReviewed ); + addBeforeUnloadPrompt(); } ); } ); }; diff --git a/assets/src/amp-validation/copy-to-clipboard-buttons.js b/assets/src/amp-validation/copy-to-clipboard-buttons.js new file mode 100644 index 00000000000..d19bbcdbc66 --- /dev/null +++ b/assets/src/amp-validation/copy-to-clipboard-buttons.js @@ -0,0 +1,76 @@ +/** + * External dependencies + */ +import Clipboard from 'clipboard'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { getURLValidationTableRows } from './get-url-validation-table-rows'; + +/** + * Success handler, called when data is copied to the clipboard. + * + * @param {Object} event + * @param {HTMLElement} event.trigger The element triggering the event. + */ +function onSuccess( { trigger } ) { + trigger.focus(); + + const newInnerText = __( 'Copied to clipboard', 'amp' ); + + // Exit if the user has already clicked the button and we are still within the + // 4000ms before the setTimeout callback runs. + if ( trigger.innerText === newInnerText ) { + return; + } + + const originalText = trigger.innerText; + trigger.innerText = newInnerText; + + setTimeout( () => { + if ( document.body.contains( trigger ) ) { + trigger.innerText = originalText; + } + }, 4000 ); +} + +/** + * Sets up the "Copy to clipboard" buttons on the URL validation screen. + */ +export function handleCopyToClipboardButtons() { + const clipboards = []; + + // eslint-disable-next-line no-new + clipboards.push( new Clipboard( 'button.single-url-detail-copy', { + text: ( btn ) => { + return JSON.stringify( JSON.parse( btn.getAttribute( 'data-error-json' ) ), null, '\t' ); + }, + } ) ); + + // eslint-disable-next-line no-new + clipboards.push( new Clipboard( 'button.copy-all', { + text: () => { + const value = getURLValidationTableRows( { checkedOnly: true } ).map( ( row ) => { + const copyButton = row.querySelector( '.single-url-detail-copy' ); + if ( ! copyButton ) { + return null; + } + + return JSON.parse( copyButton.getAttribute( 'data-error-json' ) ); + } ) + .filter( ( item ) => item ); + + return JSON.stringify( value, null, '\t' ); + }, + } ) ); + + clipboards.forEach( ( clipboard ) => { + clipboard.on( 'success', onSuccess ); + } ); +} diff --git a/assets/src/amp-validation/get-url-validation-table-rows.js b/assets/src/amp-validation/get-url-validation-table-rows.js new file mode 100644 index 00000000000..9d654c6f343 --- /dev/null +++ b/assets/src/amp-validation/get-url-validation-table-rows.js @@ -0,0 +1,16 @@ +/** + * Gets the table rows on a single URL validation screen. + * + * @param {Object} options + * @param {boolean} options.checkedOnly Whether to return only checked rows. + */ +export function getURLValidationTableRows( options = {} ) { + const rows = [ ...document.querySelectorAll( 'select.amp-validation-error-status' ) ] + .map( ( select ) => select.closest( 'tr' ) ); + + if ( true !== options.checkedOnly ) { + return rows; + } + + return rows.filter( ( row ) => row.querySelector( '.check-column input[type=checkbox]' ).checked ); +} diff --git a/includes/validation/class-amp-validated-url-post-type.php b/includes/validation/class-amp-validated-url-post-type.php index d98c1ae4665..95d934d1b5a 100644 --- a/includes/validation/class-amp-validated-url-post-type.php +++ b/includes/validation/class-amp-validated-url-post-type.php @@ -2796,6 +2796,7 @@ public static function render_single_url_list_table( $post ) { +