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

[Navigation] Makes URL dynamic for pages and posts #21050

Closed
wants to merge 23 commits into from

Conversation

draganescu
Copy link
Contributor

Description

Closes #18345

How has this been tested?

Tested locally by:

  1. Make sure you have some posts and pages
  2. Add a new page
  3. Add a Navigation block
  4. Create empty
  5. Add a link to a page, a link to a post and an external link
  6. Save and view post
  7. Links should be working

Types of changes

Small change to NavigationLinkEdit to also save the type which LinkControl offers to the onChange handler.

Then on the render function (PHP) added a call to get_permalink for anything which is not an external URL.

@draganescu draganescu added [Type] Enhancement A suggestion for improvement. [Block] Navigation Affects the Navigation Block labels Mar 20, 2020
@github-actions
Copy link

github-actions bot commented Mar 20, 2020

Size Change: +458 B (0%)

Total Size: 1.14 MB

Filename Size Change
build/api-fetch/index.js 3.39 kB +1 B
build/block-editor/index.js 115 kB +11 B (0%)
build/block-editor/style-rtl.css 10.8 kB +7 B (0%)
build/block-editor/style.css 10.8 kB +4 B (0%)
build/block-library/index.js 132 kB +28 B (0%)
build/blocks/index.js 48.2 kB +18 B (0%)
build/components/index.js 199 kB -25 B (0%)
build/compose/index.js 9.67 kB +1 B
build/core-data/index.js 11.5 kB +12 B (0%)
build/edit-navigation/index.js 10.8 kB +15 B (0%)
build/edit-post/index.js 304 kB +163 B (0%)
build/edit-post/style-rtl.css 5.6 kB +13 B (0%)
build/edit-post/style.css 5.6 kB +13 B (0%)
build/edit-site/index.js 16.8 kB +173 B (1%)
build/edit-site/style-rtl.css 3.04 kB +11 B (0%)
build/edit-site/style.css 3.04 kB +12 B (0%)
build/edit-widgets/index.js 9.35 kB -4 B (0%)
build/editor/index.js 45.1 kB +2 B (0%)
build/format-library/index.js 7.72 kB +3 B (0%)
build/keyboard-shortcuts/index.js 2.51 kB +1 B
build/list-reusable-blocks/index.js 3.12 kB +1 B
build/media-utils/index.js 5.32 kB +1 B
build/rich-text/index.js 13.9 kB -1 B
build/token-list/index.js 1.27 kB -2 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/annotations/index.js 3.67 kB 0 B
build/autop/index.js 2.82 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/index.js 7.67 kB 0 B
build/block-directory/style-rtl.css 944 B 0 B
build/block-directory/style.css 945 B 0 B
build/block-library/editor-rtl.css 7.6 kB 0 B
build/block-library/editor.css 7.59 kB 0 B
build/block-library/style-rtl.css 7.77 kB 0 B
build/block-library/style.css 7.77 kB 0 B
build/block-library/theme-rtl.css 728 B 0 B
build/block-library/theme.css 729 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/components/style-rtl.css 15.9 kB 0 B
build/components/style.css 15.8 kB 0 B
build/data-controls/index.js 1.29 kB 0 B
build/data/index.js 8.46 kB 0 B
build/date/index.js 5.38 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 569 B 0 B
build/dom/index.js 3.23 kB 0 B
build/edit-navigation/style-rtl.css 1.08 kB 0 B
build/edit-navigation/style.css 1.08 kB 0 B
build/edit-widgets/style-rtl.css 2.45 kB 0 B
build/edit-widgets/style.css 2.45 kB 0 B
build/editor/editor-styles-rtl.css 537 B 0 B
build/editor/editor-styles.css 539 B 0 B
build/editor/style-rtl.css 3.78 kB 0 B
build/editor/style.css 3.78 kB 0 B
build/element/index.js 4.65 kB 0 B
build/escape-html/index.js 733 B 0 B
build/format-library/style-rtl.css 547 B 0 B
build/format-library/style.css 548 B 0 B
build/hooks/index.js 2.13 kB 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.56 kB 0 B
build/is-shallow-equal/index.js 709 B 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/style-rtl.css 476 B 0 B
build/list-reusable-blocks/style.css 476 B 0 B
build/notices/index.js 1.79 kB 0 B
build/nux/index.js 3.4 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/plugins/index.js 2.56 kB 0 B
build/primitives/index.js 1.4 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/server-side-render/index.js 2.71 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/url/index.js 4.06 kB 0 B
build/viewport/index.js 1.85 kB 0 B
build/warning/index.js 1.13 kB 0 B
build/wordcount/index.js 1.17 kB 0 B

compressed-size-action

@draganescu
Copy link
Contributor Author

This makes the URL dynamic for pages and posts on rendering the block but does not handle the URL stored as an attribute for pages and posts.

I wonder how this can be solved though?

  1. Make an API call for each menu item to get the latest URL? Seems overkill.
  2. Make LinkControl get latest URL on edit for type page or post? Could make editing clunky.
  3. Add a sort of get_permalink clientside? Without calling the API it's a duplicated func. to maintain. With calling the api is similar to 1 or 2.

Just to be clear, the problem is when we have a menu saved and settings change (say permalink structure) and someone edits a menu item, they should see the updated link.

cc @mtias

@draganescu
Copy link
Contributor Author

This PR also adds to the Navigation block the small feat of rendering a div if the item is only a label and contains neither an ID or an URL.

@draganescu
Copy link
Contributor Author

@talldan I added back the link to the navigation item. Once the snapshots work I would suggest we address this stale url stored as attribute in a separate PR. For now the LinkContol component is not ready to manage links without URLs and also the NavigationLinkEdit component expects the items to have URLs for proper styling.

I am afraid that updating LinkControl for this case would make things complex in this context. What do you think?

@draganescu draganescu force-pushed the add/dynamic-links-navigation branch from 6338640 to b4dd7ee Compare May 11, 2020 12:33
@talldan
Copy link
Contributor

talldan commented May 12, 2020

So just to be clear, as I don't think it's all that clear for those outside this conversation—the bug this introduces is as follows:

  1. Create a navigation block with a navigation link pointing to a post and save
  2. Change the permalink structure for posts
  3. Check the URL on the front-end, observe that the URL for the post in the front-end matches the new permalink structure.
  4. Check the URL in the editor, observe that the URL for the post in the editor is outdated and matches the old permalink structure.

The current behavior in master is that both 3 & 4 are broken. So while this technically makes things less broken, it does introduce an inconsistency for the block that wasn't there before.

@draganescu
Copy link
Contributor Author

Looking at the LinkControl component it seems possible to update it to work with Id instead of URL. However, in order to have the blocks update their own stored Urls to use the rendered version (that is to take into account permalink structure and config changes) is a serious task.

As far as the LinkControl goes,

  • when the init value is not an Url, and we determine it is some Id, then we fetch the Url from the API and show that. This way, we could show for pages and posts the titles instead of links.

  • when the init value is empty or we edit, then LinkControl will simply don't pass Url to the onChange callback in the various contexts it is used (e.g. click on suggestion)

The problem here is that all the parent components implementing LinkControl will need their own front end rendering system.

Even if LinkControl autoupdates the Url on edit, the moment it is passed to a component who has no clue how Urls work, it will be optionally stale.

Assuming we only update the navigation items to not store any URL since the front will potentially render another one, we run into displaying links with no link, or invalid anchors styled to look like links.

Even if we solve it for one block, say we customize only the NavigationItem - LinkControl relationship at least the formatted links in RichText will still be in danger of being outdated.

cc @mtias what do you think of this?

@earnjam
Copy link
Contributor

earnjam commented May 15, 2020

So many of these types of issues are related to this insistence on storing nav menus as serialized block data. We have an existing menu data storage method in WordPress that already has problems like these solved. I still don't really understand the reasoning for abandoning it.

@draganescu
Copy link
Contributor Author

@mtias is #21932 related to this as well?

@draganescu draganescu force-pushed the add/dynamic-links-navigation branch from b4dd7ee to 1973247 Compare June 2, 2020 16:39
@mtias
Copy link
Member

mtias commented Jun 15, 2020

The problem here is that all the parent components implementing LinkControl will need their own front end rendering system.

I don't think LinkControl should be updated for all cases it's used. When adding an inline link, we are still bound to rendering the link as entered by the user and there's currently no expectations of such links, even if internal, being updated on permalink changes. We also don't handle server rendering inline links.

We should only handle the Link block as used in Navigation for now. I'd imagine LinkControl could have a property to make it dynamic or to prioritize IDs.

So many of these types of issues are related to this insistence on storing nav menus as serialized block data. We have an existing menu data storage method in WordPress that already has problems like these solved. I still don't really understand the reasoning for abandoning it.

@earnjam I think the issue is that the current setup addresses some issues but leaves quite a few others open. Once we start allowing more blocks to be inserted in menus — search, social icons, headings, images, text — the storage breaks down a bit as it needs to handle many other representations, some dynamic and some static. Depending on how the design evolves, we might need to have specialized blocks for any set of links (like sub-pages) so that they can be better intermixed with other blocks.

In any case, the navigation block currently works with both data structures depending on where it's used (site editing or nav-menus.php screen) so we can see where the different issues arise.

Also worth emphasizing for this particular thread that the Link block is not necessarily attached to navigation, it could become a standalone block for various other uses, so it still needs to model the attributes properly.

@draganescu draganescu force-pushed the add/dynamic-links-navigation branch from d9b4caf to 6207832 Compare July 9, 2020 17:12
@draganescu
Copy link
Contributor Author

