Skip to content

Commit

Permalink
Move Post Types Data Fetching to the core-data module
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed Mar 22, 2018
1 parent 430fa77 commit abb96ef
Show file tree
Hide file tree
Showing 15 changed files with 233 additions and 214 deletions.
14 changes: 14 additions & 0 deletions core-data/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,17 @@ export function receiveMedia( media ) {
media: castArray( media ),
};
}

/**
* Returns an action object used in signalling that post types have been received.
*
* @param {Array|Object} postTypes Post Types received.
*
* @return {Object} Action object.
*/
export function receivePostTypes( postTypes ) {
return {
type: 'RECEIVE_POST_TYPES',
postTypes: castArray( postTypes ),
};
}
21 changes: 21 additions & 0 deletions core-data/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,28 @@ export function media( state = {}, action ) {
return state;
}

/**
* Reducer managing post types state. Keyed by slug.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {string} Updated state.
*/
export function postTypes( state = {}, action ) {
switch ( action.type ) {
case 'RECEIVE_POST_TYPES':
return {
...state,
...keyBy( action.postTypes, 'slug' ),
};
}

return state;
}

export default combineReducers( {
terms,
media,
postTypes,
} );
18 changes: 17 additions & 1 deletion core-data/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import apiRequest from '@wordpress/api-request';
/**
* Internal dependencies
*/
import { setRequested, receiveTerms, receiveMedia } from './actions';
import {
setRequested,
receiveTerms,
receiveMedia,
receivePostTypes,
} from './actions';

/**
* Requests categories from the REST API, yielding action objects on request
Expand All @@ -28,3 +33,14 @@ export async function* getMedia( state, id ) {
const media = await apiRequest( { path: `/wp/v2/media/${ id }` } );
yield receiveMedia( media );
}

/**
* Requests a post type element from the REST API.
*
* @param {Object} state State tree
* @param {number} slug Post Type slug
*/
export async function* getPostType( state, slug ) {
const postType = await apiRequest( { path: `/wp/v2/types/${ slug }?context=edit` } );
yield receivePostTypes( postType );
}
12 changes: 12 additions & 0 deletions core-data/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,15 @@ export function isRequestingCategories( state ) {
export function getMedia( state, id ) {
return state.media[ id ];
}

/**
* Returns the Post Type object by slug.
*
* @param {Object} state Data state.
* @param {number} slug Post Type slug.
*
* @return {Object?} Post Type object.
*/
export function getPostType( state, slug ) {
return state.postTypes[ slug ];
}
23 changes: 22 additions & 1 deletion core-data/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import deepFreeze from 'deep-freeze';
/**
* Internal dependencies
*/
import { terms, media } from '../reducer';
import { terms, media, postTypes } from '../reducer';

describe( 'terms()', () => {
it( 'returns an empty object by default', () => {
Expand Down Expand Up @@ -88,3 +88,24 @@ describe( 'media', () => {
} );
} );
} );

describe( 'postTypes', () => {
it( 'returns an empty object by default', () => {
const state = postTypes( undefined, {} );

expect( state ).toEqual( {} );
} );

it( 'returns with received post types by slug', () => {
const originalState = deepFreeze( {} );
const state = postTypes( originalState, {
type: 'RECEIVE_POST_TYPES',
postTypes: [ { slug: 'b', title: 'beach' }, { slug: 's', title: 'sun' } ],
} );

expect( state ).toEqual( {
b: { slug: 'b', title: 'beach' },
s: { slug: 's', title: 'sun' },
} );
} );
} );
22 changes: 20 additions & 2 deletions core-data/test/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import apiRequest from '@wordpress/api-request';
/**
* Internal dependencies
*/
import { getCategories, getMedia } from '../resolvers';
import { setRequested, receiveTerms, receiveMedia } from '../actions';
import { getCategories, getMedia, getPostType } from '../resolvers';
import { setRequested, receiveTerms, receiveMedia, receivePostTypes } from '../actions';

jest.mock( '@wordpress/api-request' );

Expand Down Expand Up @@ -48,3 +48,21 @@ describe( 'getMedia', () => {
expect( received ).toEqual( receiveMedia( MEDIA ) );
} );
} );

describe( 'getPostType', () => {
const POST_TYPE = { slug: 'post' };

beforeAll( () => {
apiRequest.mockImplementation( ( options ) => {
if ( options.path === '/wp/v2/types/post?context=edit' ) {
return Promise.resolve( POST_TYPE );
}
} );
} );

it( 'yields with requested post type', async () => {
const fulfillment = getPostType( {}, 'post' );
const received = ( await fulfillment.next() ).value;
expect( received ).toEqual( receivePostTypes( POST_TYPE ) );
} );
} );
20 changes: 19 additions & 1 deletion core-data/test/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import deepFreeze from 'deep-freeze';
/**
* Internal dependencies
*/
import { getTerms, isRequestingTerms, getMedia } from '../selectors';
import { getTerms, isRequestingTerms, getMedia, getPostType } from '../selectors';

