Skip to content

Commit

Permalink
Reusable Blocks: Support importing and exporting reusable blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed Sep 11, 2018
1 parent d83c359 commit 0112cb4
Show file tree
Hide file tree
Showing 16 changed files with 427 additions and 2 deletions.
10 changes: 8 additions & 2 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@
{
"title": "Articles",
"slug": "articles",
"markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/docs/outreach/articles.md",
"markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/outreach/docs/articles.md",
"parent": "outreach"
},
{
Expand Down Expand Up @@ -425,6 +425,12 @@
"markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/packages/library-export-default-webpack-plugin/README.md",
"parent": "packages"
},
{
"title": "@wordpress/list-reusable-blocks",
"slug": "packages-list-reusable-blocks",
"markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/packages/list-reusable-blocks/README.md",
"parent": "packages"
},
{
"title": "@wordpress/npm-package-json-lint-config",
"slug": "packages-npm-package-json-lint-config",
Expand Down Expand Up @@ -851,4 +857,4 @@
"markdown_source": "https://raw.githubusercontent.com/WordPress/gutenberg/master/docs/data/data-core-viewport.md",
"parent": "data"
}
]
]
32 changes: 32 additions & 0 deletions gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,12 @@ function gutenberg_add_edit_link( $actions, $post ) {
if ( 'wp_block' === $post->post_type ) {
unset( $actions['edit'] );
unset( $actions['inline hide-if-no-js'] );
$actions['export'] = sprintf(
'<a class="wp-list-reusable-blocks__export" href="#" data-id="%s" aria-label="%s">%s</a>',
$post->ID,
__( 'Export as JSON', 'gutenberg' ),
__( 'Export as JSON', 'gutenberg' )
);
return $actions;
}

Expand Down Expand Up @@ -475,3 +481,29 @@ function gutenberg_add_admin_body_class( $classes ) {
return "$classes gutenberg-editor-page is-fullscreen-mode";
}
}

/**
* Add the reusable blocks list page import success notice.
*/
function wp_add_reusable_blocks_import_success_notice() {
?>
<div class="notice notice-success is-dismissible">
<p><?php _e( 'Reusable block imported with success!', 'gutenberg' ); ?></p>
</div>
<?php
}

/**
* Add hooks specific to the reusable blocks list page.
*
* @param string $current_screen Current screen.
*/
function wp_add_reusable_blocks_list_hooks( $current_screen ) {
$is_reusable_blocks_list_page = 'wp_block' === $current_screen->post_type && 'edit' === $current_screen->base;
$should_show_success_notice = $is_reusable_blocks_list_page && isset( $_GET['action'] ) && 'import' === $_GET['action'];

if ( $should_show_success_notice ) {
add_action( 'admin_notices', 'wp_add_reusable_blocks_import_success_notice' );
}
}
add_action( 'current_screen', 'wp_add_reusable_blocks_list_hooks' );
38 changes: 38 additions & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,22 @@ function gutenberg_register_scripts_and_styles() {
'before'
);

wp_register_script(
'wp-list-reusable-blocks',
gutenberg_url( 'build/list-reusable-blocks/index.js' ),
array(
'lodash',
'wp-api-fetch',
'wp-components',
'wp-compose',
'wp-element',
'wp-i18n',
'wp-polyfill-ecmascript',
),
filemtime( gutenberg_dir_path() . 'build/list-reusable-blocks/index.js' ),
true
);

// Editor Styles.
// This empty stylesheet is defined to ensure backwards compatibility.
wp_register_style( 'wp-blocks', false );
Expand Down Expand Up @@ -723,6 +739,14 @@ function gutenberg_register_scripts_and_styles() {
);
wp_style_add_data( 'wp-block-library-theme', 'rtl', 'replace' );

wp_register_style(
'wp-list-reusable-blocks',
gutenberg_url( 'build/list-reusable-blocks/style.css' ),
array( 'wp-components' ),
filemtime( gutenberg_dir_path() . 'build/list-reusable-blocks/style.css' )
);
wp_style_add_data( 'wp-list-reusable-block', 'rtl', 'replace' );

if ( defined( 'GUTENBERG_LIVE_RELOAD' ) && GUTENBERG_LIVE_RELOAD ) {
$live_reload_url = ( GUTENBERG_LIVE_RELOAD === true ) ? 'http://localhost:35729/livereload.js' : GUTENBERG_LIVE_RELOAD;

Expand Down Expand Up @@ -1518,3 +1542,17 @@ function gutenberg_editor_scripts_and_styles( $hook ) {
*/
do_action( 'enqueue_block_editor_assets' );
}

/**
* Enqueue the reusable blocks listing page's script
*
* @param string $hook Screen name.
*/
function wp_load_list_reusable_blocks( $hook ) {
$is_reusable_blocks_list_page = 'edit.php' === $hook && isset( $_GET['post_type'] ) && 'wp_block' === $_GET['post_type'];
if ( $is_reusable_blocks_list_page ) {
wp_enqueue_script( 'wp-list-reusable-blocks' );
wp_enqueue_style( 'wp-list-reusable-blocks' );
}
}
add_action( 'admin_enqueue_scripts', 'wp_load_list_reusable_blocks' );
1 change: 1 addition & 0 deletions packages/list-reusable-blocks/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
5 changes: 5 additions & 0 deletions packages/list-reusable-blocks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Reusable blocks listing page

Package used to add import/export links to the listing page of the reusable blocks.

<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>
34 changes: 34 additions & 0 deletions packages/list-reusable-blocks/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@wordpress/list-reusable-blocks",
"version": "1.0.0",
"description": "Adding Export/Import support to the reusable blocks listing.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"keywords": [
"templates",
"reusable blocks"
],
"private": true,
"homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/list-reusable-blocks/README.md",
"repository": {
"type": "git",
"url": "https://github.com/WordPress/gutenberg.git"
},
"bugs": {
"url": "https://github.com/WordPress/gutenberg/issues"
},
"main": "build/index.js",
"module": "build-module/index.js",
"dependencies": {
"@babel/runtime": "^7.0.0",
"@wordpress/api-fetch": "file:../api-fetch",
"@wordpress/components": "file:../components",
"@wordpress/compose": "file:../compose",
"@wordpress/element": "file:../element",
"@wordpress/i18n": "file:../i18n",
"lodash": "^4.17.10"
},
"publishConfig": {
"access": "public"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Dropdown, Button } from '@wordpress/components';

