Skip to content

Commit

Permalink
Merge pull request #129 from Automattic/add/fix-build-and-refactor
Browse files Browse the repository at this point in the history
v.1 refactoring
  • Loading branch information
iuravic authored Apr 26, 2024
2 parents dcd97d7 + 4a2eb3d commit 3c730cf
Show file tree
Hide file tree
Showing 46 changed files with 1,636 additions and 1,628 deletions.
40 changes: 28 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
# newspack-content-converter
Plugin which mass-converts pre-Gutenberg Classic HTML Posts and Pages to the Gutenberg Blocks.
Mass-conversion of pre-Gutenberg Classic HTML Posts and Pages to the Gutenberg Blocks.

### Disclaimer

Please make sure to back up your site contents fully, because this converter updates the content permanently by replacing the classic HTML content with Gutenberg Blocks content.
Make sure to back up your site contents fully, because this converter updates the content of your database permanently by replacing the classic HTML content with Gutenberg Blocks content.

This plugin is open source, and the creators can not be held responsible for any data loss or consequences of its usage.

The plugin is presently in Alpha, and used primarily as a Developer's tool -- please check back for a full and improved version soon.
### Convert HTML to Blocks

The "Newspack Content Converter" > "Converter" submenu item in the Dashboard's main allows you to mass convert all your HTML posts to Gutenberg blocks.

### Usage
Every time this screen is loaded, it will scan your existing posts and display the number of unconverted posts which can then be converted. All Posts which do not begin with block syntax `<!-- wp...` can be converted.

Clicking "Newspack Content Converter" in the Admin area's main left-hand menu, opens a page where the number of Posts and number of batches queued for Conversion is displayed. Clicking the "Run conversion" button there actually initializes the conversion and starts converting your queued Posts and Pages to Blocks.
Click "Run conversion" to actually begin the conversion. The page will reloaded and conversion will begin. This page with conversion running should not be stopped or closed until it is fully completed.

After a conversion is complete, it's sometimes necessary to flush the cache, as well.
While the conversion is running, a link will allow you to open several conversion browser tabs at once, which can speed up the entire conversion. Each such additional tab picks up the next batch of posts an converts it in a parallel process. Depending on your computer performance, it is usually recommended to run between 1 to 10 maximum parallel tabs.

After running Newspack Content Converter, if you need to undo the conversion, you restore the `wp_posts` table to its pre-conversion state by running `wp newspack-content-converter restore-content`. This will also undo any other editorial changes that have been made to the content in the interim.
In case that the conversion page gets closed or unexpectedly terminated while it hasn't finished converting, the "Converter" page will let you "Reset" the conversion and simply continue where you left off.

To re-scan your freshest HTML Posts, and to update the conversion queue, run the CLI command `wp newspack-content-converter reset`.
After the conversion is complete, it may be necessary to flush the object cache to see the effects in Gutenberg editor or the front page.

#### If the conversion page is not loading

After "Run conversion" is clicked, if the conversion page is not properly displaying and running, an alert with an error message will pop up after some time.

If the problem persists, temporarily deactivate all other active plugins and try running the conversion again. Once the conversion is complete, reactivate your site plugins.

#### Restore original content

Plugin backs up and stores original post content before conversion to blocks as custom postmeta. The "Restore content" page allows you to restore converted posts to the latest available backup.

It also lets you delete all this custom postmeta from your database, which will permanently delete the backups.

#### Settings

"Settings" page displays the post types and post statuses which get converted.

### Development

- `composer install`
- `nvm use 16`
- `npm ci --legacy-peer-deps`
- `npm run build`
- Run `npm run release:archive` to package a release. The archive will be created in `assets/release/newspack-content-converter.zip`
- Run `npm start` to compile the JS files, and start file watcher
- `npm ci`
- `npm run build` for a single build or `npm start` to compile the JS files and start the file watcher
- `npm run release:archive` to package a release. The archive will be created in `assets/release/newspack-content-converter.zip`
99 changes: 43 additions & 56 deletions assets/src/content-converter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { NewspackLogo } from 'newspack-components';
import {
runMultiplePosts,
fetchConversionBatch,
fetchRetryFailedConversionsBatch,
} from '../utilities';

class ContentConverter extends Component {
Expand All @@ -37,36 +36,37 @@ class ContentConverter extends Component {

this.state = {
isActive: null,
retryFailedConversions: props.retryFailedConversions,
postIds: null,
isConversionPrepared: null,
isConversionFinished: null,
ids: null,
thisBatch: null,
maxBatch: null,
hasIncompleteConversions: false,
totalNumberOfBatches: null,
};
}

componentDidMount() {
const { retryFailedConversions } = this.state;
document.title = "Newspack Content Converter";

// Get a batch of regular conversions, or retry the failed ones.
const fetchBatchPromise = retryFailedConversions
? fetchRetryFailedConversionsBatch
: fetchConversionBatch;

return fetchBatchPromise()
// Run a batch of conversions.
return fetchConversionBatch()
.then( response => {
if ( response ) {
const { ids: postIds, thisBatch, maxBatch, hasIncompleteConversions } = response;
const { isConversionPrepared, isConversionFinished, ids, thisBatch, totalNumberOfBatches } = response;
// Starting conversion, setting isActive to true.
this.setState( {
postIds,
isConversionPrepared,
isConversionFinished,
ids,
thisBatch,
maxBatch,
hasIncompleteConversions,
totalNumberOfBatches,
isActive: true,
} );
if ( postIds ) {
console.log( ' ----------------------- ABOUT TO CONVERT IDS: ' + postIds );
return runMultiplePosts( postIds );
// If conversion is not prepared and not finished, redirect to the plugin page.
if ( '0' == isConversionPrepared && '0' == isConversionFinished ) {
window.parent.location = '/wp-admin/admin.php?page=newspack-content-converter';
} else if ( ids ) {
console.log( ' ----------------------- ABOUT TO CONVERT BATCH: ' + thisBatch + ' IDS: ' + ids );
return runMultiplePosts( ids );
}
}

Expand All @@ -75,13 +75,15 @@ class ContentConverter extends Component {
.then( () => {
return new Promise( ( resolve, reject ) => {
console.log( ' ----------------------- FINISHED.' );
if ( this.state.postIds ) {
if ( this.state.ids && this.state.ids.length > 0 ) {
// Conversion hasn't started yet, so isActive is null before it's either true or false.
this.setState( { isActive: null } );
// This should disable the browser's "Reload page?" popup, although it doesn't always work as expected.
window.onbeforeunload = function() {};
// Reload this window to pick up the next batch.
window.location.reload( true );
} else {
// No more posts to convert, so isActive is false.
this.setState( { isActive: false } );
}

Expand All @@ -94,14 +96,15 @@ class ContentConverter extends Component {
* render().
*/
render() {
const { isActive, thisBatch, maxBatch, hasIncompleteConversions } = this.state;
const { isActive, thisBatch, totalNumberOfBatches } = this.state;

if ( null == isActive ) {
// This is the initial state of the interface, before conversion has started (true) or finished (false).
return (
<div className="newspack-content-converter__wrapper">
<div className="newspack-logo__wrapper">
<Button
href="https://newspack.pub/"
href="https://newspack.com/"
target="_blank"
label={ __( 'By Newspack' ) }
>
Expand All @@ -116,17 +119,18 @@ class ContentConverter extends Component {
</FlexBlock>
</CardHeader>
<CardFooter justify="center" isBorderless>
<Spinner />
<Spinner /> { __( 'Fetching posts for conversion... ' ) }
</CardFooter>
</Card>
</div>
);
} else if ( true == isActive ) {
// Conversion is running.
return (
<div className="newspack-content-converter__wrapper is-active">
<div className="newspack-logo__wrapper">
<Button
href="https://newspack.pub/"
href="https://newspack.com/"
target="_blank"
label={ __( 'By Newspack' ) }
>
Expand All @@ -147,28 +151,32 @@ class ContentConverter extends Component {
'This page will occasionally automatically reload, and notify you when the conversion is complete.'
) }
</p>
<p>{ __( 'If asked to Reload, chose yes.' ) }</p>
<Notice status="warning" isDismissible={ false }>
{ __( 'If asked to Reload, chose yes.' ) }
</Notice>
<p>
<em>
{ __(
'You may also carefully open an additional tab to convert another batch in parallel.'
'To convert another batch in parallel and increase conversion speed (depending on your computer performance, no more than 10 max parallel browser tabs are usually recommended), '
) }
<a href="" target="_blank">open an additional conversion tab</a>.
</em>
</p>
</CardBody>
<CardFooter justify="center" className="newspack-content-converter__batch">
<Spinner />
<p>{ __( 'Now processing batch' ) } { thisBatch }/{ maxBatch }</p>
<p>{ __( 'Now processing batch' ) } { thisBatch }/{ totalNumberOfBatches }</p>
</CardFooter>
</Card>
</div>
);
} else if ( false == isActive ) {
// Conversion has finished.
return (
<div className="newspack-content-converter__wrapper">
<div className="newspack-logo__wrapper">
<Button
href="https://newspack.pub/"
href="https://newspack.com/"
target="_blank"
label={ __( 'By Newspack' ) }
>
Expand All @@ -183,37 +191,15 @@ class ContentConverter extends Component {
</FlexBlock>
</CardHeader>
<CardBody>
{ true == hasIncompleteConversions ? (
<Notice isDismissible={ false } status="error">
{ __(
'Certain entries were not converted successfully. You may try converting those again on the "Converter" page.'
) }
</Notice>
) : (
<Notice isDismissible={ false } status="success">
{ __( 'All queued content has been converted successfully.' ) }
{ __( 'All content has been converted.' ) }
</Notice>
) }
</CardBody>
{ true == hasIncompleteConversions ? (
<CardFooter justify="flex-end">
<Button href="/wp-admin/" isSecondary>
{ __( 'Back to Dashboard' ) }
</Button>
<Button href="/wp-admin/admin.php?page=newspack-content-converter" isPrimary>
{ __( 'Back to Converter' ) }
</Button>
</CardFooter>
) : (
<CardFooter justify="flex-end">
<Button href="/wp-admin/admin.php?page=newspack-content-converter" isSecondary>
{ __( 'Back to Converter' ) }
</Button>
<Button href="/wp-admin/" isPrimary>
{ __( 'Back to Dashboard' ) }
</Button>
</CardFooter>
) }
<CardFooter justify="flex-end">
<Button href="/wp-admin/admin.php?page=newspack-content-converter" isPrimary>
{ __( 'Back to Converter' ) }
</Button>
</CardFooter>
</Card>
</div>
);
Expand All @@ -222,3 +208,4 @@ class ContentConverter extends Component {
}

export default ContentConverter;

Loading

0 comments on commit 3c730cf

Please sign in to comment.