describe( 'getTerms()', () => {
it( 'returns value of terms by taxonomy', () => {
Expand Down Expand Up @@ -74,3 +74,21 @@ describe( 'getMedia', () => {
expect( getMedia( state, 1 ) ).toEqual( { id: 1 } );
} );
} );

describe( 'getPostType', () => {
it( 'should return undefined for unknown post type', () => {
const state = deepFreeze( {
postTypes: {},
} );
expect( getPostType( state, 'post' ) ).toBe( undefined );
} );

it( 'should return a post type by slug', () => {
const state = deepFreeze( {
postTypes: {
post: { slug: 'post' },
},
} );
expect( getPostType( state, 'post' ) ).toEqual( { slug: 'post' } );
} );
} );
51 changes: 18 additions & 33 deletions edit-post/components/sidebar/featured-image/index.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
/**
* External dependencies
*/
import { connect } from 'react-redux';
import { get } from 'lodash';
import { get, partial } from 'lodash';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { PanelBody, withAPIData } from '@wordpress/components';
import { PanelBody } from '@wordpress/components';
import { PostFeaturedImage, PostFeaturedImageCheck } from '@wordpress/editor';
import { compose } from '@wordpress/element';
import { withSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { isEditorSidebarPanelOpened } from '../../../store/selectors';
import { toggleGeneralSidebarEditorPanel } from '../../../store/actions';
import { withSelect, withDispatch } from '@wordpress/data';

/**
* Module Constants
Expand All @@ -30,7 +23,7 @@ function FeaturedImage( { isOpened, postType, onTogglePanel } ) {
<PanelBody
title={ get(
postType,
[ 'data', 'labels', 'featured_image' ],
[ 'labels', 'featured_image' ],
__( 'Featured Image' )
) }
opened={ isOpened }
Expand All @@ -42,34 +35,26 @@ function FeaturedImage( { isOpened, postType, onTogglePanel } ) {
);
}

const applyWithSelect = withSelect( ( select ) => ( {
postTypeSlug: select( 'core/editor' ).getEditedPostAttribute( 'type' ),
} ) );
const applyWithSelect = withSelect( ( select ) => {
const { getEditedPostAttribute } = select( 'core/editor' );
const { getPostType } = select( 'core' );
const { isEditorSidebarPanelOpened } = select( 'core/edit-post' );

return {
postType: getPostType( getEditedPostAttribute( 'type' ) ),
isOpened: isEditorSidebarPanelOpened( PANEL_NAME ),
};
} );

const applyConnect = connect(
( state ) => {
return {
isOpened: isEditorSidebarPanelOpened( state, PANEL_NAME ),
};
},
{
onTogglePanel() {
return toggleGeneralSidebarEditorPanel( PANEL_NAME );
},
},
undefined,
{ storeKey: 'edit-post' }
);
const applyWithDispatch = withDispatch( ( dispatch ) => {
const { toggleGeneralSidebarEditorPanel } = dispatch( 'core/edit-post' );

const applyWithAPIData = withAPIData( ( props ) => {
const { postTypeSlug } = props;
return {
postType: `/wp/v2/types/${ postTypeSlug }?context=edit`,
onTogglePanel: partial( toggleGeneralSidebarEditorPanel, PANEL_NAME ),
};
} );

export default compose(
applyWithSelect,
applyConnect,
applyWithAPIData,
applyWithDispatch,
)( FeaturedImage );
52 changes: 18 additions & 34 deletions edit-post/components/sidebar/page-attributes/index.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,30 @@
/**
* External dependencies
*/
import { connect } from 'react-redux';
import { get } from 'lodash';
import { get, partial } from 'lodash';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { PanelBody, PanelRow, withAPIData } from '@wordpress/components';
import { PanelBody, PanelRow } from '@wordpress/components';
import { compose } from '@wordpress/element';
import { PageAttributesCheck, PageAttributesOrder, PageAttributesParent, PageTemplate } from '@wordpress/editor';
import { withSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { toggleGeneralSidebarEditorPanel } from '../../../store/actions';
import { isEditorSidebarPanelOpened } from '../../../store/selectors';
import { withSelect, withDispatch } from '@wordpress/data';

/**
* Module Constants
*/
const PANEL_NAME = 'page-attributes';

export function PageAttributes( { isOpened, onTogglePanel, postType } ) {
if ( ! postType.data ) {
if ( ! postType ) {
return null;
}
return (
<PageAttributesCheck>
<PanelBody
title={ get( postType, 'data.labels.attributes', __( 'Page Attributes' ) ) }
title={ get( postType, 'labels.attributes', __( 'Page Attributes' ) ) }
opened={ isOpened }
onToggle={ onTogglePanel }
>
Expand All @@ -45,34 +38,25 @@ export function PageAttributes( { isOpened, onTogglePanel, postType } ) {
);
}

const applyWithSelect = withSelect( ( select ) => ( {
postTypeSlug: select( 'core/editor' ).getEditedPostAttribute( 'type' ),
} ) );
const applyWithSelect = withSelect( ( select ) => {
const { getEditedPostAttribute } = select( 'core/editor' );
const { isEditorSidebarPanelOpened } = select( 'core/edit-post' );
const { getPostType } = select( 'core' );
return {
isOpened: isEditorSidebarPanelOpened( PANEL_NAME ),
postType: getPostType( getEditedPostAttribute( 'type' ) ),
};
} );

const applyConnect = connect(
( state ) => {
return {
isOpened: isEditorSidebarPanelOpened( state, PANEL_NAME ),
};
},
{
onTogglePanel() {
return toggleGeneralSidebarEditorPanel( PANEL_NAME );
},
},
undefined,
{ storeKey: 'edit-post' }
);
const applyWithDispatch = withDispatch( ( dispatch ) => {
const { toggleGeneralSidebarEditorPanel } = dispatch( 'core/edit-post' );

const applyWithAPIData = withAPIData( ( props ) => {
const { postTypeSlug } = props;
return {
postType: `/wp/v2/types/${ postTypeSlug }?context=edit`,
onTogglePanel: partial( toggleGeneralSidebarEditorPanel, PANEL_NAME ),
};
} );

export default compose(
applyWithSelect,
applyConnect,
applyWithAPIData,
applyWithDispatch,
)( PageAttributes );
Loading

0 comments on commit abb96ef

Please sign in to comment.