@talldan can you check this again, I added your suggestion to pass the id as part of value, good idea! Thank you!

@adamziel
Copy link
Contributor

adamziel commented Jul 14, 2020

Here's what I see in the post editor after applying this PR:

Zrzut ekranu 2020-07-14 o 16 14 04

Interestingly, the block is rendered on the frontend without any issues. I wonder if there's something wrong with my working copy? Hopefully an error like that would trigger some test failures but they seem to be in tact.

@adamziel
Copy link
Contributor

And it fixed itself, super interesting!

Co-authored-by: Adam Zielinski <adam@adamziel.com>
@adamziel
Copy link
Contributor

Before:
Zrzut ekranu 2020-07-14 o 16 35 33
Zrzut ekranu 2020-07-14 o 17 26 57

After (with permalinks enabled):
Zrzut ekranu 2020-07-14 o 16 18 42
Zrzut ekranu 2020-07-14 o 17 38 12

Two problems here - I don't know what the link is anymore, and after clicking edit the input is empty.

@adamziel
Copy link
Contributor

adamziel commented Jul 14, 2020

It's fine to update the data model so that it tracks the ID instead of the URL, but the editor experience should remain the same. I don't like how I'm not able to preview (or edit) the URL anymore. Maybe we should fetch all the relevant page URLs once the editor is loaded?

@draganescu
Copy link
Contributor Author

To enable that kind of editing we should fetch from the API details about the linked page. We don't know ahead of time which are the "relevant" pages so we'll end up with a spinner in that popover, so we can know the URL for the id. So it's still a downside. Also, when you edit the link, the link control will have to revert to "manual link" loosing the connection to the id.

Comment on lines +610 to +618
{ typeof value.id !== 'undefined' && (
<span className="block-editor-link-control__search-item-header">
{ value && value.title && (
<span className="block-editor-link-control__search-item-info">
{ value.title }
</span>
) }
</span>
) }
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this part probably needs some design influence, would be good to address as a follow-up.
Screenshot 2020-07-15 at 6 01 04 pm

} elseif ( isset( $attrs['url'] ) ) {
return esc_url( $attrs['url'] );
}
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

false isn't a valid URL. Maybe just omit this?

Suggested change
return false;

opensInNewTab,
title: label,
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, these two aren't really the same thing. If I edit the label it doesn't mean that my page title is changed.

Not sure what the alternative is, since we don't actually know the page title.

// End anchor tag content.

if ( $block->context['showSubmenuIcon'] && $has_submenu ) {
if ( isset( $block->context['showSubmenuIcon'] ) && $block->context['showSubmenuIcon'] && $has_submenu ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This change seems unrelated. Is it needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was a suggestion from @adamziel to make sure we don't get PHP Notices sometimes.

@talldan
Copy link
Contributor

talldan commented Jul 15, 2020

To enable that kind of editing we should fetch from the API details about the linked page. We don't know ahead of time which are the "relevant" pages so we'll end up with a spinner in that popover, so we can know the URL for the id. So it's still a downside. Also, when you edit the link, the link control will have to revert to "manual link" loosing the connection to the id.

I think when you edit, the page title should be the value in the input box. Maybe.

This is a tricky thing to get right.

@adamziel
Copy link
Contributor

adamziel commented Jul 15, 2020

To enable that kind of editing we should fetch from the API details about the linked page. We don't know ahead of time which are the "relevant" pages so we'll end up with a spinner in that popover, so we can know the URL for the id.

How I imagine it is this:

  • When the NavigationLink is first mounted, it requests it's related page from the API. A more sophisticated approach could batch these requests too.
  • When a page is selected from the suggestion box, the URL is retained in state.

So it's still a downside. Also, when you edit the link, the link control will have to revert to "manual link" loosing the connection to the id.

That's one way to approach it - it sounds fine to me, but maybe we could figure out even better UI here, for example disallow editing the page URL while still making it possible to edit the link URL:

Zrzut ekranu 2020-07-15 o 12 37 12

^ This isn't the right solution, but my thinking goes in that direction. Also CC @shaunandrews since it's super relevant for in-toolbar editing.

@draganescu
Copy link
Contributor Author

@adamziel do you think #24099 kinda blocks this? I do!

@adamziel
Copy link
Contributor

@draganescu no, but #23375 may. CC @shaunandrews

@noisysocks
Copy link
Member

Closing this as it's gotten stale. I'll try to address #18345 in a separate PR. It's closely related to what I've been working on in #24670.

@noisysocks noisysocks closed this Aug 26, 2020
@noisysocks noisysocks deleted the add/dynamic-links-navigation branch August 26, 2020 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Navigation Affects the Navigation Block [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NavigationLink: make the URL dynamic for links to Posts
7 participants