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

feat(structure): add ability to override the tool's canHandleIntent logic #7611

Open
wants to merge 1 commit into
base: next
Choose a base branch
from

Conversation

marcusforsberg
Copy link

Description

What issue(s) does this solve?

For Studios with multiple Structure Tools, there's currently no convenient way to decide what "instance" of the Structure Tool should or should not handle a given intent.

In our projects we generally have one Structure tool called "Content" which is used to edit document types such as pages, posts, authors, and another Structure tool called "Settings" which contains things like global config, navigation menus and redirect rules.

As of now, if the user is currently working on a document in the "Settings" tool and uses the Create button or the global search to create or edit a document type that is not even available in that tool, it will still react to the intent, leaving the user in a confusing state where they're editing a document which isn't "available" in that tool (i.e not visible in the navigation pane):

Screenshot 2024-10-11 at 12 38 49

In this screenshot, I'm on the Settings tool and used CMD + K to select a "page" document. Pages aren't available under Settings, since they're edited under Content. Ideally, I should have been redirected to the "Content" tool which can correctly handle this edit intent.

What changes are introduced?
This adds a new config option to the Structure Tool, canHandleIntent, which allows users to override the intent handling logic on a per-instance basis. The default callback for canHandleIntent is also exported, so that it can be used as a fallback within custom handlers.

Here's how it can be used:

// This Structure Tool only wants to handle intents for "author" documents
structureTool({
  title: 'Authors',
  name: 'authors',
  canHandleIntent: (intent, params) => {
    if (params.type !== 'author') return false

    // Imported from `sanity/structure`, allowing me to re-use the default logic as fallback
    return canHandleIntent(intent, params)
  },
}),

What to review

This is my first PR to Sanity core, so I'm not even sure if this is the best option here or if it's even something you wish to add support for. It's a small enough change that it shouldn't affect anything negatively, but I'm open to feedback on better ways to achieve the same end goal of having multiple Structure tools handle different intents.

Technically this is already possible to pull off by doing something like this in the project config:

tools: (prev) => {
  return prev.map((tool) => ({
    ...tool,
    canHandleIntent: (intent, params, payload) => {
      if (tool.name === 'authors' && params.type !== 'author') return false

      return tool.canHandleIntent ? tool.canHandleIntent(intent, params, payload) : false
    },
  }))
},

For all I know, this is the way it's designed, in which case this PR can be disgarded. 😊
Personally, I feel like being able to do this logic when actually defining each individual tool is in some ways easier to read. On the other hand, overriding it "globally" like this allows for more complex logic if you have many different Structure tools.

So all in all: this PR is a suggestion and if nothing else I'm hoping it can lead to some official recommendation on what is the best practice. 😊

Testing

I tested this manually in the Test Studio by adding a second Structure tool that only reacts to create and edit intents for the author type.

@marcusforsberg marcusforsberg requested review from a team as code owners October 11, 2024 10:53
@marcusforsberg marcusforsberg requested review from ryanbonial and removed request for a team October 11, 2024 10:53
Copy link

vercel bot commented Oct 11, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
page-building-studio ❌ Failed (Inspect) Dec 9, 2024 9:59am
performance-studio ❌ Failed (Inspect) Dec 9, 2024 9:59am
test-next-studio ❌ Failed (Inspect) Dec 9, 2024 9:59am
test-studio ❌ Failed (Inspect) Dec 9, 2024 9:59am
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
studio-workshop ⬜️ Ignored (Inspect) Visit Preview Dec 9, 2024 9:59am

Copy link

vercel bot commented Oct 11, 2024

@marcusforsberg is attempting to deploy a commit to the Sanity Sandbox Team on Vercel.

A member of the Team first needs to authorize it.

@bjoerge
Copy link
Member

bjoerge commented Dec 9, 2024

Hi @marcusforsberg, thank you for taking the time and effort to suggest this improvement (and my apologies for the delay in getting around to reviewing it).

Wondering if instead of having to import the default (static) canHandleIntent from desk-tool, it would be better (and also more idiomatic compared with our renderDefault pattern elsewhere) if the default canHandleIntent was passed to the caller, e.g.:

canHandleIntent: (intent, params, defaultCanHandleIntent) => {
  if (params.type !== 'author') return false
  return defaultCanHandleIntent(intent, params)
}

I believe this would have a few advantages, from the top of my head:

  • saves us from having to add a new package export from sanity/structure and saves developers from having to add another import
  • improves discovery and almost self-documenting (exposed on the function signature/type hints)
  • enables stateful/contextual default intent logic if we would need it in the future

Disclaimer: I have not done a thorough check to verify whether it's actually feasible to make such a change, but I'd be more than happy to review a proposal about what the implementation could look like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants