-
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
QuickEdit: Add slug field control #65196
Conversation
This is a tricky one, and technically an existing issue (see video below) so perhaps not one we have to fix here? slug.mp4Some validation might help; maybe the field should error when empty, and revert to the current value on blur? The Save button would be disabled when the field is empty. Some validation to avoid duplicate slugs might be handy as well. We also need to think about the conditions in which the Link field is shown in the quick-edit panel. In the vast majority of cases it's not possible to apply the same slug to multiple items, so maybe we just hide it for now? |
Yeah, this is something that I noticed too.
I'm fine following this approach. I'm going to try to implement it!
Yeah good point. I would see this kind of validation on the backend side when the user clicks save. For now, I would skip this point because it impacts some work not specifically related to the scope of this project.
True! Let's hide it! Thanks for your precious feedback, @jameskoster! 🙇 |
…into add/link-control
…into add/link-control
@@ -369,6 +370,13 @@ function usePostFields( viewType ) { | |||
return <time>{ getFormattedDate( item.date ) }</time>; | |||
}, | |||
}, | |||
{ |
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.
This works because our APIs are already extensible. However, there's an alternative that @joshuatf mentioned somewhere. Instead of doing:
{
id: 'slug',
Edit: /* custom slug Edit */,
render: /* custom slug render */,
isValid: /* custom slug isValid */,
// etc.
}
we can do something along these lines:
registerFieldType( 'core/slug', FieldSlug );
const fields = [
{
id: 'slug',
type: 'core/slug',
}
];
This has a few advantages:
-
It gets us a bit closer to making the
type
field required. We're not there there yet because there are a couple of missing types we need (image, for example), but we should aim to do it. -
We offer higher semantics and gets us a bit closer to having no-code JSON-oriented fields. This may sound a bit abstract, but imagine the following scenario: in the future, there's a mechanism for users to create screens based on declaring which fields they want from a dataset. All via UI. In that scenario, that UI needs to be no-code, and users shouldn't have to provide a "custom render", "custom edit", "custom validation", etc. if they just want a field to be a "slug". Instead, they should work with types: the basic ones provided by DataViews (string, integer, date, etc.) but also any other one that is domain-specific (slug, cart-status, etc.).
Another aspect of this PR is what should be the API offered by the wordpress/field
package?
This suggest it should export individual field properties (render, edit, isValid, etc.). There are a few. What if it exported the whole field instead? An advantage of exporting the whole Field is that the wordpress/field
package can implement new APIs as they come without having to modify the consumers:
// The consumer doesn't have to modify any code when
// a new Field property is introduced, renamed it, etc.
// It's the FieldSlug responsibility to implement it.
const fields = [
{
id: 'slug',
type: 'core/slug'
}
];
With dc2e1b8, the slug field is hidden in bulk edit mode. After a chat with @louwie17 and @joshuatf we are inclined to merge this PR without the validation (given that currently there isn't in the post editor). I'm going to mark this PR as ready to be reviewed!
Regarding the validation, we are planning to use this field as playground to think/implement how the validation should look. We are planning to create a dedicated PR (or multiples) for the validation!
Thanks for your comment! We are planning to work on this new API in the upcoming weeks! |
@@ -0,0 +1,18 @@ | |||
.fields-controls__slug { |
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.
Does it make sense this classname? Or should we think a better 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.
Perhaps I'd go with .field-slug
as a prefix.
packages/fields/package.json
Outdated
@@ -9,7 +9,6 @@ | |||
"gutenberg", | |||
"dataviews" | |||
], | |||
"private": true, |
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 presume this needs to be rebased from trunk
, correct? This package was made public already.
import SlugView from './slug-view'; | ||
|
||
const slugField: Field< BasePost > = { | ||
id: 'slug', |
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.
What type
would this field be? I feel we need to make progress on making type
obligatory and every new field we introduce should have a type.
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 would say slug
, what do you think? Mostly, because this field contains specific logic to preview the final link based on the slug setting:
gutenberg/packages/fields/src/fields/slug/slug-edit.tsx
Lines 38 to 46 in 4d1f022
const permalinkPrefix = prefix; | |
const permalinkSuffix = suffix; | |
const isEditable = PERMALINK_POSTNAME_REGEX.test( permalinkTemplate ); | |
const originalSlug = useRef( slug ); | |
const slugToDisplay = slug || originalSlug.current; | |
const permalink = isEditable | |
? `${ permalinkPrefix }${ slugToDisplay }${ permalinkSuffix }` | |
: safeDecodeURIComponent( data.link || '' ); | |
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.
After further consideration, the type should always represent a generic type, not strictly tied to WordPress. In this case, it should be link
. In the future, we might have:
- A generic field for the
link
type. - Other fields that work with the
link
type but have additional functionalities that depend on specific settings like this one.
Would it make sense for each field to have a 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.
Based on this discussion, I updated the type with 4efda74
@@ -369,6 +370,7 @@ function usePostFields( viewType ) { | |||
return <time>{ getFormattedDate( item.date ) }</time>; | |||
}, | |||
}, | |||
slugField, |
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.
It's ok for this PR going this way. I'd like to offer some thoughts about next steps.
Initially, the wordpress/fields
package exported every specific part of a field (edit, label, etc.) and we changed it to the whole field. Now that I see this, I think we have to offer an even higher-level API:
const postFields = usePostFields();
const pageFields = usePageFields();
// etc.
Essentially, the same we do for actions. In the future, we'll want 3rd parties to be able to register/unregister fields, so we can't use individual fields in every screen — otherwise, every screen will have to provide a filter/registry for that. Instead, we should offer an API that gives all the fields that are registered for a given post type.
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.
Initially, the wordpress/fields package exported every specific part of a field (edit, label, etc.) and we changed it to the whole field. Now that I see this, I think we have to offer an even higher-level API:
I see what you mean. I think that we will start to work on similar API when we will create a fields store in the @wordpress/fields
package.
In the future, we'll want 3rd parties to be able to register/unregister fields, so we can't use individual fields in every screen — otherwise, every screen will have to provide a filter/registry for that
On this, we are full aligned! We will plan to work on this API.
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've prepared a few small PRs to move the remaining field definition to @wordpress/fields
in preparation for moving usePostFields
as well:
- comment_status Post fields: move
comment_status
from edit-site to fields package #66934 - status Post fields: move
status
fromedit-site
tofields
#66937 - date Post fields: move
date
fields fromedit-site
tofields
package #66938 - author Post fields: move
author
fromedit-site
tofields
package #66939 - title Post fields: extract
title
fromedit-site
tofields
package #66940
@@ -66,6 +66,10 @@ Undocumented declaration. | |||
|
|||
Undocumented declaration. | |||
|
|||
### slugField |
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.
Can we start adding some JSDoc comments to the exported entities so this is filled up with actual info? It's enough to add a JSDoc to this statement.
It's ok to address this in a follow-up, but wanted to share some thoughts:
Thinking about how to scope next steps, this is what I think we should do:
Note that when we introduce "slug" field type, that should be automatically created for the field — but that requires other things we don't have yet (being able to register new fields types). |
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 think we can merge this one and continue iterating.
Nice catch! The design has been updated in the last weeks: https://github.com/WordPress/gutenberg/pull/63669/files. I updated the design! |
Co-authored-by: gigitux <[email protected]> Co-authored-by: oandregal <[email protected]> Co-authored-by: jameskoster <[email protected]>
What?
Part of #64519
Screen.Capture.on.2024-09-10.at.12-42-17.mp4
This PR adds the
slug
field control to the Page view. Most of the logic is copied from:getPermalinkParts
: https://github.com/WordPress/gutenberg/blob/5682b928356f624f6ed820d066689423d08d5d88/packages/editor/src/store/selectors.js/#L994-L1016isPermalinkEditable
: https://github.com/WordPress/gutenberg/blob/5682b928356f624f6ed820d066689423d08d5d88/packages/editor/src/store/selectors.js/#L937-L944Currently, these two functions are public selectors and rely on the editor state, so we can't refactor those. I think that for now, we can keep this duplicate code and when the post editor sidebar will be powered by the dataview, we can think to refactor those, but I'm open to feedback on this.
Similar to #64496, this code could be moved to the
@wordpress/core-fields-control
package if we agree to create it.Validation
There is an edge-case that I think that we should take care, but I will wait for your feedback before to proceed. When the input is empty, the save button is clickable:
This isn’t ideal because a page/post should always have a slug set. Currently, if the input is empty, the original slug is restored on the
onBlur
event, which is not the best UX.How?
Testing Instructions
Ensure that
Quick Edit in DataViews
andQuick Edit in DataViews
are enabled./wp-admin/options-permalink.php
.plain
setting.