From 106b50e5f5a82c9fafc9a006d7627e581704a099 Mon Sep 17 00:00:00 2001 From: Caroline Bridge <83305007+carolinebridge-oicr@users.noreply.github.com> Date: Thu, 29 Sep 2022 10:40:33 -0400 Subject: [PATCH] Add infrastructure for creating linear-genome-view sub-classes (#3227) * Infrastructure changes necessary for MLLV * styles import theme and export components runtime * export for external plugin runtime import * update snaps * snaps * remove ternary and tsignore snaps * Update extendedName description Co-authored-by: Colin --- packages/core/PluginManager.ts | 4 +- .../core/pluggableElementTypes/ViewType.ts | 10 +++ .../LinearGenomeView/components/Header.tsx | 14 ++-- .../components/LinearGenomeView.tsx | 22 ++---- .../components/MiniControls.tsx | 76 ++++++++++--------- .../src/LinearGenomeView/index.tsx | 24 +++++- plugins/linear-genome-view/src/index.ts | 5 ++ 7 files changed, 93 insertions(+), 62 deletions(-) diff --git a/packages/core/PluginManager.ts b/packages/core/PluginManager.ts index ee1505367a..5d8153a326 100644 --- a/packages/core/PluginManager.ts +++ b/packages/core/PluginManager.ts @@ -518,8 +518,10 @@ export default class PluginManager { const displays = this.getElementTypesInGroup('display') as DisplayType[] displays.forEach(display => { // view may have already added the displayType in its callback + // see ViewType for description of extendedName if ( - display.viewType === newView.name && + (display.viewType === newView.name || + display.viewType === newView.extendedName) && !newView.displayTypes.includes(display) ) { newView.addDisplayType(display) diff --git a/packages/core/pluggableElementTypes/ViewType.ts b/packages/core/pluggableElementTypes/ViewType.ts index eed827cdaa..f83ca77d6a 100644 --- a/packages/core/pluggableElementTypes/ViewType.ts +++ b/packages/core/pluggableElementTypes/ViewType.ts @@ -18,14 +18,24 @@ export default class ViewType extends PluggableElementBase { displayTypes: DisplayType[] = [] + // extendedName can be used for when you extend a given view type, and want + // to register all of that view types displays to yourself e.g. you create a + // linear-genome-view subtype, and want all the tracks that are compatible + // display types for the linear-genome-view to be compatible with your type + // also (without this, display types are only registered to a single view + // type) + extendedName?: string + constructor(stuff: { name: string ReactComponent: ViewReactComponent stateModel: IAnyModelType + extendedName?: string }) { super(stuff) this.ReactComponent = stuff.ReactComponent this.stateModel = stuff.stateModel + this.extendedName = stuff.extendedName if (!this.ReactComponent) { throw new Error(`no ReactComponent defined for view ${this.name}`) } diff --git a/plugins/linear-genome-view/src/LinearGenomeView/components/Header.tsx b/plugins/linear-genome-view/src/LinearGenomeView/components/Header.tsx index 08028be9e2..512b2305ac 100644 --- a/plugins/linear-genome-view/src/LinearGenomeView/components/Header.tsx +++ b/plugins/linear-genome-view/src/LinearGenomeView/components/Header.tsx @@ -119,13 +119,15 @@ const Controls = ({ model }: { model: LGV }) => { } const LinearGenomeViewHeader = observer(({ model }: { model: LGV }) => { - return model.hideHeaderOverview ? ( - - ) : ( - + return !model.hideHeader ? ( + model.hideHeaderOverview ? ( - - ) + ) : ( + + + + ) + ) : null }) export default LinearGenomeViewHeader diff --git a/plugins/linear-genome-view/src/LinearGenomeView/components/LinearGenomeView.tsx b/plugins/linear-genome-view/src/LinearGenomeView/components/LinearGenomeView.tsx index 2c1bf19a8e..20da8f5f1e 100644 --- a/plugins/linear-genome-view/src/LinearGenomeView/components/LinearGenomeView.tsx +++ b/plugins/linear-genome-view/src/LinearGenomeView/components/LinearGenomeView.tsx @@ -8,11 +8,9 @@ import { observer } from 'mobx-react' // locals import { LinearGenomeViewModel } from '..' -import Header from './Header' import TrackContainer from './TrackContainer' import TracksContainer from './TracksContainer' import ImportForm from './ImportForm' -import MiniControls from './MiniControls' import GetSequenceDialog from './GetSequenceDialog' import SearchResultsDialog from './SearchResultsDialog' @@ -47,7 +45,7 @@ const useStyles = makeStyles()(theme => ({ })) const LinearGenomeView = observer(({ model }: { model: LGV }) => { - const { tracks, error, hideHeader, initialized, hasDisplayedRegions } = model + const { tracks, error, initialized, hasDisplayedRegions } = model const { classes } = useStyles() if (!initialized && !error) { @@ -61,6 +59,9 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => { return } + const MiniControlsComponent = model.MiniControlsComponent() + const HeaderComponent = model.HeaderComponent() + return (
{model.seqDialogDisplayed ? ( @@ -75,19 +76,8 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => { handleClose={() => model.setSearchResults(undefined, undefined)} /> ) : null} - {!hideHeader ? ( -
- ) : ( -
- -
- )} + + {!tracks.length ? ( diff --git a/plugins/linear-genome-view/src/LinearGenomeView/components/MiniControls.tsx b/plugins/linear-genome-view/src/LinearGenomeView/components/MiniControls.tsx index 4484a8d131..72c1113130 100644 --- a/plugins/linear-genome-view/src/LinearGenomeView/components/MiniControls.tsx +++ b/plugins/linear-genome-view/src/LinearGenomeView/components/MiniControls.tsx @@ -9,46 +9,48 @@ import { LinearGenomeViewModel } from '..' const MiniControls = observer((props: { model: LinearGenomeViewModel }) => { const { model } = props - const { bpPerPx, maxBpPerPx, minBpPerPx, scaleFactor } = model + const { bpPerPx, maxBpPerPx, minBpPerPx, scaleFactor, hideHeader } = model const [anchorEl, setAnchorEl] = useState() - return ( - - setAnchorEl(event.currentTarget)} - > - - + return hideHeader ? ( +
+ + setAnchorEl(event.currentTarget)} + > + + - model.zoom(bpPerPx * 2)} - disabled={bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1} - color="secondary" - > - - - model.zoom(model.bpPerPx / 2)} - disabled={bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1} - color="secondary" - > - - - { - callback() - setAnchorEl(undefined) - }} - onClose={() => setAnchorEl(undefined)} - menuItems={model.menuItems()} - /> - - ) + model.zoom(bpPerPx * 2)} + disabled={bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1} + color="secondary" + > + + + model.zoom(model.bpPerPx / 2)} + disabled={bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1} + color="secondary" + > + + + { + callback() + setAnchorEl(undefined) + }} + onClose={() => setAnchorEl(undefined)} + menuItems={model.menuItems()} + /> + +
+ ) : null }) export default MiniControls diff --git a/plugins/linear-genome-view/src/LinearGenomeView/index.tsx b/plugins/linear-genome-view/src/LinearGenomeView/index.tsx index a997678536..e9f5255327 100644 --- a/plugins/linear-genome-view/src/LinearGenomeView/index.tsx +++ b/plugins/linear-genome-view/src/LinearGenomeView/index.tsx @@ -1,4 +1,4 @@ -import { lazy } from 'react' +import React, { lazy } from 'react' import { getConf, AnyConfigurationModel } from '@jbrowse/core/configuration' import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes/models' import { Region } from '@jbrowse/core/util/types' @@ -53,6 +53,10 @@ import { renderToSvg } from './components/LinearGenomeViewSvg' import RefNameAutocomplete from './components/RefNameAutocomplete' import SearchBox from './components/SearchBox' import ExportSvgDlg from './components/ExportSvgDialog' +import MiniControls from './components/MiniControls' +import Header from './components/Header' +import ZoomControls from './components/ZoomControls' +import LinearGenomeView from './components/LinearGenomeView' const SequenceSearchDialog = lazy( () => import('./components/SequenceSearchDialog'), @@ -192,6 +196,16 @@ export function stateModelFactory(pluginManager: PluginManager) { }, })) .views(self => ({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + MiniControlsComponent(): React.FC { + return MiniControls + }, + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + HeaderComponent(): React.FC { + return Header + }, + get assemblyErrors() { const { assemblyManager } = getSession(self) const { assemblyNames } = self @@ -1220,7 +1234,13 @@ export function stateModelFactory(pluginManager: PluginManager) { })) } -export { renderToSvg, RefNameAutocomplete, SearchBox } +export { + renderToSvg, + RefNameAutocomplete, + SearchBox, + ZoomControls, + LinearGenomeView, +} export type LinearGenomeViewStateModel = ReturnType export type LinearGenomeViewModel = Instance export { default as ReactComponent } from './components/LinearGenomeView' diff --git a/plugins/linear-genome-view/src/index.ts b/plugins/linear-genome-view/src/index.ts index ddfc6697eb..fbabc94d89 100644 --- a/plugins/linear-genome-view/src/index.ts +++ b/plugins/linear-genome-view/src/index.ts @@ -29,6 +29,8 @@ import { renderToSvg, RefNameAutocomplete, SearchBox, + ZoomControls, + LinearGenomeView, } from './LinearGenomeView' import { @@ -45,6 +47,9 @@ export default class LinearGenomeViewPlugin extends Plugin { BaseLinearDisplayComponent, BaseLinearDisplay, baseLinearDisplayConfigSchema, + SearchBox, + ZoomControls, + LinearGenomeView, } install(pluginManager: PluginManager) {