GMOD / jbrowse-components

Source code for JBrowse 2, a modern React-based genome browser
https://jbrowse.org/jb2
Apache License 2.0
202 stars 61 forks source link

Add ability to customize feature left click behavior #2400

Open benwbooth opened 2 years ago

benwbooth commented 2 years ago

I would like to have to ability to customize what happens when left clicking a feature. For example, I would like to open a new page instead of display the feature details drawer. This capability was in JBrowse 1 (https://jbrowse.org/docs/mouse_configs.html#click-configuration-options). JBrowse 1 also had a "linkTemplate" attribute which could be used to provide the URL to follow when clicking a feature. If the user wanted to see the feature details drawer, they could still right-click and select it from the context menu.

Right now the only workaround is to add a feature attribute that is a URL, then the user must click on the feature to open the feature details drawer, then click on the link in the feature attribute.

cmdcolin commented 2 years ago

@benwbooth thanks for posting this. currently there is no config way to do this. currently the logic for what happens when you click a feature is in the selectFeature method on the display type. different track types override this behavior to open up different types of sidebar widgets for example, but we don't have a built in way to change the behavior via the config

would also be good to add right-click menu slots, and also make the ability to customize the contents of the feature details more easily e.g. add links to the sidebar without actually encoding links in the gff

evanVerinomics commented 10 months ago

This is exactly the feature I'm looking for, is it possible to add menu items to the right click feature? I've tried updating the source code and even that isn't working.

cmdcolin commented 10 months ago

the code to modify is contextMenuItems()

https://github.com/GMOD/jbrowse-components/blob/f12cb4119061e1a155f6fc50a3c35575be352d4c/plugins/linear-genome-view/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx#L283-L302

you could try directly modifying the code there, then run "yarn start" in the products/jbrowse-web directory, and it will watch for your code modifications

instead of directly modifying the code, there are a couple other options

for plugin type code can either

a) use the Core-extendPluggableElement' to extend the display model of interest, to add extra context menu items. this does mutate the display model of interest, so then all instances of "BaseLinearDisplayModel" will have your custom right click menu modifications. here is actually some example code that adds an extra context menu item to alignments track features (adds right click option to the pileup display) https://github.com/GMOD/jbrowse-components/blob/6ceeac51f8bcecfc3b0a99e23f2277a6e5a7662e/plugins/dotplot-view/src/extensionPoints.ts#L9-L38. small amount of more docs here https://jbrowse.org/jb2/docs/developer_guides/extension_points/#core-extendpluggableelement

b) make a new display type. your new display type can e.g. "inherit" from BaseLinearDisplayModel, but then you add your own contextMenuItems. this will not doesn't mutate the existing display type, as (a) did. Normally when making a new display type, you register your display type with another track type (LinearBasicDisplay, which uses the BaseLinearDisplayModel, is associated with a generic "FeatureTrack") or make a new track type to associate it with

cmdcolin commented 10 months ago

the option (c) where we allow modifying these things directly from the config file is another option but we have not done anything for this. i imagine we could make it a jexl enabled type to allow some configurability.

evanVerinomics commented 10 months ago

Thanks for your quick response, this pushed me in the right direction. Here's what ended up working for me if anyone else needs a plugin solution for this action:


`    class VariantFeaturePlugin extends Plugin {
        name = "VariantFeaturePlugin";

        install(pluginManager) {
            pluginManager.addToExtensionPoint(
                "Core-extendPluggableElement",
                pluggableElement => {
                    // console.log("pluggable el: ", pluggableElement.name );
                    if (pluggableElement.name === "LinearVariantDisplay" ) {
                        const { stateModel } = pluggableElement;
                        const newStateModel = stateModel.extend(self => {
                            const superContextMenuItems = self.contextMenuItems;
                            return {
                                views: {
                                    contextMenuItems() {
                                        const feature = self.contextMenuFeature;
                                        if (!feature) {
                                            return superContextMenuItems();
                                        }
                                        const newMenuItems = [
                                            ...superContextMenuItems(),
                                            {
                                                label: "New Feature",
                                                icon: AddIcon,
                                                onClick: () => {
                                                    console.log("got here! ");
                                                }
                                            }
                                        ];

                                        return newMenuItems;
                                    }
                                }
                            };
                        });

                        pluggableElement.stateModel = newStateModel;
                    }
                    return pluggableElement;
                }
            );
        }

        configure() { }
    }`