Skip to content

Commit

Permalink
Edit Post: Upgrade admin notices to notice module
Browse files Browse the repository at this point in the history
  • Loading branch information
aduth committed Nov 7, 2018
1 parent a8bd2a8 commit 18407d6
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ function gutenberg_register_scripts_and_styles() {
'wp-embed',
'wp-i18n',
'wp-keycodes',
'wp-notices',
'wp-nux',
'wp-plugins',
'wp-polyfill',
Expand Down
112 changes: 112 additions & 0 deletions packages/edit-post/src/components/admin-notices/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { withDispatch } from '@wordpress/data';

/**
* Set of class name suffixes to associate as the status of an admin notice.
*
* @type {Set}
*/
const NOTICE_STATUSES = new Set( [
'success',
'warning',
'error',
'info',
] );

/**
* Pattern matching a class list item matching the pattern of an admin notice
* status class.
*
* @type {RegExp}
*/
const REGEXP_NOTICE_STATUS = /^notice-(\w+)$/;

/**
* Returns an array of admin notice Elements.
*
* @return {Element[]} Admin notice elements.
*/
function getAdminNotices() {
return [ ...document.querySelectorAll( '.notice' ) ];
}

/**
* Given an admin notice Element, returns the upgraded content string. Prefers
* text found within its first child paragraph node, but falls back to the text
* content of the entire notice element.
*
* @param {Element} element Admin notice element.
*
* @return {string} Upgraded notice content.
*/
function getNoticeContentFromElement( element ) {
let node = element;
if ( node.firstElementChild && node.firstElementChild.nodeName === 'P' ) {
node = node.firstElementChild;
}

return node.textContent.trim();
}

/**
* Given an admin notice Element, returns the upgraded status type, or
* undefined if one cannot be determined (i.e. one is not assigned).
*
* @param {Element} element Admin notice element.
*
* @return {?string} Upgraded status type.
*/
function getNoticeStatusFromClassList( element ) {
for ( const className of element.classList ) {
const match = className.match( REGEXP_NOTICE_STATUS );
if ( match && NOTICE_STATUSES.has( match[ 1 ] ) ) {
return match[ 1 ];
}
}
}

/**
* Given an admin notice Element, returns a notices module object.
*
* @param {Element} element Admin notice element.
*
* @return {WPNotice} Notice object.
*/
function getNoticeFromElement( element ) {
const status = getNoticeStatusFromClassList( element );
const content = getNoticeContentFromElement( element );
const isDismissible = element.classList.contains( 'is-dismissible' );

return { status, content, isDismissible };
}

export class AdminNotices extends Component {
componentDidMount() {
this.convertNotices();
}

convertNotices() {
const { createNotice } = this.props;
getAdminNotices().forEach( ( element ) => {
// Convert and create.
const notice = getNoticeFromElement( element );
createNotice( notice );

// Remove (now-redundant) admin notice element.
element.parentNode.removeChild( element );
} );
}

render() {
return null;
}
}

export default withDispatch( ( dispatch ) => {
const { createNotice } = dispatch( 'core/notices' );

return { createNotice };
} )( AdminNotices );
40 changes: 40 additions & 0 deletions packages/edit-post/src/components/admin-notices/test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* External dependencies
*/
import renderer from 'react-test-renderer';

/**
* Internal dependencies
*/
import { AdminNotices } from '../';

describe( 'AdminNotices', () => {
beforeEach( () => {
// The superfluous whitespace is intentional in verifying expected
// outputs of (a) non-element first child of the element (whitespace
// text node) and (b) untrimmed content.
document.body.innerHTML = `
<div class="notice notice-success is-dismissible">
<p>
My notice text
</p>
<button type="button" class="notice-dismiss">
<span class="screen-reader-text">Dismiss this notice.</span>
</button>
</div>
`;
} );

it( 'should upgrade notices', () => {
const createNotice = jest.fn();

renderer.create( <AdminNotices createNotice={ createNotice } /> );

expect( createNotice ).toHaveBeenCalledWith( {
status: 'success',
isDismissible: true,
content: 'My notice text',
} );
expect( document.body.childElementCount ).toBe( 0 );
} );
} );
2 changes: 2 additions & 0 deletions packages/edit-post/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import Sidebar from '../sidebar';
import PluginPostPublishPanel from '../sidebar/plugin-post-publish-panel';
import PluginPrePublishPanel from '../sidebar/plugin-pre-publish-panel';
import FullscreenMode from '../fullscreen-mode';
import AdminNotices from '../admin-notices';

function Layout( {
mode,
Expand Down Expand Up @@ -69,6 +70,7 @@ function Layout( {
<BrowserURL />
<UnsavedChangesWarning />
<AutosaveMonitor />
<AdminNotices />
<Header />
<div
className="edit-post-layout__content"
Expand Down
1 change: 1 addition & 0 deletions packages/edit-post/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import '@wordpress/core-data';
import '@wordpress/editor';
import '@wordpress/nux';
import '@wordpress/viewport';
import '@wordpress/notices';
import { registerCoreBlocks } from '@wordpress/block-library';
import { render, unmountComponentAtNode } from '@wordpress/element';
import { dispatch } from '@wordpress/data';
Expand Down

0 comments on commit 18407d6

Please sign in to comment.