Skip to content

Add Command Palette support #121

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

Open
wants to merge 33 commits into
base: trunk
Choose a base branch
from
Open

Conversation

priethor
Copy link
Contributor

@priethor priethor commented Apr 25, 2025

What

This PR adds support for WordPress Command Palette/Core Commands (Cmd+K / Ctrl+K interface) by registering:

  • Core commands to navigate to SCF admin pages
  • "View All" commands for each Custom Post Type registered with SCF
  • "Add new" for each Custom Post Type registered with SCF

Implementation details

The commands are divided into admin and CPT command files.

  • Core commands are only registered when the current user has admin permissions
  • CPT commands are registered only when these conditions are met:
    • The current user has enough capabilities to edit the CPT
    • The CPT has enabled the show_ui setting

To prevent errors and optimize performance, JavaScript files for core and/or CPT commands will only be enqueued when needed.

Testing Instructions

  1. Ensure you're using WordPress 6.3+ (Commands API was introduced in 6.3)
  2. Ensure you have registered at least one CPT (e.g., "Books")
  3. Press Cmd+K (Mac) or Ctrl+K (Windows) in the Block Editor
  4. Type "SCF" or "Taxonomies" to see SCF-related admin commands
  5. Type your CPT name ("Books") to see its related commands ("View books", "Add book")
  6. Verify that commands correctly navigate to their respective pages
  7. As an administrator, verify you can see both admin commands and CPT ones
  8. As a user with limited permissions, verify that you only see commands you have access to. For example, an editor should only see CPT commands
  9. Test with a WordPress version earlier than 6.3 to confirm that no errors occur

Recording

Grabacion.de.pantalla.2025-04-25.a.las.13.55.21.mov

Followups

  • Consider registering commands with useCommandLoader instead, which was introduced in WP 6.4.
  • Add tests
  • Implement a new REST endpoint for CPTs to avoid using acf_localize_data
  • Migrate to TypeScript

@priethor priethor added the [Type] Enhancement New feature or request label Apr 25, 2025
@priethor priethor self-assigned this Apr 25, 2025
@priethor priethor changed the title First attempt at adding command palette support Add Command Palette support Apr 25, 2025
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 left some initial general feedback before trying to better understand how it exactly works. I will try to test it next.

Comment on lines 16 to 19
const { __ } = wp.i18n;
const { createElement } = wp.element;
const { Icon } = wp.components;
const commandStore = wp.data.dispatch( 'core/commands' );
Copy link
Member

Choose a reason for hiding this comment

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

It is possible to use import statements to let the build tackle detecting all dependencies. @cbravobernal added all necessary code to automate it. See:

