Skip to content
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

Adding initial metabox support. #2583

Closed
wants to merge 1 commit into from

Conversation

BE-Webdesign
Copy link
Contributor

This is an imcomplete task but here is an initial jab at adding meta box
support. Keep it on the DL for now.

@BE-Webdesign BE-Webdesign added Needs Design Needs design efforts. Needs Design Feedback Needs general design feedback. [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible [Status] In Progress Tracking issues with work in progress labels Aug 28, 2017
@BE-Webdesign
Copy link
Contributor Author

BE-Webdesign commented Aug 28, 2017

A lot of things to do still but at least this works.

Technical things that still need to be done:

  • Incorporate SASS variables into the build for the metabox CSS. ( Could still use more of this though for styles actually in the iframe ).
  • Have Gutenberg trigger updates of the extended settings.
  • Somehow, not sure if this is possible, incorporate iframes of the sidebar metaboxes into the sidebar. It is most likely possible, but will be tricky.
  • Removing silly comments.
  • Assessing viability of approach.
  • Removing standard core metaboxes that are not needed.
  • Adding JavaScript to ensure the metaboxes track the state of the Sidebar. Will probably need to use selectors and some event listeners. It will be ugly. Alternatively suggested by Riad, have Redux/React control the state of the iframe. This is probably the better way forward.
  • Extensive Testing. Will need to get this PR into better shape before doing a testing call. Feedback on what glaring flaws there are already could help get this to a testable state sooner.
  • Get Yoast to work. This is important as other plugins may rely on the classic editor and title values. These fields will need to be disabled however in order to prevent them from conflicting with the update of these values sent by Gutenberg.
  • We will need a way to mark the state as "dirty", when metabox values are changed.
  • Error handling.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

This looks like the path we should take. Amazing work

I tried yoast and I guess yoast reads the editor's title and content to update its UI, I was wondering if we could add a hidden input for the title and a hidden TinyMCE for the post content, keeping them in sync with Gutenberg. Would the Yoast metabox (and other metaboxes relying on the editor) work as expected in this case?

Also, can we avoid the "update settings" button at all? Relying on Gutenberg publish button, when we hit it, submit the metaboxes and then fetch the post, apply Gutenberg edits and save it.

I left some notes, but I must say I'm not very familiar with this area.

*/
?>
<header class="gutenberg-metaboxes__header" style="<?php echo $heading_style; ?>">
<h2 style="font-size: 14px;">Extended Settings</h2>
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we get this out of the iframe and show it inside the Gutenberg editor instead and keep only the content in the iframe?. This would allow us to tie this easily to the state (toggle open/close), show a loading maybe while still loading the iframe.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, if we can take the submit button out of the heading and have Gutenberg trigger this, then we should also be able to have the editor state toggling the state of the metabox area.

<div class="gutenberg-metaboxes">
<div id="postbox-container-2" class="postbox-container">
<?php
$locations = array( 'normal', 'advanced', 'side' );
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we split this into two iframes, one containing advanced and normal locations (like the current one) and show the side metaboxes in the sidebar? Not sure about this, but just asking

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 know if that will be possible, as the sidebar is managed by React. I could do something similar to what James did as well. Also definitely worth a try. One of the advantages of using the approach taken here is that it will be relatively easy to split different metabox groups into separate iframes etc. So rather than looping like we are here, we can have a query param specify whether we are rendering the normal, advanced, or side location.

?>
<header class="gutenberg-metaboxes__header" style="<?php echo $heading_style; ?>">
<h2 style="font-size: 14px;">Extended Settings</h2>
<input name="save" type="submit" class="button button-primary button-large" id="publish" value="Update Settings">
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we move this out of the iframe, catch the click, submit the iframe and maybe refetch the post object to the Gutenberg state on success?

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 so. Definitely worth a try.

@BE-Webdesign
Copy link
Contributor Author

I tried yoast and I guess yoast reads the editor's title and content to update its UI, I was wondering if we could add a hidden input for the title and a hidden TinyMCE for the post content, keeping them in sync with Gutenberg. Would the Yoast metabox (and other metaboxes relying on the editor) work as expected in this case?

Also, can we avoid the "update settings" button at all? Relying on Gutenberg publish button, when we hit it, submit the metaboxes and then fetch the post, apply Gutenberg edits and save it.

Yeah, these are all really good ideas. The Yoast one will be tricky to do, but I was thinking of a similar approach. We can definitely get rid of the update settings button.

I left some notes, but I must say I'm not very familiar with this area.

Same.

I will probably have time after tomorrows meeting to work more on this, and polish it up. Hopefully the meeting can give us some more insightful feedback as well. I like the idea of trying to integrate it more into React/Redux world, but we should bounce that idea off of others as well.

$notice = false;
$form_extra = '';
if ( 'auto-draft' == $post->post_status ) {
if ( 'edit' == $action )
Copy link
Member

Choose a reason for hiding this comment

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

Getting a notice here at this line:

Notice: Undefined variable: action in /srv/www/editor/htdocs/wp-content/plugins/gutenberg/lib/metabox-api.php on line 204

</html>

<?php
exit( 'YOLO, Gutenberg metaboxes in da haus' );
Copy link
Member

Choose a reason for hiding this comment

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

😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's the only true way to exit.

lib/register.php Outdated
global $post;
$post_id = $post->ID;
$meta_box_api_url = get_admin_url();
$meta_box_api_url = $meta_box_api_url . 'post.php';
Copy link
Member

Choose a reason for hiding this comment

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

Could consolidate these two lines as admin_url( 'post.php' )

@aaronjorbin
Copy link
Member

Also, can we avoid the "update settings" button at all? Relying on Gutenberg publish button, when we hit it, submit the metaboxes and then fetch the post, apply Gutenberg edits and save it.

I think I remember there being issues, but I can't exactly remember what, related to AJAX saving of metadata. This came up during the last distraction free writing update. @iseulde do you remember? There likely is a core ticket somewhere with this info.

Also, it shouldn't just be on publish that metadata is saved.

return;
} // don't run for server side render

let
Copy link
Member

Choose a reason for hiding this comment

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

Given that this is enqueued verbatim, the ES2015 let won't fly in IE11. I wonder if we need a huge library for this, or if we can lean on prior art like the Sandbox component frame observing or similar frame resizing in mce-view.js.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, let got put in because I ran an eslint fix on these files. so the original I found is just straight es5. I think finding something smaller is a better solution though.

'metabox-resizing-gutenberg',
gutenberg_url( 'assets/js/iframeResizer.js' ),
array( 'jquery' ),
filemtime( gutenberg_dir_path() . 'assets/js/iframeResizer.js' ),
Copy link
Member

Choose a reason for hiding this comment

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

Since this is an external script, should we use the version number?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, definitely, this will probably be a throwaway script though. Aduth pointed out there are already iframe resizing things being done in Gutenberg.

@aduth
Copy link
Member

aduth commented Aug 30, 2017

My initial thoughts with iframes was more of a per-metabox approach, but in reflecting on the implementation and some of the discussion here, I think a single iframe could work well. Particularly if we want to try to emulate fields of the current editor (the example of Yoast reading from title). I could imagine the iframe rendering these fields, visually hidden from the user but kept in sync with the parent Gutenberg screen. Already mentioned, but the challenging part is coordinating this sync:

  • If a field in Gutenberg changes, how do we communicate this to the metabox iframe?
  • If the Gutenberg post is saved, how do we relay this same command to the metabox iframe?
  • Conversely, if a metabox field changes, how do we surface this back up to the Gutenberg editor (particularly for flagging as needing save)?

I foresee abundant (ab)use of postMessage 😄

Edit: Since the frames are same origin, maybe we don't need postMessage and can simply call into the frame's contentWindow, and window.parent from the frame.

die( 'Silence is golden.' );
}

function gutenberg_meta_box_api() {
Copy link
Member

Choose a reason for hiding this comment

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

The "API" naming here could be misleading. It's not really much of an API (at least in the RESTful sense), more just a partial page.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

gutenberg_metabox_partial_page()?

@BE-Webdesign
Copy link
Contributor Author

I think I remember there being issues, but I can't exactly remember what, related to AJAX saving of metadata. This came up during the last distraction free writing update. @iseulde do you remember? There likely is a core ticket somewhere with this info.

Also, it shouldn't just be on publish that metadata is saved.

We will definitely want to check that out. We want metadata saved on Publish and Update correct? Draft saving as well I imagine?

@aaronjorbin
Copy link
Member

We will definitely want to check that out. We want metadata saved on Publish and Update correct? Draft saving as well I imagine?

If the UI says "saved", users will expect that all content on the page is saved. Users should never have to know the difference between what is "the javascript based editor" and what is "an iframe".

@BE-Webdesign
Copy link
Contributor Author

Sounds good

@BE-Webdesign
Copy link
Contributor Author

BE-Webdesign commented Sep 2, 2017

Interesting new hurdles of using Redux/React:

  • We will need a way to mark the state as "dirty", when metabox values are changed.

A solution to this could create mutation observers for the iframes and when they detect a change we can mark the post as "dirty". I think that would work well but would love to hear other ideas.

  • Triggering the submission of a form in an iframe from JS rather than HTML does not appear to trigger HTML validation. Metaboxes will need to 100% rely on server side validation, which they should already, to be secure. If any iframe gurus know about form submission via iframe/JS, chime in with any ideas.

  • PHPCS gives warning about hooks not matching requirements. Well not sure what to do about that, as these are the hooks WordPress Core uses. Ignoring PHPCS is probably the best solution, unless someone has a better idea?

@codecov
Copy link

codecov bot commented Sep 3, 2017

Codecov Report

Merging #2583 into master will decrease coverage by 0.25%.
The diff coverage is 21.96%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2583      +/-   ##
==========================================
- Coverage   33.69%   33.43%   -0.26%     
==========================================
  Files         185      187       +2     
  Lines        5594     5724     +130     
  Branches      976      997      +21     
==========================================
+ Hits         1885     1914      +29     
- Misses       3141     3224      +83     
- Partials      568      586      +18
Impacted Files Coverage Δ
editor/metaboxes/index.js 0% <0%> (ø)
editor/index.js 0% <0%> (ø) ⬆️
editor/effects.js 38.96% <0%> (-1.04%) ⬇️
editor/metaboxes/iframe.js 0% <0%> (ø)
editor/sidebar/index.js 0% <0%> (ø) ⬆️
editor/layout/index.js 0% <0%> (ø) ⬆️
editor/actions.js 47.36% <100%> (+6.19%) ⬆️
editor/reducer.js 89.4% <100%> (+0.75%) ⬆️
editor/selectors.js 96.75% <100%> (+0.35%) ⬆️
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 26369c3...bc1046f. Read the comment docs.

@karmatosed karmatosed removed the Needs Design Feedback Needs general design feedback. label Sep 4, 2017
@BE-Webdesign
Copy link
Contributor Author

@youknowriad, @aduth, @matias: I think this is now at a pretty decent baseline of functionality. Would love feedback. The last piece before starting to put this in front of Metabox people, is getting Yoast to work.

@youknowriad
Copy link
Contributor

Hey @BE-Webdesign I wanted to try this, I'm thinking we should try to move it to a mergeable state but I had trouble making it work, the settings just didn't show up. what am i missing?

@BE-Webdesign
Copy link
Contributor Author

@youknowriad Should be fixed now, sorry about the confusion. Thank you for taking the time to help track down that bug.

@BE-Webdesign
Copy link
Contributor Author

Do not change the editor behavior if there are no metaboxes: no extra fetch/save request, no settings button.

Yup, should be reasonably doable.

I'm seeing custom taxonomies metaboxes showing up but we already have them baked in Gutenberg

This is partly tied into the above issue, but it should be relatively easy to fix.

I think the metaboxes using the content editor and the title input can be handled as a follow-up PR. We should try to iterate on this, we can't get it right for all metaboxes in the first iteration.

Yeah, that is also a possibility. I am pretty sure this covers the vast majority of metabox use cases. Iteration is totally fine by me.

Also the metabox blinking effect when updated is not a great experience but this also could be handled separately, we have solutions for this.

Yeah, personally I would like to put that in before merge, if possible, but am open to whatever. I think the blinking will really throw people off, and on what is already a very sensitive topic, we want to make sure that this is handled as seamlessly as possible.

What do you think?

I agree with all of your points. I think this works pretty well and with the addition of some of these minor changes, we can have something mergeable.

I think we want to also come up with a plan to deprecate these legacy metaboxes as well, this is some pretty hacktastic code, that should not live in Gutenberg forever. I think block templates will largely solve that problem, and hopefully with the superior user experience people will switch over, making an eventual deprecation smooth.

I will try and do these changes and see how that looks. If you can help with the blinking iframes that would be cool.

@BE-Webdesign
Copy link
Contributor Author

Going to patch this up now.

@BE-Webdesign
Copy link
Contributor Author

Detecting whether metaboxes are empty and instructing React/Redux is definitely more tricky than it ought to be. I have another hacky solution almost ready.

@BE-Webdesign
Copy link
Contributor Author

This is sadly a wormhole of a problem. Luckily the problem is related to how ACF registers metaboxes. I will try to hunt down what is going on exactly. Going to take a bit more time than expected.

@BE-Webdesign
Copy link
Contributor Author

how ACF registers metaboxes

Nevermind not as bad, was just hook timing.

@BE-Webdesign
Copy link
Contributor Author

Nevermind still terrible.

@karmatosed
Copy link
Member

karmatosed commented Sep 21, 2017

I am currently trying to give a design review for this and one thing strikes me on first loading, that's the double areas. For example, I was using ACF and see this:

2017-09-21 at 21 33

I think this is being mentioned and worked on and that the one without the field in it should just not show.

I wanted to add a visual though of the issue so those following along design wise can catch up. As we progress, if we are able to show screenshots, it really helps include everyone to get a review.

@BE-Webdesign
Copy link
Contributor Author

BE-Webdesign commented Sep 21, 2017

I think this is being mentioned and worked on and that the one without the field in it should just not show.

I wanted to add a visual though of the issue so those following along design wise can catch up. As we progress, if we are able to show screenshots, it really helps include everyone to get a review.

Sounds great! Thank you karmatosed. I am indeed working on hiding any empty metabox areas. It is pretty much done, and working locally. I just need to touch things up before I push it live.

Basic metabox support please see docs/metabox.md for details.
@BE-Webdesign
Copy link
Contributor Author

@youknowriad, @matias, @karmatosed and anyone else who is interested!:

Please see general overview for details on how this works.

Design review would be great! I tried to imitate what Joen had in the original #952. I still probably need to add the open close for the extended settings as a whole. Shouldn't be too hard to do that now. Solving the iframe flicker would also be nice. I can do that, but if y'all already have good solutions for that we can use those.

@youknowriad
Copy link
Contributor

@BE-Webdesign Awesome document, it really helps clarifying how it works.

Solving the iframe flicker would also be nice. I can do that, but if y'all already have good solutions for that we can use those.

I tied to play a bit with this, but my "hack" was not satisfying. I tried saving the iframe's HTML into a variable and set it into a second iframe while submitting the form, it worked but sometimes weird things happen :). I think I was not setting the temporary iframe's HTML properly for some unknown reason.

@BE-Webdesign
Copy link
Contributor Author

Awesome document, it really helps clarifying how it works.

There are definitely some details missing in it, but it will hopefully provide a good general overview.

On iframe flicker:

I have a solution, if you want me to try it. I am gonna clone the iframe when it goes to update, hide the iframe that is updating, and on reload delete the clone.

@youknowriad
Copy link
Contributor

I have a solution, if you want me to try it. I am gonna clone the iframe when it goes to update, hide the iframe that is updating, and on reload delete the clone.

yep, go for it, that's what I tried but miserably failed to achieve :)

@BE-Webdesign
Copy link
Contributor Author

yep, go for it, that's what I tried but miserably failed to achieve :)

I am sure you could solve it, I will try to solve it. Is there anything else I should try to update? I think after the flicker is fixed, this will be in a decent place, then tackling the Yoast stuff will be a next step?

@youknowriad
Copy link
Contributor

Yep, we should merge this, to gather some feedback and test it by plugin developers.

@WordPress WordPress deleted a comment from BE-Webdesign Sep 25, 2017
@BE-Webdesign
Copy link
Contributor Author

Okay sounds good. Some of the comments are possibly applicable lol.

@karmatosed
Copy link
Member

For a design review, I feel there are still 2 things I would love fixed, although I don't feel that is a merge breaker. I think it can be refined after merge.

2017-09-25 at 19 16

1: The fact that we have overly long input fields. I can see a need for strong stress testing of this area.
2. The empty area when another has it. I would suggest only one area is open by default.

I feel other things will come up as we get people to test with their plugins, so holding back for now. The principle is true to the initial concept.

@BE-Webdesign
Copy link
Contributor Author

The fact that we have overly long input fields. I can see a need for strong stress testing of this area.

I can address that, and have things be more in line with the original mockup.

  1. The empty area when another has it. I would suggest only one area is open by default.

I will also change this to be more inline with the original mockup.

@BE-Webdesign
Copy link
Contributor Author

BE-Webdesign commented Sep 26, 2017

@karmatosed, @joen.

Another idea for the design layout brought up by @aduth, is that maybe we could have the metabox area fixed at the bottom of the content area, which could then expand upwards to show metaboxes. In the current wp-admin experience, metaboxes must be scrolled to, past large swaths of content. It might create a better user experience being able to quickly open and collapse metaboxes. Using this UI approach, we could also reduce the complexity of this PR in two aspects:

Eliminate the need to have an iframe resizing hack, as the expanded metabox area will become a scrollable element.
Eliminate the need to remove iframe flicker when the metaboxes are saved (double buffering). We could instead collapse the metabox area with a nice animation of sorts on save.

This could have drawbacks as well to the user experience as the metabox area might become "cramped" being set in a set height scrollable area.

Word are probably not a good way to communicate these ideas, so what would be the proposed method of comparing, both solutions?

@karmatosed karmatosed removed the Needs Design Needs design efforts. label Sep 27, 2017
@BE-Webdesign
Copy link
Contributor Author

Closing in favor of #2804. A new branch was made so that returning to the non expandable version of metaboxes would be painless and easy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Status] In Progress Tracking issues with work in progress [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants