From c020261b06174981e4832095acf7b16591d49313 Mon Sep 17 00:00:00 2001 From: devinwalker Date: Tue, 30 Apr 2024 09:41:27 -0700 Subject: [PATCH 1/8] Fix rest_no_route error by using addQueryArgs to properly build URL. Refactor admin.js for cleaner code and improved functionality Changes in code include adjusting indentation and spacing as well as importing addQueryArgs from '@wordpress/url'. Moreover, the code for checking if images exist and setting image URLs has been modified for efficiency. Lastly, minor changes were made in the HTML part of the code like adding spaces before closing tags. --- src/admin.js | 119 +++++++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 56 deletions(-) diff --git a/src/admin.js b/src/admin.js index 06d2c65..1dc9370 100644 --- a/src/admin.js +++ b/src/admin.js @@ -1,10 +1,10 @@ import './admin.scss'; -import { Button, Dashicon, Modal, Popover, Spinner } from '@wordpress/components'; -import { render, useEffect, useState } from '@wordpress/element'; -import { __, _n, sprintf } from '@wordpress/i18n'; +import {Button, Dashicon, Modal, Spinner} from '@wordpress/components'; +import {render, useEffect, useState} from '@wordpress/element'; +import {__, _n, sprintf} from '@wordpress/i18n'; import domReady from '@wordpress/dom-ready'; -import { decodeEntities } from '@wordpress/html-entities'; -import { getQueryArgs } from '@wordpress/url'; +import {decodeEntities} from '@wordpress/html-entities'; +import {addQueryArgs, getQueryArgs} from '@wordpress/url'; import ExpandableText from './ExpandableText'; import TrunkPopover from './TrunkPopover'; @@ -17,7 +17,7 @@ const AdminPage = () => { const [ isConfirmModalOpen, setIsConfirmModalOpen ] = useState( false ); const [ isChangelogModalOpen, setIsChangelogModalOpen ] = useState( false ); const [ rollbackVersion, setIsRollbackVersion ] = useState( queryArgs.current_version ); - const { adminUrl, referrer } = wprData; + const {adminUrl, referrer} = wprData; const openConfirmModal = () => setIsConfirmModalOpen( true ); const openChangelogModal = () => setIsChangelogModalOpen( true ); @@ -26,13 +26,16 @@ const AdminPage = () => { useEffect( () => { - let restUrl = `${wprData.restUrl}wp-rollback/v1/fetch-info/?type=${queryArgs.type}&slug=${queryArgs.type === 'theme' ? queryArgs.theme_file : queryArgs.plugin_slug}`; + let restUrl = addQueryArgs( wprData.restUrl + 'wp-rollback/v1/fetch-info/', { + type: queryArgs.type, + slug: queryArgs.type === 'theme' ? queryArgs.theme_file : queryArgs.plugin_slug, + } ); const headers = new Headers( { 'X-WP-Nonce': wprData.restApiNonce, // Assuming nonce is stored in wprData.nonce } ); - fetch( restUrl, { headers: headers } ) + fetch( restUrl, {headers: headers} ) .then( ( response ) => response.json() ) .then( ( data ) => { setRollbackInfo( data ); @@ -43,36 +46,36 @@ const AdminPage = () => { } ); }, [ wprData ] ); - useEffect(() => { + useEffect( () => { const checkAndSetImage = async () => { - if (rollbackInfo && rollbackInfo.slug) { - const sizes = ['icon-256x256', 'icon-128x128', 'icon']; - const extensions = ['png', 'jpg', 'gif', 'svg']; + if ( rollbackInfo && rollbackInfo.slug ) { + const sizes = [ 'icon-256x256', 'icon-128x128', 'icon' ]; + const extensions = [ 'png', 'jpg', 'gif', 'svg' ]; - for (let size of sizes) { - for (let ext of extensions) { + for ( let size of sizes ) { + for ( let ext of extensions ) { const url = `https://ps.w.org/${rollbackInfo.slug}/assets/${size}.${ext}`; - const exists = await checkImage(url); - if (exists) { - setImageUrl(url); + const exists = await checkImage( url ); + if ( exists ) { + setImageUrl( url ); return; } } } - setImageUrl(wprData.avatarFallback); + setImageUrl( wprData.avatarFallback ); } }; checkAndSetImage(); - }, [rollbackInfo]); + }, [ rollbackInfo ] ); - function checkImage(url) { - return new Promise((resolve, reject) => { + function checkImage( url ) { + return new Promise( ( resolve, reject ) => { var img = new Image(); - img.onload = () => resolve(true); - img.onerror = () => resolve(false); + img.onload = () => resolve( true ); + img.onerror = () => resolve( false ); img.src = url; - }); + } ); } if ( isLoading ) { @@ -109,7 +112,7 @@ const AdminPage = () => { // Convert to 24-hour format and remove 'GMT' let adjustedDateString = dateString.replace( 'am', ' AM' ).replace( 'pm', ' PM' ).replace( ' GMT', '' ); - adjustedDateString = new Date( adjustedDateString ).toLocaleString( 'en-US', { timeZone: 'GMT' } ); + adjustedDateString = new Date( adjustedDateString ).toLocaleString( 'en-US', {timeZone: 'GMT'} ); const date = new Date( adjustedDateString ); if ( isNaN( date.getTime() ) ) { @@ -146,7 +149,7 @@ const AdminPage = () => {

{__( 'WP Rollback', 'wp-rollback' )}

- {'WP + {'WP

{__( 'Select which version you would like to rollback to from the releases listed below.', 'wp-rollback' )}

@@ -158,7 +161,7 @@ const AdminPage = () => { src={( false !== rollbackInfo.banners.high ? rollbackInfo.banners.high : rollbackInfo.banners.low )} width={800} height={'auto'} className={'wpr-plugin-banner'} - alt={rollbackInfo.name}/> + alt={rollbackInfo.name} />
)} @@ -168,14 +171,14 @@ const AdminPage = () => {
{rollbackInfo.name}/ + alt={rollbackInfo.name} />
)} {imageUrl && queryArgs.type === 'plugin' && (
{rollbackInfo.name}/ + alt={rollbackInfo.name} />
)} @@ -189,7 +192,7 @@ const AdminPage = () => { alt={sprintf( __( 'View %s on WordPress.org', 'wp-rollback' ), rollbackInfo.name )} > {decodeEntities( rollbackInfo.name )} - + )} {queryArgs.type === 'theme' && ( @@ -198,7 +201,7 @@ const AdminPage = () => { // translators: %s Plugin or Theme name. alt={sprintf( __( 'View %s on WordPress.org', 'wp-rollback' ), rollbackInfo.name )}> {decodeEntities( rollbackInfo.name )} - + )} @@ -206,7 +209,7 @@ const AdminPage = () => { {queryArgs.type === 'theme' && rollbackInfo.sections.description && (
- +
)} @@ -235,7 +238,7 @@ const AdminPage = () => {

{__( 'Theme Author', 'wp-rollback' )}

- +
{rollbackInfo.author.display_name} @@ -252,7 +255,7 @@ const AdminPage = () => {

{__( 'Last Updated', 'wp-rollback' )}

- + {getTimeAgo( rollbackInfo.last_updated )}
@@ -263,14 +266,18 @@ const AdminPage = () => {
{Object.keys( rollbackInfo.versions ) - .sort((a, b) => { - if (a === 'trunk') return 1; // Always places 'trunk' at the end - if (b === 'trunk') return -1; // Always places 'trunk' at the end - return b.localeCompare(a, undefined, { - numeric: true, + .sort( ( a, b ) => { + if ( a === 'trunk' ) { + return 1; + } // Always places 'trunk' at the end + if ( b === 'trunk' ) { + return -1; + } // Always places 'trunk' at the end + return b.localeCompare( a, undefined, { + numeric : true, sensitivity: 'base', - }); - }) + } ); + } ) .map( ( version, index ) => (
@@ -309,7 +316,7 @@ const AdminPage = () => { onRequestClose={closeChangelogModal} disabled={( rollbackVersion === false )} className={'wpr-modal wpr-modal__changelog'} - icon={} + icon={} >
{ onRequestClose={closeConfirmModal} disabled={( rollbackVersion === false )} className={'wpr-modal'} - icon={} + icon={} >

{ @@ -366,29 +373,29 @@ const AdminPage = () => {

Notice: We strongly recommend you create a complete backup of your WordPress files and database prior to performing a rollback. We are not responsible for any misuse, deletions, white screens, fatal errors, or any other issue resulting from the use of this plugin.

', 'wp-rollback' ) }}/> + dangerouslySetInnerHTML={{__html: __( '

Notice: We strongly recommend you create a complete backup of your WordPress files and database prior to performing a rollback. We are not responsible for any misuse, deletions, white screens, fatal errors, or any other issue resulting from the use of this plugin.

', 'wp-rollback' )}} />
- - - + + + {queryArgs.type === 'plugin' && (
- - - + + +
)} {queryArgs.type === 'theme' && (
- - + +
)} - - + +
@@ -408,6 +415,6 @@ const AdminPage = () => { domReady( function() { if ( document.getElementById( 'root-wp-rollback-admin' ) ) { - render( , document.getElementById( 'root-wp-rollback-admin' ) ); + render( , document.getElementById( 'root-wp-rollback-admin' ) ); } } ); From 021bb004cfebd01685ffe600397e6b27c6c188d9 Mon Sep 17 00:00:00 2001 From: devinwalker Date: Tue, 30 Apr 2024 09:44:58 -0700 Subject: [PATCH 2/8] Update WP Rollback plugin version to 2.0.7 This commit updates the WP Rollback plugin version to 2.0.7 and indicates compatibility with WordPress version 6.6. It includes changes to the plugin's description, along with the addition of bug fixes in the changelog. These fixes resolve an error with plain permalink websites and update the way the React app is loaded to suppress React 18+ warnings. --- package.json | 2 +- readme.txt | 8 ++++++-- wp-rollback.php | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 06827f7..964d6c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wp-rollback", - "version": "2.0.0", + "version": "2.0.7", "description": "Rollback (or forward) any WordPress.org plugin, theme, or block like a boss.", "homepage": "https://wprollback.com", "author": "WP Rollback", diff --git a/readme.txt b/readme.txt index 6a9f87c..f866d9e 100644 --- a/readme.txt +++ b/readme.txt @@ -3,9 +3,9 @@ Contributors: dlocc, drrobotnik, webdevmattcrom, givewp Tags: rollback, revert, downgrade, version, plugins, themes, version, versions, backup, backups, revision, revisions Requires at least: 5.0 Donate Link: https://givewp.com/ -Tested up to: 6.5 +Tested up to: 6.6 Requires PHP: 7.4 -Stable tag: 2.0.6 +Stable tag: 2.0.7 License: GPLv3 License URI: http://www.gnu.org/licenses/gpl-3.0.html @@ -106,6 +106,10 @@ This is the first version of this plugin. It is a tool for your convenience. Rol == Changelog == += 2.0.7 = +* Fix: Resolved a bug with plain permalink websites which caused a `rest_no_route` error when trying to rollback a plugin or theme. Thanks, @afizesan for helping pinpoint the issue. +* Fix: Update the way the React app is loaded to suppress React 18+ warnings. + = 2.0.6 = Fix: The release corrects the paths used in plugin file includes and requires. The unnecessary forward slashes at the start of each file path have been removed. This change ensures proper file inclusion and requirement, avoiding potential issues with file not found errors. diff --git a/wp-rollback.php b/wp-rollback.php index acf2279..53ab4ce 100644 --- a/wp-rollback.php +++ b/wp-rollback.php @@ -5,7 +5,7 @@ * Description: Rollback (or forward) any WordPress.org plugin, theme or block like a boss. * Author: WP Rollback * Author URI: https://wprollback.com/ - * Version: 2.0.6 + * Version: 2.0.7 * Text Domain: wp-rollback * Domain Path: /languages * From 87b8aa4f8c9f016d0b44eda7fbf068d63f990cf8 Mon Sep 17 00:00:00 2001 From: devinwalker Date: Tue, 30 Apr 2024 09:56:00 -0700 Subject: [PATCH 3/8] Replace render with createRoot in admin.js The code has been updated to import createRoot instead of render from '@wordpress/element' in admin.js of the wp-rollback plugin. Additionally, the domReady function has been refactored to use createRoot if available, otherwise it falls back to ReactDOM.render. This change improves the rendering process of the AdminPage. --- src/admin.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/admin.js b/src/admin.js index 1dc9370..39244b5 100644 --- a/src/admin.js +++ b/src/admin.js @@ -1,6 +1,6 @@ import './admin.scss'; import {Button, Dashicon, Modal, Spinner} from '@wordpress/components'; -import {render, useEffect, useState} from '@wordpress/element'; +import {createRoot, useEffect, useState} from '@wordpress/element'; import {__, _n, sprintf} from '@wordpress/i18n'; import domReady from '@wordpress/dom-ready'; import {decodeEntities} from '@wordpress/html-entities'; @@ -413,8 +413,18 @@ const AdminPage = () => { }; -domReady( function() { - if ( document.getElementById( 'root-wp-rollback-admin' ) ) { - render( , document.getElementById( 'root-wp-rollback-admin' ) ); +domReady(function() { + const container = document.getElementById('root-wp-rollback-admin'); + if (!container) { + return; } -} ); + + const component = ; + + // Use createRoot if available, otherwise fallback to ReactDOM.render + if (createRoot) { + createRoot(container).render(component); + } else { + ReactDOM.render(component, container); + } +}); From b283adcd656dd597fc1f258fd533ca93053ef952 Mon Sep 17 00:00:00 2001 From: devinwalker Date: Tue, 30 Apr 2024 09:56:14 -0700 Subject: [PATCH 4/8] Migrate Prettier configuration to JS file The previous JSON configuration file for Prettier has been removed and replaced with a new JavaScript configuration file. This new configuration file imports the default settings from WordPress Scripts and applies some customisations, including a print width of 120 and disabling the use of tabs. --- .prettierrc.js | 10 ++++++++++ .prettierrc.json | 7 ------- 2 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 .prettierrc.js delete mode 100644 .prettierrc.json diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..7669fbc --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,10 @@ +const defaultConfig = require( '@wordpress/scripts/config/.prettierrc.js' ); + +// Add customizations to WordPress prettier config. +const config = { + ...defaultConfig, + printWidth: 120, + useTabs: false, +}; + +module.exports = config; diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index fa858b5..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "tabWidth": 4, - "trailingComma": "es5", - "printWidth": 120, - "bracketSpacing": false, - "singleQuote": true -} From 43ef760b68d2eb883d0687321fe2389fbf90c541 Mon Sep 17 00:00:00 2001 From: devinwalker Date: Tue, 30 Apr 2024 12:50:01 -0700 Subject: [PATCH 5/8] Update minimum required WordPress version The minimum required WordPress version for plugin was updated from 5.0 to 6.0 for optimal compatibility. This change was necessary for the best compatibility with the new React components in the user interface. --- readme.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index f866d9e..9e18d8a 100644 --- a/readme.txt +++ b/readme.txt @@ -1,7 +1,7 @@ === WP Rollback - Rollback Plugins and Themes === Contributors: dlocc, drrobotnik, webdevmattcrom, givewp Tags: rollback, revert, downgrade, version, plugins, themes, version, versions, backup, backups, revision, revisions -Requires at least: 5.0 +Requires at least: 6.0 Donate Link: https://givewp.com/ Tested up to: 6.6 Requires PHP: 7.4 @@ -109,6 +109,7 @@ This is the first version of this plugin. It is a tool for your convenience. Rol = 2.0.7 = * Fix: Resolved a bug with plain permalink websites which caused a `rest_no_route` error when trying to rollback a plugin or theme. Thanks, @afizesan for helping pinpoint the issue. * Fix: Update the way the React app is loaded to suppress React 18+ warnings. +* Tweak: Bumped the plugin's minimum required WordPress version to 6.0+ for best compatibility with new React components in UI. = 2.0.6 = Fix: The release corrects the paths used in plugin file includes and requires. The unnecessary forward slashes at the start of each file path have been removed. This change ensures proper file inclusion and requirement, avoiding potential issues with file not found errors. From 9d083314d23c887411ec9eeefa090c8ed595763c Mon Sep 17 00:00:00 2001 From: devinwalker Date: Tue, 30 Apr 2024 13:04:51 -0700 Subject: [PATCH 6/8] Update ignore and config files for project Several changes were made to the .distignore, .prettierignore, .gitignore, and .editorconfig files in this commit. These changes mainly consist of additions and removals of files and directories to be ignored. Also a max_line_length attribute was added to .editorconfig for customization purpose. --- .distignore | 8 +++----- .editorconfig | 1 + .gitignore | 13 ++++++++++--- .prettierignore | 20 ++++++++++---------- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/.distignore b/.distignore index 028aa9d..5b88ffa 100644 --- a/.distignore +++ b/.distignore @@ -1,18 +1,16 @@ .git .github -.wordpress-org -node_modules +.wordpress-orgnode_modules src/*.js -src/**/*.js .editorconfig .gitignore .prettierignore .prettierrc.json +.prettierrc.js composer.json composer.lock -package.json -package-lock.json +package.jsonpackage-lock.json README.md webpack.config.js diff --git a/.editorconfig b/.editorconfig index 76fdcd3..5535dec 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,6 +9,7 @@ tab_width = 4 indent_style = space insert_final_newline = true trim_trailing_whitespace = true +max_line_length = 120 [*.txt] trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index 2696cac..cbba6cf 100644 --- a/.gitignore +++ b/.gitignore @@ -9,9 +9,7 @@ yarn-error.log* coverage # Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release /build -/src/Strauss # Dependency directories node_modules/ @@ -25,11 +23,20 @@ node_modules/ # Output of 'npm pack' *.tgz -# dotenv environment variables file +# dotenv environment variables files and directories .env +.prettierignore +.prettierrc +.gitignore +/.idea/ +.vscode +.DS_Store # No composer stuff /vendor/ # No language files /languages/* + +# Catch alls +wp-rollback.zip diff --git a/.prettierignore b/.prettierignore index 4bd56d2..1d50f46 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,12 +1,12 @@ -# Ignore node modules -node_modules/* +# Ignore directories +.github +assets +build +node_modules +languages -# Ignore Composer packages -vendor/* - -# Ignore Directories -sample-data/* - -# Ignore Files -package-lock.json +# Ignore files composer.lock +package-lock.json +phpcs.xml +.php-cs-fixer.cache From d38211ddb1d67dc2e06619a5e688e397e7f28cd6 Mon Sep 17 00:00:00 2001 From: devinwalker Date: Tue, 30 Apr 2024 13:06:26 -0700 Subject: [PATCH 7/8] Fix .distignore and .gitignore formatting The .distignore file has been updated to have separate entries for package.json and package-lock.json rather than them being on the same line. Additionally, the .gitignore file has been amended to remove coverage and unnecessary empty lines, and to include .idea. --- .distignore | 3 ++- .gitignore | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.distignore b/.distignore index 5b88ffa..b7be7f3 100644 --- a/.distignore +++ b/.distignore @@ -10,7 +10,8 @@ src/*.js .prettierrc.js composer.json composer.lock -package.jsonpackage-lock.json +package.json +package-lock.json README.md webpack.config.js diff --git a/.gitignore b/.gitignore index cbba6cf..91dd377 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,7 @@ logs npm-debug.log* yarn-debug.log* yarn-error.log* - -# Coverage directory used by tools like istanbul -coverage +.idea # Compiled binary addons (https://nodejs.org/api/addons.html) /build From 436e7ad1cf298c99699e521953137486e13c8280 Mon Sep 17 00:00:00 2001 From: devinwalker Date: Tue, 30 Apr 2024 13:11:47 -0700 Subject: [PATCH 8/8] use prettier formatting --- src/admin.js | 539 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 317 insertions(+), 222 deletions(-) diff --git a/src/admin.js b/src/admin.js index 39244b5..df29f4e 100644 --- a/src/admin.js +++ b/src/admin.js @@ -1,15 +1,14 @@ import './admin.scss'; -import {Button, Dashicon, Modal, Spinner} from '@wordpress/components'; -import {createRoot, useEffect, useState} from '@wordpress/element'; -import {__, _n, sprintf} from '@wordpress/i18n'; +import { Button, Dashicon, Modal, Spinner } from '@wordpress/components'; +import { createRoot, useEffect, useState } from '@wordpress/element'; +import { __, _n, sprintf } from '@wordpress/i18n'; import domReady from '@wordpress/dom-ready'; -import {decodeEntities} from '@wordpress/html-entities'; -import {addQueryArgs, getQueryArgs} from '@wordpress/url'; +import { decodeEntities } from '@wordpress/html-entities'; +import { addQueryArgs, getQueryArgs } from '@wordpress/url'; import ExpandableText from './ExpandableText'; import TrunkPopover from './TrunkPopover'; const AdminPage = () => { - const [ isLoading, setIsLoading ] = useState( true ); const [ rollbackInfo, setRollbackInfo ] = useState( false ); const [ imageUrl, setImageUrl ] = useState( null ); @@ -17,7 +16,7 @@ const AdminPage = () => { const [ isConfirmModalOpen, setIsConfirmModalOpen ] = useState( false ); const [ isChangelogModalOpen, setIsChangelogModalOpen ] = useState( false ); const [ rollbackVersion, setIsRollbackVersion ] = useState( queryArgs.current_version ); - const {adminUrl, referrer} = wprData; + const { adminUrl, referrer } = wprData; const openConfirmModal = () => setIsConfirmModalOpen( true ); const openChangelogModal = () => setIsChangelogModalOpen( true ); @@ -25,7 +24,6 @@ const AdminPage = () => { const closeChangelogModal = () => setIsChangelogModalOpen( false ); useEffect( () => { - let restUrl = addQueryArgs( wprData.restUrl + 'wp-rollback/v1/fetch-info/', { type: queryArgs.type, slug: queryArgs.type === 'theme' ? queryArgs.theme_file : queryArgs.plugin_slug, @@ -35,7 +33,7 @@ const AdminPage = () => { 'X-WP-Nonce': wprData.restApiNonce, // Assuming nonce is stored in wprData.nonce } ); - fetch( restUrl, {headers: headers} ) + fetch( restUrl, { headers: headers } ) .then( ( response ) => response.json() ) .then( ( data ) => { setRollbackInfo( data ); @@ -54,7 +52,7 @@ const AdminPage = () => { for ( let size of sizes ) { for ( let ext of extensions ) { - const url = `https://ps.w.org/${rollbackInfo.slug}/assets/${size}.${ext}`; + const url = `https://ps.w.org/${ rollbackInfo.slug }/assets/${ size }.${ ext }`; const exists = await checkImage( url ); if ( exists ) { setImageUrl( url ); @@ -80,16 +78,16 @@ const AdminPage = () => { if ( isLoading ) { return ( -
-
-
+
+
+
-

{__( 'Loading...', 'wp-rollback' )}

+

{ __( 'Loading...', 'wp-rollback' ) }

@@ -99,20 +97,19 @@ const AdminPage = () => { // output error message if one is found in the API response if ( rollbackInfo.message ) { return ( -
-
-

{rollbackInfo.code}

-

{rollbackInfo.message}

+
+
+

{ rollbackInfo.code }

+

{ rollbackInfo.message }

); } function getTimeAgo( dateString ) { - // Convert to 24-hour format and remove 'GMT' let adjustedDateString = dateString.replace( 'am', ' AM' ).replace( 'pm', ' PM' ).replace( ' GMT', '' ); - adjustedDateString = new Date( adjustedDateString ).toLocaleString( 'en-US', {timeZone: 'GMT'} ); + adjustedDateString = new Date( adjustedDateString ).toLocaleString( 'en-US', { timeZone: 'GMT' } ); const date = new Date( adjustedDateString ); if ( isNaN( date.getTime() ) ) { @@ -128,144 +125,204 @@ const AdminPage = () => { return sprintf( _n( '%s second ago', '%s seconds ago', diffInSeconds, 'wp-rollback' ), diffInSeconds ); } else if ( diffInSeconds < 3600 ) { // translators: %s Number of minutes. - return sprintf( _n( '%s minute ago', '%s minutes ago', Math.floor( diffInSeconds / 60 ), 'wp-rollback' ), Math.floor( diffInSeconds / 60 ) ); + return sprintf( + _n( '%s minute ago', '%s minutes ago', Math.floor( diffInSeconds / 60 ), 'wp-rollback' ), + Math.floor( diffInSeconds / 60 ) + ); } else if ( diffInSeconds < 86400 ) { // translators: %s Number of hours. - return sprintf( _n( '%s hour ago', '%s hours ago', Math.floor( diffInSeconds / 3600 ), 'wp-rollback' ), Math.floor( diffInSeconds / 3600 ) ); - } else if ( diffInSeconds < 2592000 ) { // 30 days + return sprintf( + _n( '%s hour ago', '%s hours ago', Math.floor( diffInSeconds / 3600 ), 'wp-rollback' ), + Math.floor( diffInSeconds / 3600 ) + ); + } else if ( diffInSeconds < 2592000 ) { + // 30 days // translators: %s Number of days. - return sprintf( _n( '%s day ago', '%s days ago', Math.floor( diffInSeconds / 86400 ), 'wp-rollback' ), Math.floor( diffInSeconds / 86400 ) ); - } else if ( diffInSeconds < 31536000 ) { // 365 days + return sprintf( + _n( '%s day ago', '%s days ago', Math.floor( diffInSeconds / 86400 ), 'wp-rollback' ), + Math.floor( diffInSeconds / 86400 ) + ); + } else if ( diffInSeconds < 31536000 ) { + // 365 days // translators: %s Number of monthes. - return sprintf( _n( '%s month ago', '%s months ago', Math.floor( diffInSeconds / 2592000 ), 'wp-rollback' ), Math.floor( diffInSeconds / 2592000 ) ); + return sprintf( + _n( '%s month ago', '%s months ago', Math.floor( diffInSeconds / 2592000 ), 'wp-rollback' ), + Math.floor( diffInSeconds / 2592000 ) + ); } else { // translators: %s Number of years. - return sprintf( _n( '%s year ago', '%s years ago', Math.floor( diffInSeconds / 31536000 ), 'wp-rollback' ), Math.floor( diffInSeconds / 31536000 ) ); + return sprintf( + _n( '%s year ago', '%s years ago', Math.floor( diffInSeconds / 31536000 ), 'wp-rollback' ), + Math.floor( diffInSeconds / 31536000 ) + ); } } return ( -
-
-
-

{__( 'WP Rollback', 'wp-rollback' )}

- {'WP +
+
+
+

{ __( 'WP Rollback', 'wp-rollback' ) }

+ + { +
-

{__( 'Select which version you would like to rollback to from the releases listed below.', 'wp-rollback' )}

+

+ { __( + 'Select which version you would like to rollback to from the releases listed below.', + 'wp-rollback' + ) } +

- {rollbackInfo.banners && queryArgs.type === 'plugin' && ( rollbackInfo.banners.high || rollbackInfo.banners.low ) && ( -
- {rollbackInfo.name} -
- )} + { rollbackInfo.banners && + queryArgs.type === 'plugin' && + ( rollbackInfo.banners.high || rollbackInfo.banners.low ) && ( +
+ { +
+ ) }
- - {rollbackInfo.screenshot_url && queryArgs.type === 'theme' && ( + { rollbackInfo.screenshot_url && queryArgs.type === 'theme' && (
- {rollbackInfo.name} + {
- )} - - {imageUrl && queryArgs.type === 'plugin' && ( -
- {rollbackInfo.name} + ) } + + { imageUrl && queryArgs.type === 'plugin' && ( +
+ {
- - )} - -
-

- {queryArgs.type === 'plugin' && ( - +

+ { queryArgs.type === 'plugin' && ( + - {decodeEntities( rollbackInfo.name )} + { decodeEntities( rollbackInfo.name ) } - )} - {queryArgs.type === 'theme' && ( - - {decodeEntities( rollbackInfo.name )} + alt={ sprintf( + __( 'View %s on WordPress.org', 'wp-rollback' ), + rollbackInfo.name + ) } + > + { decodeEntities( rollbackInfo.name ) } - )} - + ) }

- {queryArgs.type === 'theme' && rollbackInfo.sections.description && ( -
- + { queryArgs.type === 'theme' && rollbackInfo.sections.description && ( +
+ +
+ ) } + +
+
+ + { __( 'Installed version:', 'wp-rollback' ) }{ ' ' } + { queryArgs.current_version } +
- )} - -
-
{__( 'Installed version:', 'wp-rollback' )}{' '} - {queryArgs.current_version}
- - {queryArgs.type === 'plugin' && ( -
- {__( 'Plugin author:', 'wp-rollback' )}{' '} - - + + { queryArgs.type === 'plugin' && ( +
+ + { __( 'Plugin author:', 'wp-rollback' ) }{ ' ' } +
- )} + ) }
-
-
- {queryArgs.type === 'theme' && ( -
-

{__( 'Theme Author', 'wp-rollback' )}

-
- -
{rollbackInfo.author.display_name} +
+ { queryArgs.type === 'theme' && ( +
+

{ __( 'Theme Author', 'wp-rollback' ) }

+
- )} - - {queryArgs.type === 'plugin' && ( -
-
- + ) } + + { queryArgs.type === 'plugin' && ( +
+
+
-

{__( 'Last Updated', 'wp-rollback' )}

-
+

{ __( 'Last Updated', 'wp-rollback' ) }

+
- {getTimeAgo( rollbackInfo.last_updated )} + + { getTimeAgo( rollbackInfo.last_updated ) } +
- )} + ) }
-
- {Object.keys( rollbackInfo.versions ) +
+ { Object.keys( rollbackInfo.versions ) .sort( ( a, b ) => { if ( a === 'trunk' ) { return 1; @@ -274,157 +331,195 @@ const AdminPage = () => { return -1; } // Always places 'trunk' at the end return b.localeCompare( a, undefined, { - numeric : true, + numeric: true, sensitivity: 'base', } ); } ) .map( ( version, index ) => ( -
-
-
-
- - +
+ +
- {isChangelogModalOpen && ( + { isChangelogModalOpen && ( } + title={ __( 'Plugin Changelog', 'wp-rollback' ) } + onRequestClose={ closeChangelogModal } + disabled={ rollbackVersion === false } + className={ 'wpr-modal wpr-modal__changelog' } + icon={ } > -
+
- )} + ) } - {isConfirmModalOpen && ( + { isConfirmModalOpen && ( } + title={ __( 'Are you sure you want to proceed?', 'wp-rollback' ) } + onRequestClose={ closeConfirmModal } + disabled={ rollbackVersion === false } + className={ 'wpr-modal' } + icon={ } > -

${rollbackInfo.name}`, - `${rollbackVersion}`, - ), - }}>

+

${ rollbackInfo.name }`, + `${ rollbackVersion }` + ), + } } + >

- - - - - - - - - - - - + + + + + + + + + + + +
- -
- - {queryArgs.current_version} -
- - {rollbackVersion}
+ + + +
+ + + { queryArgs.current_version } +
+ + + { rollbackVersion } +
-
Notice: We strongly recommend you create a complete backup of your WordPress files and database prior to performing a rollback. We are not responsible for any misuse, deletions, white screens, fatal errors, or any other issue resulting from the use of this plugin.

', 'wp-rollback' )}} /> +
Notice: We strongly recommend you create a complete backup of your WordPress files and database prior to performing a rollback. We are not responsible for any misuse, deletions, white screens, fatal errors, or any other issue resulting from the use of this plugin.

', + 'wp-rollback' + ), + } } + /> - + - - + + - {queryArgs.type === 'plugin' && ( + { queryArgs.type === 'plugin' && (
- - - + + +
- )} - {queryArgs.type === 'theme' && ( + ) } + { queryArgs.type === 'theme' && (
- - + +
- )} - - - - -
- - + ) } + + + + +
+ +
- )} - + ) }
- ); - }; -domReady(function() { - const container = document.getElementById('root-wp-rollback-admin'); - if (!container) { +domReady( function () { + const container = document.getElementById( 'root-wp-rollback-admin' ); + if ( ! container ) { return; } const component = ; // Use createRoot if available, otherwise fallback to ReactDOM.render - if (createRoot) { - createRoot(container).render(component); + if ( createRoot ) { + createRoot( container ).render( component ); } else { - ReactDOM.render(component, container); + ReactDOM.render( component, container ); } -}); +} );