description: command.description,
keywords: command.keywords,
callback: ( { close } ) => {
document.location = command.url;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: the following could help remove some duplication from the command config a bit:

Suggested change
document.location = command.url;
document.location = adminUrl + command.url;

@gziolo
Copy link
Member

gziolo commented Apr 25, 2025

You can also divide the work into two PRs since it’s fully functional and tests well. Command Palette support doesn’t have to be a Beta Feature because it’s a straightforward enhancement that anyone familiar with the concept should appreciate.

Follow-up work could include:

  • Refactoring JS files to TS.
  • Enhancing asset management to automatically detect dependencies in the build step.

However, we need to take a closer look at the functionality, particularly the strategy for when these commands become available, depending on the WP version, the presence of custom post types, and user permissions.

priethor and others added 8 commits April 25, 2025 17:16
Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl>
- Defer the script loading (defer was introduced in WP 6.3)
- Defer script execution by using the priority queue (introduced in WP 5.0)

Since the scripts will only be registered in versions with Command API support, which is 6.3+, we can use both
@priethor priethor force-pushed the add-command-palette-support branch from 764103d to 1df01fe Compare April 25, 2025 17:19
/**
* Register admin commands for SCF
*/
queue.add( context, () => {

Choose a reason for hiding this comment

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

It's not really clear to me why you're using "priority-queue" here? Did you actually notice performance issues or something. Also potentially you can just use requestIdleCallback directly instead of using a queue with a single callback.

Copy link
Contributor Author

@priethor priethor Apr 28, 2025

Choose a reason for hiding this comment

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

I did not notice any performance difference; I implemented the priority queue in parallel to defer the loading here.

Choose a reason for hiding this comment

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

Let's just get rid of it. I think defer is enough.

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 simplified to a requestIdleCallback here before reading your answer. Should I get rid of that, too? It still seems overkill.

}

if ( ! empty( $custom_post_types ) ) {
acf_localize_data(

Choose a reason for hiding this comment

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

Personally, I'd argue that we should move away from localized variables like that as much as possible and instead use REST API endpoints. Do SCF has endpoints to retrieve these things, can't we just rely on Core endpoints for post types...?

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 the only endpoints registered are the ones that fetch custom post types and post fields, in every field you can chose to include it or not in the WP default API endpoints for posts fetching, but there are no internal endpoints to retrieve all post types or all post fields created with the plugin.

They are instead localizing the data:

acf_localize_data( $data_to_localize );

Moving everything to a REST API could be done, but this needs to define a new API structure, with its own documentation and decide the approach for the store handling ( using Redux based like wp-data, or move to React Query or something similar )

What's your opinion on that @youknowriad ?

Copy link
Contributor Author

@priethor priethor Apr 28, 2025

Choose a reason for hiding this comment

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

There are two issues why using the Rest API would require some extra work and I didn't consider for this:

  • While it does a PHP function to retrieve SCF Post types (acf_get_acf_post_types), it doesn't have a custom enpoint to do so, just WordPress` built in endpoints.
  • More importantly, in order to show CPTs in the REST API, each CPT needs to enable the Show in REST API setting.

Therefore, my guess is we will need custom SCF endpoints for the admin that show all, as we will encounter a similar issue when implementing DataViews. What do you think about this approach, Riad?

Choose a reason for hiding this comment

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

We're on WordPress, so for me, we should be use the entities and core-data here. no need to duplicate things that exist.

More importantly, in order to show CPTs in the REST API, each CPT needs to enable the Show in REST API setting.

For me this is something that we should try to get rid of. Every CPT should be visible in the endpoints, I think this is a setting of another age.

That said, for now, a custom endpoint/entity could work if we're not ready to make all CPTs created by SCF show_in_rest true. Are there any valid reasons for not doing it?

Copy link
Contributor Author

@priethor priethor Apr 28, 2025

Choose a reason for hiding this comment

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

Are there any valid reasons for not doing it?

If by this you mean a custom endpoint, the only reason not to do it right now is the extra complexity it adds to this PR, we should probably tackle that separately.

As per the existing setting, I wouldn't change an existing setting as we don't know all the cases or real users (e.g., having CPTs only for the admin to manage private data), though.

Choose a reason for hiding this comment

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

As per the existing setting, I wouldn't change an existing setting as we don't know all the cases or real users (e.g., having CPTs only for the admin to manage private data), though.

This is different than show_in_rest, this should be mostly handled by the public boolean.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thinking a bit more about this:

  • Right now, we would need to use the types endpoint.
  • show_in_rest determines whether a custom post type gets its own endpoint, but also hides the CPT definition from the types endpoint.
  • In any case, the types endpoint doesn't return any information to know whether a type is a CPT and/or created by SCF (e.g., no post-type field)

Therefore, my inclination is to create a new endpoint for custom post types that ignores the show_in_rest. This will be needed, too, when migrating the Post Types screen to DataViews.

Copy link

@youknowriad youknowriad Apr 28, 2025

Choose a reason for hiding this comment

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

The ideal scenario is to actually use the types endpoint and add "metadata" to the post type. That said, I think it's a good interim solution to have a custom endpoint.

Copy link

@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.

In parallel to this PR, I wonder if we should implement this PR within SCF (before it gets into Core) to enable the command palette everywhere.

@youknowriad
Copy link

So for me, the PR is fine. But I think we should ask ourselves what we want to do with these post types and any SCF UI going forward. Do we want to decouple the server and client and have a consistent data layer to communicate between both (ideally on top of core-data) or do we want to continue with these localized scripts which for me feels like hacks.

An investment in the core-data layer will help this PR but also any future PR that would like to rely on SCF entities in its client UI.

@priethor
Copy link
Contributor Author

Do we want to decouple the server and client and have a consistent data layer to communicate between both (ideally on top of core-data) or do we want to continue with these localized scripts which for me feels like hacks.

I don't know if a hack, but it did feel like a dated approach that doesn't align with the current direction of core and modern architecture. I do agree with investing in decoupling server and client; the amount of data required in this PR is minimal, but as we move forward with new functionalities, it will pay off or even become necessary.

How do you all feel about this PR with the current approach, and then follow up with the new endpoint implementation?

@youknowriad
Copy link

How do you all feel about this PR with the current approach, and then follow up with the new endpoint implementation?

I'm ok with this personally, but I would try to avoid the acf script dependency, it seems this is not needed at all and we can just use any random global variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants