Sidebar Field Extension

Describe the issue:

  • I’m trying to create a field extension where when we reference an object in Hubspot by the object id, we have a sidebar panel added that displays data bout the hubspot record
    • ideally, only if that field has an object id would we render the sidebar panel
  • The idea being that we could have multiple models that each might have a different purpose in referencing an object in hubspot, and each might want to display different fields from the hubspot object
  • A field extension would work great since this allows us to customize the application of the referenced hubspot object to the record type through the field extension configuration options

Issue

  • The concept of this plugin was driven from the existence of the Sidebar Notes plugin, which leverages a non-documented feature of specifying a field extension as asSidebarPanel: true, returned from the manualFieldExtensions hook.
  • However, it appears that this method of rendering in the sidebar, doesn’t allow you to control where in the sidebar the field is rendered (rank, placement)

Questions

  • What is the expected way of implementing a plugin like this?
  • If using the primary way of configuring a sidebar plugin, if i’m in the itemFormSidebarPanels hook, I don’t see how to
    1. easily determine if the sidebar panel should be rendered for a given item type
    2. provide configuration for this particular sidebar panel implementation
    3. dynamically fetch information about the given itemType to determine if it contains a field with a specific name or that might have specific configuration options
  • Would the only method be to configure which model, field, and configuration options to leverage within the plugin configuration screen?

Additional Documentation Issue

  • See the documented ctx methods available to the itemFormSidebarPanels hook. The type I see for ctx in the context of this hook is IntentCtx, which doesn’t include the majority of what is referenced in the documentation here. There are async methods referenced, that IIRC cannot be used because you cannot return a promise from the hook.

Hey @nroth,

First off, the Sidebar Notes plugin is using a very old version of the plugins-sdk, and what looks like deprecated methods/properties. Let’s ignore that for now.

The current, supported method of adding sidebars is, as you say, using the itemFormSidebarPanels hook: Sidebars and sidebar panel | Documentation — DatoCMS. Please make sure you’re using most recent version of the plugins SDK (^2.x.x).

You should be able to:

  • Render an individual panel within the sidebar with itemFormSidebarPanels()
    • You can control placement & rank using the placement & rank parameters — sorry that isn’t clear in the docs, but you can see it in the TypeScript of that hook’s return type.
  • OR render an entire sidebar (take over the entire side, not just a panel) with itemFormSidebars()
  • (You might also consider using a record Outlet instead, which renders at the top of a record instead on the side)

But with any of these, you’re right, the plugin SDK doesn’t allow much in the way of dynamically showing or hiding things. You are limited to using the provided itemType and ctx (which should be of type ItemFormSidebarsCtx or ItemFormSidebarPanelsCtx, not IntentCtx; the normal methods/props should be available there?)

Example:

As for using dynamic data fetched async from the outside, unfortunately you can’t really do that inside the connect() function in main.tsx right now (I wish you could too, and am asking for it internally). But for now, you have to move that part of the logic inside the actual rendered component (which is just standard React or JS).

e.g. the flow would go something like this:

  • Define a sidebar/panel/outlet that gets rendered conditionally, depending on itemType/ID/anything available in the ctx
  • Inside that component, do an async fetch and either display the product data directly, or display one of several possible sub-components to show depending on the conditions met.
  • If there is nothing relevant to show, just show a “No product info for this product/model” message.

It’s not as clean as being able to dynamically show/hide the thing altogether, I know. Sorry about that!

Sorry, quick note: Seems like rank must be >= 1 to work correctly. Lower values will be higher visually.

A rank of 0 seems bugged right now.

But this would work:

[
	{
		id: 'firstPanel',
		label: 'First panel',
		startOpen: true,
		placement: ['before', 'info'], // Where to place it relative to our default panels
		rank: 1 // Tiebreaker if two panels have the same `placement` value. Must be >= 1. Lower values are visually higher up.
	},
	{
		id: 'secondPanel',
		label: 'Second Panel',
		startOpen: true,
		placement: ['before', 'info'],
		rank: 2
	},
];

I updated the docs to be more explicit about positioning: Sidebars and sidebar panel | Documentation — DatoCMS