From 500dfea4db444615ac53059e471b189ff4da9e4b Mon Sep 17 00:00:00 2001 From: BE-Webdesign Date: Fri, 1 Sep 2017 21:17:11 -0400 Subject: [PATCH] Bringing iframes into React/Redux Brings iframes into React, updates of the post now trigger submission of the iframe forms. Fixed linting errors, and added tests for new JS functionality. --- .eslintignore | 1 + assets/css/metabox.css | 1 + editor/actions.js | 31 ++++++ editor/effects.js | 15 +++ editor/layout/index.js | 10 +- editor/metaboxes/index.js | 62 +++++++++++ editor/metaboxes/style.scss | 7 ++ editor/reducer.js | 10 ++ editor/selectors.js | 10 ++ editor/test/actions.js | 24 +++++ editor/test/reducer.js | 59 +++++++++++ editor/test/selectors.js | 17 +++ gutenberg.php | 2 +- lib/client-assets.php | 8 ++ ...tabox-api.php => metabox-partial-page.php} | 100 +++++++++++------- lib/register.php | 19 +++- 16 files changed, 329 insertions(+), 47 deletions(-) create mode 100644 editor/metaboxes/index.js create mode 100644 editor/metaboxes/style.scss rename lib/{metabox-api.php => metabox-partial-page.php} (85%) diff --git a/.eslintignore b/.eslintignore index 164ae5ac2c7ef..3aa71080db424 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ build coverage vendor node_modules +/assets/js diff --git a/assets/css/metabox.css b/assets/css/metabox.css index a0af58ad1c7aa..615c3365747b0 100644 --- a/assets/css/metabox.css +++ b/assets/css/metabox.css @@ -1,6 +1,7 @@ /* Hides scrollbar to make iframe content seem as though it is part of the page. */ .gutenberg-metabox-html { overflow: hidden; + width: 100%; } .gutenberg-metabox-html.sidebar-open { diff --git a/editor/actions.js b/editor/actions.js index 27938e8be1f1f..6a7331cf1259b 100644 --- a/editor/actions.js +++ b/editor/actions.js @@ -309,6 +309,37 @@ export function removeNotice( id ) { }; } +// Metabox related actions. + +/** + * Returns an action object used to trigger metabox updates. + * + * @return {Object} Action object + */ +export function updateMetaboxes() { + return { + type: 'UPDATE_METABOXES', + }; +} + +/** + * Returns an action object used to set metabox DOM references. + * + * @param {String} location The metabox location: normal, advanced, side. + * @param {DOMElement} node The reference node of the metabox. + * + * @return {Object} Action object + */ +export function setMetaboxReference( location, node ) { + return { + type: 'SET_METABOX_REFERENCE', + data: { + location, + node, + }, + }; +} + export const createSuccessNotice = partial( createNotice, 'success' ); export const createInfoNotice = partial( createNotice, 'info' ); export const createErrorNotice = partial( createNotice, 'error' ); diff --git a/editor/effects.js b/editor/effects.js index 163982fba0e50..911c917f64286 100644 --- a/editor/effects.js +++ b/editor/effects.js @@ -25,6 +25,7 @@ import { removeNotice, savePost, editPost, + updateMetaboxes, } from './actions'; import { getCurrentPost, @@ -35,6 +36,7 @@ import { isEditedPostDirty, isEditedPostNew, isEditedPostSaveable, + getMetaboxNodes, } from './selectors'; const SAVE_POST_NOTICE_ID = 'SAVE_POST_NOTICE_ID'; @@ -113,6 +115,9 @@ export default { ) ); } + // Update metaboxes. + dispatch( updateMetaboxes() ); + if ( get( window.history.state, 'id' ) !== post.id ) { window.history.replaceState( { id: post.id }, @@ -273,4 +278,14 @@ export default { return effects; }, + UPDATE_METABOXES( action, store ) { + const { getState } = store; + const state = getState(); + const metaboxes = getMetaboxNodes( state ); + Object.values( metaboxes ).forEach( ( iframe ) => { + // The standard post.php form ID post should probably be mimicked. + const form = iframe.contentWindow.document.getElementById( 'post' ); + form.submit(); + } ); + }, }; diff --git a/editor/layout/index.js b/editor/layout/index.js index b9d91011e4138..36a5878ab8c34 100644 --- a/editor/layout/index.js +++ b/editor/layout/index.js @@ -21,6 +21,7 @@ import UnsavedChangesWarning from '../unsaved-changes-warning'; import DocumentTitle from '../document-title'; import AutosaveMonitor from '../autosave-monitor'; import { removeNotice } from '../actions'; +import Metaboxes from '../metaboxes'; import { getEditorMode, isEditorSidebarOpened, @@ -32,8 +33,8 @@ function Layout( { mode, isSidebarOpened, notices, ...props } ) { 'is-sidebar-opened': isSidebarOpened, } ); - return ( -
+ return [ +
@@ -44,8 +45,9 @@ function Layout( { mode, isSidebarOpened, notices, ...props } ) { { mode === 'visual' && }
{ isSidebarOpened && } -
- ); + , + , + ]; } export default connect( diff --git a/editor/metaboxes/index.js b/editor/metaboxes/index.js new file mode 100644 index 0000000000000..cb4fe652e403b --- /dev/null +++ b/editor/metaboxes/index.js @@ -0,0 +1,62 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; +import { connect } from 'react-redux'; +// @TODO Should this be React or WordPress elements? +import { Component } from 'react'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import './style.scss'; +import { setMetaboxReference } from '../actions'; + +class Metaboxes extends Component { + constructor() { + super(); + + this.state = { + cool: 'yeah', + }; + } + + componentDidMount() { + // Sets a React Node Reference into the store. + this.props.setReference( this.props.location, this.node ); + } + + render() { + const { location, isSidebarOpened, id = 'gutenberg-metabox-iframe' } = this.props; + const classes = classnames( { + 'sidebar-open': isSidebarOpened, + 'gutenberg-metabox-iframe': true, + } ); + + return ( +