Skip to content

Conversation

@youknowriad
Copy link
Contributor

@youknowriad youknowriad commented Jul 20, 2018

This PR tries to remove all wp.api usage from the "editor" package.

Notes

  • Splits effects file for sanity and also to make it easier to use async/await
  • Adds a resolveSelector utility function that waits for the resolution of the selector before returning a promise with its value.
  • Replaces wp.api.getPostTypeRoute with select( 'core' ).getPostType( getCurrentPostType( state ) ).rest_base

Testing instructions

  • Ensure shared blocks work
  • Ensure taxonomy selectors work
  • Ensure saving posts work

@@ -0,0 +1,320 @@
/**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For more sanity and also because it's easier to use async/await this way, I extracted some effects handler into their own files.

REQUEST_POST_UPDATE_SUCCESS: requestPostUpdateSuccess,
REQUEST_POST_UPDATE_FAILURE: requestPostUpdateFailure,
TRASH_POST: ( action, store ) => {
trashPost( action, store );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't assign it directly because there's a warning if we return a promise from effect handlers

const getResult = () => select( namespace )[ selectorName ].apply( null, args );

const unsubscribe = subscribe( () => {
if ( hasFinished() ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where it's not working at the moment, I'm not certain why but hasFinished is never true.

  • Try to edit a post and click "save draft", nothing happens because it's stuck here.

cc @aduth

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to better distill what has exactly changed with the effects file refactoring. I will wait until you are online before I continue. In general, I like the direction where it is heading. It will also help us to address #7397 with the removel of withAPIData usage.

hasCreateAction: taxonomy ? get( getCurrentPost(), [ '_links', 'wp:action-create-' + taxonomy.rest_base ], false ) : false,
hasAssignAction: taxonomy ? get( getCurrentPost(), [ '_links', 'wp:action-assign-' + taxonomy.rest_base ], false ) : false,
terms: taxonomy ? select( 'core/editor' ).getEditedPostAttribute( taxonomy.rest_base ) : [],
taxonomy,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we pass down restBase instead of full taxonomy object? I think only this one field is used in the component. It would also align better with what we had before.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this made me think, what will happen when taxonomy is falsy? We don't check against it inside the component.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We check against hasAssignAction which is false if the taxonomy is falsy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the taxonomy object is used for labels as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we expect to refactor this component so that it's not calling apiFetch at all? This was a hope of mine. Wondering if it would make things easier to do this conversion first, before this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should do it, the thing is, it's not ready at the moment because we need paginated/query data in core-data. Hopefully we can get back to that once we publish those remaining packages.

hasCreateAction: taxonomy ? get( getCurrentPost(), [ '_links', 'wp:action-create-' + taxonomy.rest_base ], false ) : false,
hasAssignAction: taxonomy ? get( getCurrentPost(), [ '_links', 'wp:action-assign-' + taxonomy.rest_base ], false ) : false,
terms: taxonomy ? select( 'core/editor' ).getEditedPostAttribute( taxonomy.rest_base ) : [],
taxonomy,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I echo my previous concerns regarding taxonomy and rest_base.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I added a check for this specific component

@gziolo gziolo added npm Packages Related to npm packages [Type] Code Quality Issues or PRs that relate to code quality labels Jul 23, 2018
@gziolo gziolo added this to the 3.4 milestone Jul 23, 2018
*
* @return {Promise} Selector result.
*/
export function resolveSelector( namespace, selectorName, ...args ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This utility or something equivalent will be bundled in the data module once we land the async actions work.

@youknowriad youknowriad force-pushed the remove/ap-api-from-editor branch from 4d993d5 to 8fce9d6 Compare July 23, 2018 13:48
@youknowriad youknowriad force-pushed the remove/ap-api-from-editor branch from 8fce9d6 to a5f4c9d Compare July 23, 2018 14:16
@youknowriad youknowriad changed the title WIP: Remove all wp.api Usage from the editor package Remove all wp.api Usage from the editor package Jul 24, 2018
Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One nitpick so far, I will continue tomorrow. taxonomy changes look good as a temporary solution. I double checked your comments 👍

"dom-scroll-into-view": "1.2.1",
"element-closest": "2.0.2",
"equivalent-key-map": "0.2.0",
"equivalent-key-map": "0.2.1",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove it from here, it is used only in data package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, I didn't understand, removing it break the unit tests (but only on travis)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice I removed it and than added it back in the commits

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there went something wrong with package-lock.json. We can clean it up when all packages are there, no worries 👍

@gwwar gwwar requested a review from vindl July 25, 2018 14:35
@Copons
Copy link
Contributor

Copons commented Jul 25, 2018

Not sure if relevant, but I've found a wp.api here:

// APIProvider
//
// - context.getAPISchema
// - context.getAPIPostTypeRestBaseMapping
// - context.getAPITaxonomyRestBaseMapping
[
APIProvider,
{
...wpApiSettings,
...pick( wp.api, [
'postTypeRestBaseMapping',
'taxonomyRestBaseMapping',
] ),
},
],

@Copons
Copy link
Contributor

Copons commented Jul 25, 2018

Tested for a bit and couldn't break anything! ✨

  • Ensure shared blocks work
  • Ensure taxonomy selectors work
  • Ensure saving posts work

@gwwar
Copy link
Contributor

gwwar commented Jul 25, 2018

Re:

// APIProvider
//
// - context.getAPISchema
// - context.getAPIPostTypeRestBaseMapping
// - context.getAPITaxonomyRestBaseMapping
[
APIProvider,
{
...wpApiSettings,
...pick( wp.api, [
'postTypeRestBaseMapping',
'taxonomyRestBaseMapping',
] ),
},
],

It looks like wpApiSettings, wp.api.postTypeRestBaseMapping and wp.api.taxonomyRestBaseMapping are all globals, and we'll run into trouble trying to resolve these in the published package.

Could we provide defaults, or pass through props to this component, with a fallback to globals if they exist?

@youknowriad
Copy link
Contributor Author

Good catch @gwwar and @Copons I feel like we can get rid of them entirely as withApiData is meant to be deprecated anyway. I'll see tomorrow if I can refactor the components using them.


// We need to trigger the selector (to trigger the resolver)
const result = getResult();
if ( hasFinished() ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can unsubscribe be declared after this if statement so we wouldn't have to subscribe it if is already finished?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit test passes, so it should be good :)

} );

