-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Edit Post: Refactor state handling for the sidebar #5435
Conversation
edit-post/components/header/index.js
Outdated
isPublishSidebarOpen: isPublishSidebarOpened( state ), | ||
hasActiveMetaboxes: hasMetaBoxes( state ), | ||
isSaving: isSavingMetaBoxes( state ), | ||
} ), | ||
{ | ||
onOpenGeneralSidebar: () => openGeneralSidebar( 'editor' ), | ||
onOpenGeneralSidebar: openGeneralSidebar.bind( 'edit-post/document' ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the argument be the second parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, probably it's a better idea to stick with the arrow function 😃
5aa31d4
to
24aed5b
Compare
@@ -93,6 +96,5 @@ export function getSidebarSettings( name ) { | |||
* @return {void} | |||
*/ | |||
export function activateSidebar( name ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@omarreiss @xyfi @IreneStr, can we get rid of this function completely and start using dispatch( 'edit-post' ).openGeneralSidebar( name );
directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question 2, should we rename openGeneralSidebar
to openEditorSidebar
and use the name editor sidebar in other places?
On the other hand, I created isEditorSidebarOpened
selector to check if block or document settings are opened in the sidebar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it would be fine to get rid of this function. I still see the use for a higher level API like this because it simply requires less knowledge of the user. But maybe it is a bit premature to be adding API's like this one at this stage. I would like to make a knowledge matrix further down the road to map what knowledge is needed to solve a particular kind of problem in Gutenberg as a plugin author. Based on that we could always decide to reintroduce helpers like this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will open a separate PR for that together with docs update. This PR got big once I started integrating data
module. We can wrap it later back with something that you will find out helpful when integrating plugins.
24aed5b
to
b9f56de
Compare
b9f56de
to
bc8cced
Compare
4bfe64f
to
4c9d517
Compare
const generalSidebarOpen = getPreference( state, 'activeGeneralSidebar' ) !== null; | ||
const publishSidebarOpen = state.publishSidebarActive; | ||
|
||
return generalSidebarOpen || publishSidebarOpen; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are still using a specific flag for publish sidebar, should we consolidate the behaviors and remove the flag from state?
Another point should we have a flag that tells if sidebars are open, and one property that tells the current sidebar that is open or will be open if sidebar flag is toggled?
The advantages being we can have a button to close and open the last sidebar, without resetting the last sidebar to close it. We would also be able to have open flags for different view sizes allowing us to recover the mobile behaviour where mobile sidebars open and close state is totally independent from desktop one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are still using a specific flag for publish sidebar, should we consolidate the behaviors and remove the flag from state?
That would be awesome. However, they have different UI. I didn't want to touch it as part of this PR, but rather focus on the code that might remove some code duplication between the editor and plugins.
Another point should we have a flag that tells if sidebars are open, and one property that tells the current sidebar that is open or will be open if sidebar flag is toggled?
This might be tricky because of how you interact with the editor. When you open the right side menu of the block you want to see the advanced setting of the block. When you click on the cog button in the header you rather expect to see the document settings, but definitely not the last open plugin. So I would say toggling for the last open sidebar might be not the best fit in many cases. Did you have something different in mind? I might not understand your reasoning correctly. This thing is really tricky because of so many factors involved :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you click on the cog button in the header you rather expect to see the document settings, but definitely not the last open plugin.
Yes, that's true, but in that case, the cog button whould trigger, an action to change the sidebar to the general one and another action to open the sidebar.
I think my basic idea is the following: we have one or more flags (e.g: mobile and desktop) that say if a sidebar is opened or not. So our sidebar checking logic is trivial.
We also have one field with the sidebar id of the sidebar that is opened or that if sidebars are shown should be rendered (with the open sidebar action) we can also trigger an action to change the sidebar.
The sidebar components would check the flag to see if sidebars are opened and the id of the sidebar to check if they should render or not.
This is something we can do after e.g: as part of a mobile improvement, or as part of a refactor of our own sidebars to use the extensibility mechanism.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should definitely explore that further. Thanks for sharing your ideas 👍
{ storeKey: 'edit-post' } | ||
export default compose( | ||
withSelect( ( select ) => ( { | ||
isEditorSidebarOpened: select( 'core/edit-post' ).isEditorSidebarOpened(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not directly related to this pr, and even if we decide to some change it should not be in this PR. We are always repeating select( 'core/edit-post' ). This makes me wonder if we should not do something like: const editPostSelect = select( 'core/edit-post' ). Or add an argument to withSelect like withSelect( 'core/edit-post', ( select )...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW this is how I'd documented examples in the updated @wordpress/data
documentation:
While it means you can't do an implicit arrow return, I think the whole thing ends up being more readable overall (implicit arrow returns for objects are always questionable).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it has been discussed a few times in the past. I will find some link and share on Monday :) I might even share a similar idea you mentioned: withSelect( 'core/edit-post', ( select )
. I think I saw @aduth using the following:
withSelect( ( select) => {
const { mySelector } = select( 'core/edit-post' );
return {
// some code here
};
} );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aduth I want to refactor all connect occurrences in the edit-post module next week to see if it has any impact on the module’s bundle size. I’ll follow your advice despite the fact that I personally like this short notation 😃
export function isEditorSidebarOpened( state ) { | ||
const activeGeneralSidebar = getPreference( state, 'activeGeneralSidebar', null ); | ||
|
||
return [ 'edit-post/document', 'edit-post/block' ].includes( activeGeneralSidebar ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To check if a sidebar is active ( the general one) we check a property of the sidebar (which of tabs is opened). That seems like a good improvement to do next. Have an identifier for the general sidebar 'edit-post/general'. The logic to check if the general sidebar is opened or not should not use an internal property of the general sidebar which of the tabs is opened.
The tab of the general sidebar should only be used when rendering that sidebar, as it should be just a config of that sidebar. The tab logic of the general sidebar should be specified in an identical way to what a plugin needing tabs would do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Array#includes
is not polyfilled. This will error in IE11. Use _.includes
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wanted to clarify as I'm about to sign off for the weekend and apparently not thinking clear enough :)
Do you propose to combine those two sidebars into one that contains two tabs and display only one depending on the internal state (block vs document)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add a commit in the PR #5528 that also solves this includes problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing ❤️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested the changes here and I did not find any obvious regressions.
This simplifies a lot the code, nice job 👍
I think there are still some improvements/simplifications that could be made, I left some comments and discussions here can be a basis for future improvements. The improvements should not block the merging of this as the further improvements can be done in other PR's to avoid increasing the size of this PR.
{ storeKey: 'edit-post' } | ||
export default compose( | ||
withSelect( ( select ) => ( { | ||
isEditorSidebarOpened: select( 'core/edit-post' ).isEditorSidebarOpened(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW this is how I'd documented examples in the updated @wordpress/data
documentation:
While it means you can't do an implicit arrow return, I think the whole thing ends up being more readable overall (implicit arrow returns for objects are always questionable).
export function isEditorSidebarOpened( state ) { | ||
const activeGeneralSidebar = getPreference( state, 'activeGeneralSidebar', null ); | ||
|
||
return [ 'edit-post/document', 'edit-post/block' ].includes( activeGeneralSidebar ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Array#includes
is not polyfilled. This will error in IE11. Use _.includes
instead.
export function getActiveGeneralSidebarName( state ) { | ||
const activeGeneralSidebar = getPreference( state, 'activeGeneralSidebar', null ); | ||
|
||
return activeGeneralSidebar && ( isEditorSidebarOpened( state ) || isPluginSidebarOpened( state ) ) ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So... activeGeneralSidebar
is not always expected to align with the value of isEditorSidebarOpened( state ) || isPluginSidebarOpened( state )
? When does this occur? When someone tries to activate a sidebar for which there are no settings? Should that be allowed / optimized for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had an early return when there is no value set. It can be now removed as I created those two helper methods.
The things get complex with the plugins when you activate a plugin sidebar, leave the page and deactivate plugin. The value is persisted so next time you visit Gutenberg it tries to load the sidebar but there is no code there. That’s way isPluginSidebarOpen does additional checks. I hope to further optimize it once the new plugin API is finalized. We could also reset the value when about to render on initial page load. If you have better ideas let us know 😃
@jorgefilipecosta thanks for your review and great comments. Let's continue the discussion on the next steps here in parallel to the ongoing work on #5430. As soon as that PR is merged we can take next steps 👍 |
Here's how the editor looks in IE11 after this merge: See: #5435 (comment) |
@aduth thanks for catching the issue with IE and includes. @jorgefilipecosta thanks for super quick fix. I searched for the occurrences of Array method and I found a few... I wasn’t aware they don’t work 😃 |
Description
Follow-up for #4777.
This PR aims to simplify the state management for the sidebars to make it easier to maintain with the upcoming changes from #5430. I figured out we can treat
editor
related sidebars in a similar way as plugins (maybe even combine them in the future) and store the active sidebar name together. I could take this approach because they are mutually exclusive in a sense that you can display only one of them at the same time in the same space.At the same time, I refactored a few updated files to make them work with the new
data
module to get a better feeling how it all integrates with our codebase.How Has This Been Tested?
Register sidebar using the following code:
To activate it use the following:
I tested the following manually:
Show Advanced Settings
button.Hide Advanced Settings
button.All unit tests should still pass:
npm test
.Screenshots (jpeg or gifs if applicable):
Types of changes
Refactoring.
Checklist: