Skip to content

Commit

Permalink
Add example of defining and using a plugin with the embedded compone…
Browse files Browse the repository at this point in the history
…nt (#2437)
  • Loading branch information
cmdcolin committed Oct 21, 2021
1 parent 6d9b1c2 commit a47c5fd
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 129 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
/* eslint-disable no-console */
import React, { useEffect, useState } from 'react'
import { PluginRecord } from '@jbrowse/core/PluginLoader'
import { observer } from 'mobx-react'
import { PluginRecord } from '@jbrowse/core/PluginLoader'
import { Region } from '@jbrowse/core/util/types'
import { createViewState, JBrowseLinearGenomeView, loadPlugins } from '../src'
import ViewType from '@jbrowse/core/pluggableElementTypes/ViewType'
import PluginManager from '@jbrowse/core/PluginManager'
import Plugin from '@jbrowse/core/Plugin'

// locals
import { createViewState, loadPlugins, JBrowseLinearGenomeView } from '../src'

// configs
import volvoxConfig from '../public/test_data/volvox/config.json'
import volvoxSession from '../public/volvox-session.json'
import nextstrainConfig from '../public/nextstrain_covid.json'
Expand Down Expand Up @@ -52,7 +60,6 @@ export const OneLinearGenomeView = () => {
// use 1-based coordinates for locstring
location: 'ctgA:1105..1221',
onChange: patch => {
// eslint-disable-next-line no-console
console.log('patch', patch)
},
})
Expand Down Expand Up @@ -124,122 +131,6 @@ export const TwoLinearGenomeViews = () => {
)
}

export const WithPlugins = () => {
// usage with buildtime plugins
// this plugins array is then passed to the createViewState constructor
// import UCSCPlugin from 'jbrowse-plugin-ucsc'
// const plugins = [UCSCPlugin]

// usage with runtime plugins
// this plugins array is then passed to the createViewState constructor
const [plugins, setPlugins] = useState<PluginRecord[]>()
useEffect(() => {
async function getPlugins() {
const loadedPlugins = await loadPlugins([
{
name: 'UCSC',
url: 'https://unpkg.com/jbrowse-plugin-ucsc@^1/dist/jbrowse-plugin-ucsc.umd.production.min.js',
},
])
setPlugins(loadedPlugins)
}
getPlugins()
}, [setPlugins])

if (!plugins) {
return null
}

const state = createViewState({
assembly: {
name: 'hg19',
aliases: ['GRCh37'],
sequence: {
type: 'ReferenceSequenceTrack',
trackId: 'Pd8Wh30ei9R',
adapter: {
type: 'BgzipFastaAdapter',
fastaLocation: {
uri: 'https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz',
locationType: 'UriLocation',
},
faiLocation: {
uri: 'https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai',
locationType: 'UriLocation',
},
gziLocation: {
uri: 'https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi',
locationType: 'UriLocation',
},
},
},
refNameAliases: {
adapter: {
type: 'RefNameAliasAdapter',
location: {
uri: 'https://s3.amazonaws.com/jbrowse.org/genomes/hg19/hg19_aliases.txt',
locationType: 'UriLocation',
},
},
},
},
plugins: plugins.map(p => p.plugin),
tracks: [
{
type: 'FeatureTrack',
trackId: 'segdups_ucsc_hg19',
name: 'UCSC SegDups',
category: ['Annotation'],
assemblyNames: ['hg19'],
adapter: {
type: 'UCSCAdapter',
track: 'genomicSuperDups',
},
},
],
location: '1:2,467,681..2,667,681',
defaultSession: {
name: 'Runtime plugins',
view: {
id: 'aU9Nqje1U',
type: 'LinearGenomeView',
offsetPx: 22654,
bpPerPx: 108.93300653594771,
displayedRegions: [
{
refName: '1',
start: 0,
end: 249250621,
reversed: false,
assemblyName: 'hg19',
},
],
tracks: [
{
id: 'MbiRphmDa',
type: 'FeatureTrack',
configuration: 'segdups_ucsc_hg19',
displays: [
{
id: '8ovhuA5cFM',
type: 'LinearBasicDisplay',
height: 100,
configuration: 'segdups_ucsc_hg19-LinearBasicDisplay',
},
],
},
],
hideHeader: false,
hideHeaderOverview: false,
trackSelectorType: 'hierarchical',
trackLabels: 'overlapping',
showCenterLine: false,
},
},
})
return <JBrowseLinearGenomeView viewState={state} />
}

export const WithTextSearching = () => {
const textSearchConfig = {
assembly,
Expand Down Expand Up @@ -454,7 +345,6 @@ export const NextstrainExample = () => {
defaultSession,
location: 'SARS-CoV-2:1..29,903',
onChange: patch => {
// eslint-disable-next-line no-console
console.log('patch', patch)
},
configuration: {
Expand Down Expand Up @@ -502,6 +392,183 @@ export const VisibleRegionsExample = () => {
)
}

export const WithInlinePlugin = () => {
// you don't have to necessarily define this inside your react component, it
// just helps so that you can see the source code in the storybook to have it
// here
class HighlightRegionPlugin extends Plugin {
name = 'HighlightRegionPlugin'

install(pluginManager: PluginManager) {
pluginManager.addToExtensionPoint(
'Core-extendPluggableElement',
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(pluggableElement: any) => {
if (pluggableElement.name === 'LinearGenomeView') {
const { stateModel } = pluggableElement as ViewType
const newStateModel = stateModel.extend(self => {
const superRubberBandMenuItems = self.rubberBandMenuItems
return {
views: {
rubberBandMenuItems() {
return [
...superRubberBandMenuItems(),
{
label: 'Console log selected region',
onClick: () => {
const { leftOffset, rightOffset } = self
const selectedRegions = self.getSelectedRegions(
leftOffset,
rightOffset,
)
// console log the list of potentially multiple
// regions that were selected
console.log(selectedRegions)
},
},
]
},
},
}
})

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

configure() {}
}

const state = createViewState({
assembly,
plugins: [HighlightRegionPlugin],
tracks,
defaultSession,
location: 'ctgA:1105..1221',
})

return <JBrowseLinearGenomeView viewState={state} />
}

export const WithExternalPlugins = () => {
// usage with buildtime plugins
// this plugins array is then passed to the createViewState constructor
// import UCSCPlugin from 'jbrowse-plugin-ucsc'
// const plugins = [UCSCPlugin]

// usage with runtime plugins
// this plugins array is then passed to the createViewState constructor
const [plugins, setPlugins] = useState<PluginRecord[]>()
useEffect(() => {
async function getPlugins() {
const loadedPlugins = await loadPlugins([
{
name: 'UCSC',
url: 'https://unpkg.com/jbrowse-plugin-ucsc@^1/dist/jbrowse-plugin-ucsc.umd.production.min.js',
},
])
setPlugins(loadedPlugins)
}
getPlugins()
}, [setPlugins])

if (!plugins) {
return null
}

const state = createViewState({
assembly: {
name: 'hg19',
aliases: ['GRCh37'],
sequence: {
type: 'ReferenceSequenceTrack',
trackId: 'Pd8Wh30ei9R',
adapter: {
type: 'BgzipFastaAdapter',
fastaLocation: {
uri: 'https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz',
locationType: 'UriLocation',
},
faiLocation: {
uri: 'https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai',
locationType: 'UriLocation',
},
gziLocation: {
uri: 'https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi',
locationType: 'UriLocation',
},
},
},
refNameAliases: {
adapter: {
type: 'RefNameAliasAdapter',
location: {
uri: 'https://s3.amazonaws.com/jbrowse.org/genomes/hg19/hg19_aliases.txt',
locationType: 'UriLocation',
},
},
},
},
plugins: plugins.map(p => p.plugin),
tracks: [
{
type: 'FeatureTrack',
trackId: 'segdups_ucsc_hg19',
name: 'UCSC SegDups',
category: ['Annotation'],
assemblyNames: ['hg19'],
adapter: {
type: 'UCSCAdapter',
track: 'genomicSuperDups',
},
},
],
location: '1:2,467,681..2,667,681',
defaultSession: {
name: 'Runtime plugins',
view: {
id: 'aU9Nqje1U',
type: 'LinearGenomeView',
offsetPx: 22654,
bpPerPx: 108.93300653594771,
displayedRegions: [
{
refName: '1',
start: 0,
end: 249250621,
reversed: false,
assemblyName: 'hg19',
},
],
tracks: [
{
id: 'MbiRphmDa',
type: 'FeatureTrack',
configuration: 'segdups_ucsc_hg19',
displays: [
{
id: '8ovhuA5cFM',
type: 'LinearBasicDisplay',
height: 100,
configuration: 'segdups_ucsc_hg19-LinearBasicDisplay',
},
],
},
],
hideHeader: false,
hideHeaderOverview: false,
trackSelectorType: 'hierarchical',
trackLabels: 'overlapping',
showCenterLine: false,
},
},
})
return <JBrowseLinearGenomeView viewState={state} />
}

const JBrowseLinearGenomeViewStories = {
title: 'Linear View',
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@ import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks'

You can use extra load a plugin at runtime for the embedded component.

This can come in the form of
This example loads a plugin that is defined in your own source code

- Plugins loaded a build time
- Plugins loaded at runtime
<Canvas withSource="open">
<Story id="linear-view--with-inline-plugins" />
</Canvas>

The build time would be installed from NPM and included in your source code for
setting up the components. The runtime ones would load e.g. from a URL, and
you'd also write some code to load those. This example shows runtime, but a
small source code comment in this example shows how build time would be used
too
This example loads a plugin from an external URL

<Canvas withSource="open">
<Story id="linear-view--with-plugins" />
<Story id="linear-view--with-external-plugins" />
</Canvas>

0 comments on commit a47c5fd

Please sign in to comment.