Creating custom Action Menu Items

API developers can customize context menu items on a per-entity basis. For example, from a Versions page, you could select multiple versions, right-click, then.... Build a PDF Report (for example). We call these ActionMenuItems (AMI's).

Action Menu Items

 

Action Menu Item Fields:

  • Title (title): The display name of the menu item.
  • URL (url): The URL of our script that will create the PDF report.
  • Order (list_order): The ordinal position of the menu item (relative to other custom menu items).
  • Entity Type (entity_type): We've set this to 'Version', which specifically restricts the menu item to only appear on Version pages. Omitting this key (a nil value) has the effect of allowing the menu item on ALL enabled entities.
  • Selection Required (selection_required): Determines whether the menu item will be active if there are no rows currently selected.
  • Folder (folder): Allows you to organize AMI's into folders within the context menu (currently only a single level of folders is supported).
  • Restrict to Permission Groups (permissions_groups): Allows you to restrict access for the AMI to only specified permission groups. If left empty, AMI will be available for all users.
  • Restrict to Projects (projects): Will make it so the AMI only shows up in specified Projects. If left empty, AMI will be available in all Projects.
  • Poll for Data Updates (poll_for_data_updates): Starts a polling loop to query for event log entries. This is for cases where the code on the other end of the ActionMenuItem makes changes back to Shotgun via the API on entities that are visible on the page that triggered the ActionMenuItem.

 

Action Menu Folders

Example of the "Folder" field in action.

 

Types of Action Menu Items

There are 2 types of menu items you can create:

Custom HTTP URL example

We're going to create a custom menu item called 'Build PDF Report'. When we're done, people will be able to go to any Versions page on our Shotgun server, select 1 or more Versions, right-click, then click 'Build PDF Report' from the Shotgun menu. Doing this will launch a script you've supposedly created, to get a nicely formatted report sent back to their browser. Here's how it works:

Option 1: Create the menu item via the UI

Action Menu Admin Page

From the User Settings menu, choose Action Menu Items to open the AMI admin page. To create a new AMI, click on Add Action Menu Item. Fill out the Title and any other required fields, and click Create Action Menu Item.

Option 2: Create the menu item via the API

from shotgun_api3 import Shotgun
from pprint import pprint

SERVER_PATH = '*****' #your server path here
SCRIPT_USER = '*****' #your script name
SCRIPT_KEY =  '*****' #your key here

sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

data = {

  "title":"Build PDF Report",

  "url": "http://some_url",

  "list_order": 1,

  "entity_type": "Version",

  "selection_required": False

}

#Create the menu item
menu_item = sg.create("ActionMenuItem", data)

 

What happens when a user clicks on the Action Menu Item?

Shotgun dispatches a POST request in a new window, and sends along data from the current page (as part of the POST request) to the receiving url. Here's an example of the workflow.

  • User navigates to a Versions page
  • User selects 1 or more Versions
  • User brings up the context menu (by right-clicking or clicking on the gear menu in the toolbar)
  • User clicks 'Build PDF Report' (for example)
  • Shotgun dispatches a POST request to the ActionMenuItem's url in a new window (If your Shotgun server is served over https, and your url is served over http, expect to see a browser warning)
  • Your script - located at the url specified - processes the POST data, and generates a pdf document
  • A nicely formatted pdf report is sent back to the user for viewing or download (We'll leave this part to you)

 

POST contents

User data

  • user_id: The user id of the currently logged in user (eg: 34)
  • user_login: The login of the currently logged in user (eg: joe)

Page data

  • title: The page title (eg. "All Versions") 
  • page_id: The id of the page from which the action menu item was clicked (eg: 1353)
  • entity_type: The entity type of the current page (eg. Version)
  • cols: A comma-separated list of system field names of all the visible columns on the page (eg. code, sg_status_list, description)
  • column_display_names: A comma-separated list of display names of all the visible columns on the page (eg. Version, Status, Description)
  • sort_column: The system name of the column that was sorted by (eg. code).
         * Only sent if there is a sort applied. If an advanced sort is applied, only the first sort-by column is sent. 
  • sort_direction: (eg. asc or desc)
         * Only sent if there is a sort applied 

Entity Ids

  • selected_ids: A comma-separated list of the selected entity ids (eg: 931, 900)
  • ids: A comma-separated list of all ids of the entities returned by the current page's query. This returns ALL Ids, including those that aren't visible due to pagination. (eg: 931, 900, 904, 907)

Project data (only sent if all entities on the current page share the same project)

  • project_name: The name of the Project (eg: Gunslinger)
  • project_id: The Id of the Project (eg: 81)

 

Custom protocol handler example

A more advanced implementation of custom ActionMenuItems involves setting up a custom protocol handler (eg: maya://version_0101). This allows you to bridge Shotgun with applications like Maya, RV, or Cinesync. (Note: We also have built-in integration with Maya and other software packages via the Pipeline Toolkit.) When you specify a url value of a custom protocol, the same post data is sent. You may want to use this to launch an in-house tool to dispatch different requests, for example.
To read more about setting up custom protocols, click here.

Limitations

When using custom protocols, the query info is sent as a GET request. Browsers have varying limitations of the size of the GET request they allow. Generally 2k is the lower limit which means you may experience "Failed to load resource" errors in your console if you attempt to select a lot of rows and launch your custom protocol. Since the column names are also sent in the query string, one way to increase the number of rows you can select in this case is to hide any columns you don't need on the page and launch your request again which will free up some characters in the query "bank". We're currently looking at ways to help solve this issue.

 

Examples

Here are some related example scripts to help get you started:

 

Limitations and Notes

  • Certain fields will never be sent in the POST request: Step columns, Thumbnails
  • Data is sent via POST for http and https links and GET for custom protocol links
  • When using custom protocols, the query info is sent as a GET request. Browsers have varying limitations of the size of the GET request they allow. Generally 2k is the lower limit which means you may experience "Failed to load resource" errors in your console if you attempt to select a lot of rows and launch your custom protocol. Since the column names are also sent in the query string, one way to increase the number of rows you can select in this case is to hide any columns you don't need on the page and launch your request again which will free up some characters in the query "bank". We're currently looking at ways to help solve this issue.
  • You can remove Action Menu Items using the delete() API method, or by deleting then from the Action Menu Items admin page in the UI.
Follow

21 Comments

  • 0
    Avatar
    Prabu Kasireddy

    Is there a way to group the Custom Menu items?

    We have 4 Custom menu items as of now for an entity and might have more in the future.

     

    We were wondering if there is a way to group the menu items based on what they do.

    Tried adding an item with the text as ----------------------- and left the URL blank - When this item is selected - the page freezes.

    Any thoughts?

  • 0
    Avatar
    KP

    We don't have a way to group the menu options yet, but I can certainly add that request to our list.

    Thinking you'd provide an additional parameter 'group' and then the menu would group up all items in the same group for that entity type with the value of 'group' as the menu header. Then each group would be separated by an appropriate separator as you're requesting. Does that sound like it would cover your use case?

  • 0
    Avatar
    Prabu Kasireddy

    Yes that sounds perfect.

    May be the order for the group by its name?

  • 0
    Avatar
    Chris Mihaly

    Is there any way to know what shotgun server instance called the tool web app?   We run a dev, produciton and staging server for shotgun and would like the tool to call back to the right shotgun instance?

  • 0
    Avatar
    KP

    The POST doesn't currently send the instance name or url in the request but we have it on our list to add this. You could inject it manually as part of the parameters in the ActionMenuItem for now which at least one client is doing but this is pretty hacky. Could you also get at it using the HTTP_REFERER? I haven't tested that but it might be worth a shot since I'm pretty sure Apache is sending that info.

  • 0
    Avatar
    Shani Turner

    in the data hash I set

     'url' : '/Volumes/SEAT_B/_developer/shani/scripts/smf/add_ref_link_actionmenu.py'

    but when I click on the new action menu item I created using this url I get this page:

    https://sassoonfilmdesign.shotgunstudio.com/Volumes/SEAT_B/_developer/shani/scripts/smf/add_ref_link_actionmenu.py

    with error:

    Sorry, this page does not exist. It may have been deleted or your link may be incorrect.

    If you believe this is an error, please contact support at support@shotgunsoftware.com.

    Do you know whayt I am doing wrong?

  • 0
    Avatar
    Stu Aitken

    Shani

     

    if you havn't already solved this, I'm pretty sure its because it needs a proper web URL - ie  http or https - it won't work with a local file system path

    the error returned infers that shotgun interpreted what you had supplied as a sub path on the hosted shotgun web site, not as a link to an actual script on your internal file server

    Shotgun assumes that the information is being passed to a web service not a local script

    the way to get his working would be to have your python script served from behind a web server (eg apache) at a specific URL

     

    hope that helps

  • 0
    Avatar
    Shani Turner

    thanks Stu for looking at my question and giving me some clues! Makes sense what you wrote, I'll try that....

  • 0
    Avatar
    Arthur Na

    Is there a way I can execute scripts/program that is stored in a local path?

  • 0
    Avatar
    Arthur Na

    I mean from action menu item .

  • 0
    Avatar
    Finn Nielsen

    When I select more than about 60 shots and invoke my custom protocol handler, Chrome refuses with a "Failed to load resource" error. I get a similar error in Firefox.

    I am wondering if the maximum size of a GET request as been exceeded. However, the documentation states that Shotgun uses POST - is this correct?

  • 0
    Avatar
    KP

    @finn

    The request is a POST if it is going to another website via http or https. Custom protocols use a GET format (ie. myhandler://dosomething?ids=1,2,3[........])

  • 0
    Avatar
    KP

     

    @Finn,

    It appears you may be correct. Though 60 rows is pretty low. Seems that much of the space is taken up by including the column names in the query. If you hide some of the columns on the page you should be able to select more than that. On my testing page, I was able to get almost 200 selected before I got that error.

    I've created a ticket to see if we can do something there. Maybe an option on ActionMenuItems to suppress the column names if they're not needed.

    As far as working around the browser limitation, seems like there's no defined limitation in any spec but they vary from browser to browser :/. Theoretically we could save the state of the page with some sort of key and then just pass the key in the GET request but that would change things a lot and require you to make an additional roundtrip to the server to get the ids.

    We'll think about this one, but for now I'd remove some columns from your page and see if that shrinks the request size to allow you to select more rows.

  • 0
    Avatar
    Finn Nielsen

    Thanks for investigating the issue thoroughly and providing a workaround:-)

    All my ActionMenuItem handler scripts use the Python API to do stuff in Shotgun, including get any needed additional data from the records. So in the case of this type of handlers, only the record id's are really needed. I would suggest an option on ActionMenuItems like the one you mentioned, except the request only contains a list of id's.

  • 0
    Avatar
    Dugan Chen

    The link to the " Handling ActionMenuItem Calls" example is broken.

  • 0
    Avatar
    Nate Barnard

    Could the entity type field become multi rather than single?  To have the same menu item available for more than one entity currently requires duplicating the Action Menu item and then updating to an additional type.  Keep it cleaner if we could just have one multi.

    Thanks,

    Nate

  • 0
    Avatar
    Patrick Wolf

    What happens when a user clicks on the Action Menu Item?

    ... Shotgun dispatches a POST request to the ActionMenuItem's url in a "NEW WINDOW" ...

    Would be great if Shotgun could open a in page pop up window instead of a new window to allow for seamless integration

    see feature request: https://support.shotgunsoftware.com/entries/44166336

  • 0
    Avatar
    Jake Richards

    Is there any sample code that redirects the user to the custom protocol?  I see the link for "Example: Handling Shotgun ActionMenuItem calls " but it basically just gets all the fields passed to it but I was interested in the last part where I redirect to the custom protocol.  Essentially, I'm looking for almost the same functionality as the "Play in RV" action menu item.  Thanks!

  • 0
    Avatar
    Sung, Yun-Chen - Paramount Animation

    The need to open URL in a new window requires popup windows to be enabled  (Safari won't enable on per-site basis) and is annoying to users who want to keep popups blocked when they browse.  Plus it leaves a new tab in browser every time the menu time is invoked.  So, I support Patrick Wolf's suggestion above... which is a year old now.

     

  • 0
    Avatar
    Tony Aiello

    This limitation noted above:

    sort_column: The system name of the column that was sorted by _(eg. code). _

         * Only sent if there is a sort applied. If an advanced sort is applied, only the first sort-by column is sent.

    is sad.  The same limitation applies to the grouping_column kwarg.  But, the full set of sort and group columns are available in the latest PageSetting entity for the current user for the page, or in the "zero-th" PageSetting if the current user hasn't modified the page from its default.  So if you're building an ActionMenuItem that needs to know the full grouping and sorting settings for the selected entities on a page, you'd have to both use the API to query for that latest "current user" PageSetting, as well as read the PostGreSQL directly for the zero-th PageSetting ... since as-of Shotgun 5, the API doesn't return the full details for a page's zero-th PageSetting.  :-(

    It would be so much more easier and helpful if the sort_column and the grouping_column could return multiple results, just like the cols and column_display_names.  Similarly, the sort_direction, grouping_direction, **and grouping_method** would have to be corresponding comma-separated lists too.

     

  • 0
    Avatar
    Alfred

    It's been more than a year since the last response, but after working with AMIs, I would like to add, that I support most of what westernx is doing to provide a more customized AMI setup:

     

    1. Grouping actions

    2. Icons

Please sign in to leave a comment.