plotly / dash-cytoscape

Interactive network visualization in Python and Dash, powered by Cytoscape.js
https://dash.plot.ly/cytoscape
MIT License
601 stars 119 forks source link

adding support for context-menu #196

Closed cleaaum closed 10 months ago

cleaaum commented 11 months ago

This PR integrates the external js library "cytoscape-context-menus" to give the user the ability to define its own context menu.

In order to add a context menu item the user needs to use the contextMenu prop and pass at least the following items to create the menu item.

contextMenu=[
                {
                    "id": "item-id",
                    "label": "menu item text",
                    "tooltipText": "tooltip",
                    "availableOn": ["node", "edge"],
                    "onClick(Custom)": "behaviour",
                }
]

Then, the user has three options to define the onClick behaviour: 1) Using a pre defined js function by passing one of the built-in functions. For now, remove, add_node, and add_edge are supported. This is done by setting "onClick": "remove" for example. 2) Using a namespace by providing a user defined js function in window.dashCytoscapeComponentFunctions. This is done by setting "onClickCustom": "add-2-nodes" for example, where add-2-nodes is defined in the namespace. 3) Using Python in a Dash Callback. In this case js will return relevant information to modify the Cytoscape elements accordingly. These are accessible through the ContextMenuData and elements prop. The user must simply omit the "onClick" key.

I've provided a sample app (usage-context-menu.py) with a context menu and also provided a js namespace under assets/ctxMenuFns.js with an example of a user defined js function. This example has the following context menu items implemented via the following methods: 1) Using a pre defined js function:remove, add_node, and add_edge. 2) Using a namespace: add-2-nodes 3) Using Python in a Dash Callback: split_edge and revert_edge

Pre-Merge checklist

alexcjohnson commented 11 months ago

@cleaaum this looks great! Two questions about the API:

cleaaum commented 11 months ago

@alexcjohnson Thank you for the review Alex! I've addressed all comments except for the add-edge one (i've left an explanation). I think I prefer differentiating them with onClickUser and onClickBuiltIn, or even just onClick.

cleaaum commented 11 months ago

@alexcjohnson and @emilykl - I believe this PR is ready for a final review. I have updated tests to test context menu item behaviours as well as updating the context menu via a callback. The prop docstrings have been updated and the contextMenu props have been renamed for clarity. After discussing functional components with Hatch, it seems like converting cytoscape to a functional component would take quite a bit of time. If we were to do this, I think it would make more sense to merge the context menu PR first and work on this on a separate branch. What I have currently implemented uses shouldComponentUpdate() and componentDidUpdate() and this works well (just outdated).

emilykl commented 11 months ago

@cleaaum Just finished a final look over -- my only comments are the super nitpicky docstring edits and the logic in the create context menu function -- otherwise lgtm! 🎉

emilykl commented 11 months ago

Oh also @cleaaum check the failing CI steps. At least some of them are very easy fixes.