/**
* Internal dependencies
*/
import ImportForm from '../import-form';

function ImportDropdown( { onUpload } ) {
return (
<Dropdown
position="bottom right"
contentClassName="list-reusable-blocks-import-dropdown__content"
renderToggle={ ( { isOpen, onToggle } ) => (
<Button
type="button"
aria-expanded={ isOpen }
onClick={ onToggle }
isPrimary
>
{ __( 'Import from JSON' ) }
</Button>
) }
renderContent={ () => <ImportForm onUpload={ onUpload } /> }
/>
);
}

export default ImportDropdown;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.list-reusable-blocks-import-dropdown__content .components-popover__content {
padding: 10px;
}
101 changes: 101 additions & 0 deletions packages/list-reusable-blocks/src/components/import-form/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { withInstanceId } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import { Button, Notice } from '@wordpress/components';

/**
* Internal dependencies
*/
import importReusableBlock from '../../utils/import';

class ImportForm extends Component {
constructor() {
super( ...arguments );
this.state = {
isLoading: false,
error: null,
file: null,
};

this.isMounted = true;
this.onChangeFile = this.onChangeFile.bind( this );
this.onSubmit = this.onSubmit.bind( this );
}

componentWillUnmount() {
this.isMounted = false;
}

onChangeFile( event ) {
this.setState( { file: event.target.files[ 0 ] } );
}

onSubmit( event ) {
event.preventDefault();
const { file } = this.state;
const { onUpload } = this.props;
if ( ! file ) {
return;
}
this.setState( { isLoading: true } );
importReusableBlock( file )
.then( ( reusableBlock ) => {
if ( ! this.isMounted ) {
return;
}

this.setState( { isLoading: false } );
onUpload( reusableBlock );
} )
.catch( ( error ) => {
if ( ! this.isMounted ) {
return;
}

this.setState( { isLoading: false, error: error.message } );
} );
}

render() {
const { instanceId } = this.props;
const { file, isLoading, error } = this.state;
const inputId = 'list-reusable-blocks-import-form-' + instanceId;
return (
<form
className="list-reusable-blocks-import-form"
onSubmit={ this.onSubmit }
>
{ error && (
<Notice status="error">
{ error }
</Notice>
) }
<label
htmlFor={ inputId }
className="list-reusable-blocks-import-form__label"
>
{ __( 'File' ) }
</label>
<input
id={ inputId }
type="file"
onChange={ this.onChangeFile }
/>
<Button
type="submit"
isBusy={ isLoading }
disabled={ ! file || isLoading }
isDefault
className="list-reusable-blocks-import-form__button"
>
{ __( 'Import' ) }
</Button>
</form>
);
}
}

export default withInstanceId( ImportForm );
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.list-reusable-blocks-import-form__label {
display: block;
margin-bottom: 10px;
}

.list-reusable-blocks-import-form__button {
margin-top: 20px;
float: right;
}

.list-reusable-blocks-import-form .components-notice__content {
margin: 0;
}
38 changes: 38 additions & 0 deletions packages/list-reusable-blocks/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* WordPress dependencies
*/
import { render } from '@wordpress/element';
import { addQueryArgs } from '@wordpress/url';

/**
* Internal dependencies
*/
import exportReusableBlock from './utils/export';
import ImportDropdown from './components/import-dropdown';

// Setup Export Links
document.body.addEventListener( 'click', ( event ) => {
if ( ! event.target.classList.contains( 'wp-list-reusable-blocks__export' ) ) {
return;
}
event.preventDefault();
exportReusableBlock( event.target.dataset.id );
} );

// Setup Import Form
document.addEventListener( 'DOMContentLoaded', function() {
const buttons = document.getElementsByClassName( 'page-title-action' );
const button = buttons.item( 0 );
if ( ! button ) {
return;
}

const refreshAndShowNotice = () => {
window.location = addQueryArgs( window.location.href, { action: 'import' } );
};

const container = document.createElement( 'div' );
container.className = 'list-reusable-blocks__container';
button.parentNode.insertBefore( container, button );
render( <ImportDropdown onUpload={ refreshAndShowNotice } />, container );
} );
9 changes: 9 additions & 0 deletions packages/list-reusable-blocks/src/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@import "./components/import-dropdown/style.scss";
@import "./components/import-form/style.scss";

.list-reusable-blocks__container {
display: inline-flex;
padding: 9px 0 4px; // To match the H1
align-items: center;
vertical-align: top;
}
Loading

0 comments on commit 0112cb4

Please sign in to comment.