Skip to content

Commit

Permalink
Add a way to programmatically remove editor panels from UI (#11802)
Browse files Browse the repository at this point in the history
* Add a way to programatically remove editor panels from UI

* Add e2e test to ensure it is possible to remove sidebar panels

* Edit post: Remove obsolete panel reducer

* Edit post: Refactor state to not persist removed panels

* Edit post: Remove old action handler for removed panels in preferences

* Docs: Update data documentation for edit-post package
  • Loading branch information
gziolo authored Nov 15, 2018
1 parent b1e11e5 commit 87d940f
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 34 deletions.
22 changes: 22 additions & 0 deletions docs/data/data-core-edit-post.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ Returns true if the publish sidebar is opened.

Whether the publish sidebar is open.

### isEditorPanelRemoved

Returns true if the given panel was programmatically removed, or false otherwise.
All panels are not removed by default.

*Parameters*

* state: Global application state.
* panelName: A string that identifies the panel.

*Returns*

Whether or not the panel is removed.

### isEditorPanelEnabled

Returns true if the given panel is enabled, or false otherwise. Panels are
Expand Down Expand Up @@ -301,6 +315,14 @@ Returns an action object used to open or close a panel in the editor.

* panelName: A string that identifies the panel to open or close.

### removeEditorPanel

Returns an action object used to remove a panel from the editor.

*Parameters*

* panelName: A string that identifies the panel to remove.

### toggleFeature

Returns an action object used to toggle a feature flag.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
import { compose } from '@wordpress/compose';
import { compose, ifCondition } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';

/**
Expand All @@ -10,9 +10,14 @@ import { withSelect, withDispatch } from '@wordpress/data';
import BaseOption from './base';

export default compose(
withSelect( ( select, { panelName } ) => ( {
isChecked: select( 'core/edit-post' ).isEditorPanelEnabled( panelName ),
} ) ),
withSelect( ( select, { panelName } ) => {
const { isEditorPanelEnabled, isEditorPanelRemoved } = select( 'core/edit-post' );
return {
isRemoved: isEditorPanelRemoved( panelName ),
isChecked: isEditorPanelEnabled( panelName ),
};
} ),
ifCondition( ( { isRemoved } ) => ! isRemoved ),
withDispatch( ( dispatch, { panelName } ) => ( {
onChange: () => dispatch( 'core/edit-post' ).toggleEditorPanelEnabled( panelName ),
} ) )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,22 @@ exports[`OptionsModal should match snapshot when the modal is active 1`] = `
<WithSelect(PostTaxonomies)
taxonomyWrapper={[Function]}
/>
<WithSelect(WithDispatch(BaseOption))
<WithSelect(IfCondition(WithDispatch(BaseOption)))
label="Featured Image"
panelName="featured-image"
/>
<PostExcerptCheck>
<WithSelect(WithDispatch(BaseOption))
<WithSelect(IfCondition(WithDispatch(BaseOption)))
label="Excerpt"
panelName="post-excerpt"
/>
</PostExcerptCheck>
<WithSelect(WithDispatch(BaseOption))
<WithSelect(IfCondition(WithDispatch(BaseOption)))
label="Discussion"
panelName="discussion-panel"
/>
<WithSelect(PageAttributesCheck)>
<WithSelect(WithDispatch(BaseOption))
<WithSelect(IfCondition(WithDispatch(BaseOption)))
label="Page Attributes"
panelName="page-attributes"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ exports[`MetaBoxesSection renders a Custom Fields option and meta box options 1`
<WithSelect(EnableCustomFieldsOption)
label="Custom Fields"
/>
<WithSelect(WithDispatch(BaseOption))
<WithSelect(IfCondition(WithDispatch(BaseOption)))
key="test1"
label="Meta Box 1"
panelName="meta-box-test1"
/>
<WithSelect(WithDispatch(BaseOption))
<WithSelect(IfCondition(WithDispatch(BaseOption)))
key="test2"
label="Meta Box 2"
panelName="meta-box-test2"
Expand All @@ -34,12 +34,12 @@ exports[`MetaBoxesSection renders meta box options 1`] = `
<Section
title="Advanced Panels"
>
<WithSelect(WithDispatch(BaseOption))
<WithSelect(IfCondition(WithDispatch(BaseOption)))
key="test1"
label="Meta Box 1"
panelName="meta-box-test1"
/>
<WithSelect(WithDispatch(BaseOption))
<WithSelect(IfCondition(WithDispatch(BaseOption)))
key="test2"
label="Meta Box 2"
panelName="meta-box-test2"
Expand Down
14 changes: 14 additions & 0 deletions packages/edit-post/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ export function toggleEditorPanelOpened( panelName ) {
};
}

/**
* Returns an action object used to remove a panel from the editor.
*
* @param {string} panelName A string that identifies the panel to remove.
*
* @return {Object} Action object.
*/
export function removeEditorPanel( panelName ) {
return {
type: 'REMOVE_PANEL',
panelName,
};
}

/**
* Returns an action object used to toggle a feature flag.
*
Expand Down
39 changes: 26 additions & 13 deletions packages/edit-post/src/store/reducer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { get } from 'lodash';
import { get, includes } from 'lodash';

/**
* WordPress dependencies
Expand Down Expand Up @@ -105,6 +105,28 @@ export const preferences = combineReducers( {
},
} );

/**
* Reducer storing the list of all programmatically removed panels.
*
* @param {Array} state Current state.
* @param {Object} action Action object.
*
* @return {Array} Updated state.
*/
export function removedPanels( state = [], action ) {
switch ( action.type ) {
case 'REMOVE_PANEL':
if ( ! includes( state, action.panelName ) ) {
return [
...state,
action.panelName,
];
}
}

return state;
}

/**
* Reducer returning the next active general sidebar state. The active general
* sidebar is a unique name to identify either an editor or plugin sidebar.
Expand All @@ -123,15 +145,6 @@ export function activeGeneralSidebar( state = DEFAULT_ACTIVE_GENERAL_SIDEBAR, ac
return state;
}

export function panel( state = 'document', action ) {
switch ( action.type ) {
case 'SET_ACTIVE_PANEL':
return action.panel;
}

return state;
}

/**
* Reducer for storing the name of the open modal, or null if no modal is open.
*
Expand Down Expand Up @@ -207,10 +220,10 @@ const metaBoxes = combineReducers( {
} );

export default combineReducers( {
preferences,
activeGeneralSidebar,
panel,
activeModal,
publishSidebarActive,
metaBoxes,
preferences,
publishSidebarActive,
removedPanels,
} );
17 changes: 16 additions & 1 deletion packages/edit-post/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ export function isPublishSidebarOpened( state ) {
return state.publishSidebarActive;
}

/**
* Returns true if the given panel was programmatically removed, or false otherwise.
* All panels are not removed by default.
*
* @param {Object} state Global application state.
* @param {string} panelName A string that identifies the panel.
*
* @return {boolean} Whether or not the panel is removed.
*/
export function isEditorPanelRemoved( state, panelName ) {
return includes( state.removedPanels, panelName );
}

/**
* Returns true if the given panel is enabled, or false otherwise. Panels are
* enabled by default.
Expand All @@ -110,7 +123,9 @@ export function isPublishSidebarOpened( state ) {
*/
export function isEditorPanelEnabled( state, panelName ) {
const panels = getPreference( state, 'panels' );
return get( panels, [ panelName, 'enabled' ], true );

return ! isEditorPanelRemoved( state, panelName ) &&
get( panels, [ panelName, 'enabled' ], true );
}

/**
Expand Down
10 changes: 10 additions & 0 deletions packages/edit-post/src/store/test/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import {
toggleEditorPanelEnabled,
toggleEditorPanelOpened,
removeEditorPanel,
openGeneralSidebar,
closeGeneralSidebar,
openPublishSidebar,
Expand Down Expand Up @@ -59,6 +60,15 @@ describe( 'actions', () => {
} );
} );

describe( 'removeEditorPanel', () => {
it( 'should return a REMOVE_PANEL action', () => {
expect( removeEditorPanel( 'post-status' ) ).toEqual( {
type: 'REMOVE_PANEL',
panelName: 'post-status',
} );
} );
} );

describe( 'toggleEditorPanelEnabled', () => {
it( 'should return a TOGGLE_PANEL_ENABLED action', () => {
expect( toggleEditorPanelEnabled( 'post-status' ) ).toEqual( {
Expand Down
21 changes: 21 additions & 0 deletions packages/edit-post/src/store/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
activeModal,
isSavingMetaBoxes,
metaBoxLocations,
removedPanels,
} from '../reducer';

describe( 'state', () => {
Expand Down Expand Up @@ -313,4 +314,24 @@ describe( 'state', () => {
} );
} );
} );

describe( 'removedPanels', () => {
it( 'should remove panel', () => {
const original = deepFreeze( [] );
const state = removedPanels( original, {
type: 'REMOVE_PANEL',
panelName: 'post-status',
} );
expect( state ).toEqual( [ 'post-status' ] );
} );

it( 'should not remove already removed panel', () => {
const original = deepFreeze( [ 'post-status' ] );
const state = removedPanels( original, {
type: 'REMOVE_PANEL',
panelName: 'post-status',
} );
expect( state ).toBe( original );
} );
} );
} );
41 changes: 41 additions & 0 deletions packages/edit-post/src/store/test/selectors.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';

/**
* Internal dependencies
*/
Expand All @@ -16,6 +21,7 @@ import {
getActiveMetaBoxLocations,
isMetaBoxLocationActive,
isEditorPanelEnabled,
isEditorPanelRemoved,
} from '../selectors';

describe( 'selectors', () => {
Expand Down Expand Up @@ -195,6 +201,26 @@ describe( 'selectors', () => {
} );
} );

describe( 'isEditorPanelRemoved', () => {
it( 'should return false by default', () => {
const state = deepFreeze( {
removedPanels: [],
} );

expect( isEditorPanelRemoved( state, 'post-status' ) ).toBe( false );
} );

it( 'should return true when panel was removed', () => {
const state = deepFreeze( {
removedPanels: [
'post-status',
],
} );

expect( isEditorPanelRemoved( state, 'post-status' ) ).toBe( true );
} );
} );

describe( 'isEditorPanelEnabled', () => {
it( 'should return true by default', () => {
const state = {
Expand Down Expand Up @@ -229,6 +255,21 @@ describe( 'selectors', () => {

expect( isEditorPanelEnabled( state, 'post-status' ) ).toBe( false );
} );

it( 'should return false when a panel is enabled but removed', () => {
const state = deepFreeze( {
preferences: {
panels: {
'post-status': {
enabled: true,
},
},
},
removedPanels: [ 'post-status' ],
} );

expect( isEditorPanelEnabled( state, 'post-status' ) ).toBe( false );
} );
} );

describe( 'isEditorPanelOpened', () => {
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/specs/new-post-default-content.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Internal dependencies
*/
import { newPost, getEditedPostContent, openDocumentSettingsSidebar } from '../support/utils';
import { findSidebarPanelWithTitle, newPost, getEditedPostContent, openDocumentSettingsSidebar } from '../support/utils';
import { activatePlugin, deactivatePlugin } from '../support/plugins';

describe( 'new editor filtered state', () => {
Expand All @@ -27,7 +27,7 @@ describe( 'new editor filtered state', () => {

// open the sidebar, we want to see the excerpt.
await openDocumentSettingsSidebar();
const [ excerptButton ] = await page.$x( '//div[@class="edit-post-sidebar"]//button[@class="components-button components-panel__body-toggle"][contains(text(),"Excerpt")]' );
const excerptButton = await findSidebarPanelWithTitle( 'Excerpt' );
if ( excerptButton ) {
await excerptButton.click( 'button' );
}
Expand Down
Loading

0 comments on commit 87d940f

Please sign in to comment.