// Trigger resolution
const value = await resolveSelector( 'resolveStore', 'selectAll', 'check' );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be resolveStore2?


describe( 'resolveSelector', () => {
it( 'Should wait for selector resolution', async () => {
registerStore( 'resolveStore', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make to extract the store definitions as follows:

	const resolveStore = {
		reducer: ( state = 'no', action ) => {
			if ( action.type === 'resolve' ) {
				return 'yes';
			}
			return state;
		},
		selectors: {
			selectAll: ( state, key ) => ( key === 'check' ) ? state : 'no-key',
		},
		resolvers: {
			selectAll: () => {
				return new Promise( ( resolve ) => {
					process.nextTick( () => resolve( { type: 'resolve' } ) );
				} );
			},
		},
	};

and share it between those 2 tests?

if ( action.type === 'resolve' ) {
return 'yes';
}
if ( action.type === 'reset' ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type is never used. Removing it doesn't break any test.

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I finished my review, how do you feel about addressing smaller things in this PR and opening a follow up for what @Copons discovered? This PR is already big and I bet we will have to move Provider code outside of editor to make it backward compatible. We need to ensure withAPIData works for some time before we fully deprecate it.

dispatch( removeNotice( TRASH_POST_NOTICE_ID ) );
try {
await apiFetch( { path: `/wp/v2/${ postType.rest_base }/${ postId }`, method: 'DELETE' } );
} catch ( error ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this code missing after apiFetch when comparing with master:

const post = getCurrentPost( getState() );

// TODO: This should be an updatePost action (updating subsets of post properties),
// But right now editPost is tied with change detection.
dispatch( resetPost( { ...post, status: 'trash' } ) );

Is that expected change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not, I wonder how this happened :P

// TODO: these are potentially undefined, this fix is in place
// until there is a filter to not use shared blocks if undefined
const postType = await resolveSelector( 'core', 'getPostType', 'wp_block' );
if ( ! postType ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to check the return value for this selector. We should ensure it is not an empty object because this check will fail.

Just in case it's necessary, there are 2 more places where we have the same check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be an empty object, if the state is not there for some reason, it will be undefined and it will be the right post type if not. I wonder if we can't just remove the check entirely actually :P

@gziolo
Copy link
Member

gziolo commented Jul 26, 2018

It looks like wpApiSettings, wp.api.postTypeRestBaseMapping and wp.api.taxonomyRestBaseMapping are all globals, and we'll run into trouble trying to resolve these in the published package.

Could we provide defaults, or pass through props to this component, with a fallback to globals if they exist?

It looks like @youknowriad found a really nice solution for that one :)

@youknowriad
Copy link
Contributor Author

I removed the remaining dependencies to wp.api. I didn't deprecate withAPIData yet but I think we're ready for it. This PR should be ready to go.

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested locally a similar set of functionalities as @Copons did. Everything works as expected. Travis is failing with one of the e2e tests, but it's a known issue and we have open PR to fix it. I restart build. Feel free to merge as soon as it turns green.

Great job with this refactor 🥇

@youknowriad youknowriad merged commit 740de8d into master Jul 26, 2018
@youknowriad youknowriad deleted the remove/ap-api-from-editor branch July 26, 2018 11:03
APIProvider,
{
...wpApiSettings,
...pick( wp.api, [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const TRASH_POST_NOTICE_ID = 'TRASH_POST_NOTICE_ID';

/**
* Request Post Update Effect handler
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These JSDoc descriptions really go to reinforce my worry that we don't really have a good understanding of what's intended to take place in these functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

npm Packages Related to npm packages [Type] Code Quality Issues or PRs that relate to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants