Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactors for app-core view container #3994

Merged
merged 8 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 6 additions & 42 deletions packages/app-core/src/ui/App/ViewContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
import React, { useEffect, useRef } from 'react'
import { IconButton, Paper, useTheme } from '@mui/material'
import React, { useEffect } from 'react'
import { Paper, useTheme } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import { observer } from 'mobx-react'
import { getSession, useWidthSetter } from '@jbrowse/core/util'
import clsx from 'clsx'
import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes/models'
import { SessionWithFocusedViewAndDrawerWidgets } from '@jbrowse/core/util'

// icons
import CloseIcon from '@mui/icons-material/Close'
import MinimizeIcon from '@mui/icons-material/Minimize'
import AddIcon from '@mui/icons-material/Add'

// locals
import ViewMenu from './ViewMenu'
import ViewContainerTitle from './ViewContainerTitle'
import ViewHeader from './ViewHeader'

const useStyles = makeStyles()(theme => ({
viewContainer: {
overflow: 'hidden',
margin: theme.spacing(0.5),
padding: `0 ${theme.spacing(1)} ${theme.spacing(1)}`,
},
icon: {
color: theme.palette.secondary.contrastText,
},
grow: {
flexGrow: 1,
},
focusedView: {
background: theme.palette.secondary.main,
},
Expand All @@ -47,18 +34,11 @@ const ViewContainer = observer(function ({
onMinimize: () => void
children: React.ReactNode
}) {
const { classes } = useStyles()
const theme = useTheme()
const ref = useWidthSetter(view, theme.spacing(1))
const scrollRef = useRef<HTMLDivElement>(null)
const { classes, cx } = useStyles()
const session = getSession(view) as SessionWithFocusedViewAndDrawerWidgets

// scroll the view into view when first mounted. note: this effect will run
// only once, because of the empty array second param
useEffect(() => {
scrollRef.current?.scrollIntoView?.({ block: 'center' })
}, [])

useEffect(() => {
function handleSelectView(e: Event) {
if (e.target instanceof Element) {
Expand All @@ -80,30 +60,14 @@ const ViewContainer = observer(function ({
<Paper
ref={ref}
elevation={12}
className={clsx(
className={cx(
classes.viewContainer,
session.focusedViewId === view.id
? classes.focusedView
: classes.unfocusedView,
)}
>
<div ref={scrollRef} style={{ display: 'flex' }}>
<ViewMenu model={view} IconProps={{ className: classes.icon }} />
<div className={classes.grow} />

<ViewContainerTitle view={view} />
<div className={classes.grow} />
<IconButton data-testid="minimize_view" onClick={onMinimize}>
{view.minimized ? (
<AddIcon className={classes.icon} fontSize="small" />
) : (
<MinimizeIcon className={classes.icon} fontSize="small" />
)}
</IconButton>
<IconButton data-testid="close_view" onClick={onClose}>
<CloseIcon className={classes.icon} fontSize="small" />
</IconButton>
</div>
<ViewHeader view={view} onClose={onClose} onMinimize={onMinimize} />
<Paper>{children}</Paper>
</Paper>
)
Expand Down
66 changes: 66 additions & 0 deletions packages/app-core/src/ui/App/ViewHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { useEffect, useRef } from 'react'
import { IconButton } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import { observer } from 'mobx-react'
import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes/models'

// icons
import CloseIcon from '@mui/icons-material/Close'
import MinimizeIcon from '@mui/icons-material/Minimize'
import AddIcon from '@mui/icons-material/Add'

// locals
import ViewMenu from './ViewMenu'
import ViewContainerTitle from './ViewContainerTitle'

const useStyles = makeStyles()(theme => ({
icon: {
color: theme.palette.secondary.contrastText,
},
grow: {
flexGrow: 1,
},
viewHeader: {
display: 'flex',
},
}))

const ViewHeader = observer(function ({
view,
onClose,
onMinimize,
}: {
view: IBaseViewModel
onClose: () => void
onMinimize: () => void
}) {
const { classes } = useStyles()
const scrollRef = useRef<HTMLDivElement>(null)

// scroll the view into view when first mounted. note: this effect will run
// only once, because of the empty array second param
useEffect(() => {
scrollRef.current?.scrollIntoView?.({ block: 'center' })
}, [])
return (
<div ref={scrollRef} className={classes.viewHeader}>
<ViewMenu model={view} IconProps={{ className: classes.icon }} />
<div className={classes.grow} />

<ViewContainerTitle view={view} />
<div className={classes.grow} />
<IconButton data-testid="minimize_view" onClick={onMinimize}>
{view.minimized ? (
<AddIcon className={classes.icon} fontSize="small" />
) : (
<MinimizeIcon className={classes.icon} fontSize="small" />
)}
</IconButton>
<IconButton data-testid="close_view" onClick={onClose}>
<CloseIcon className={classes.icon} fontSize="small" />
</IconButton>
</div>
)
})

export default ViewHeader
14 changes: 7 additions & 7 deletions packages/core/pluggableElementTypes/models/baseTrackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,19 @@ export function createBaseTrackConfig(pluginManager: PluginManager) {
type: string
displays: { type: string; displayId: string }[]
}
const displayTypes = new Set()
const { displays = [] } = snap
if (snap.trackId !== 'placeholderId') {
// Gets the displays on the track snapshot and the possible displays
// from the track type and adds any missing possible displays to the
// snapshot
displays.forEach(d => d && displayTypes.add(d.type))
const trackType = pluginManager.getTrackType(snap.type)
trackType.displayTypes.forEach(displayType => {
if (!displayTypes.has(displayType.name)) {
const configDisplayTypes = new Set(
displays.filter(d => !!d).map(d => d.type),
)
pluginManager.getTrackType(snap.type).displayTypes.forEach(d => {
if (!configDisplayTypes.has(d.name)) {
displays.push({
displayId: `${snap.trackId}-${displayType.name}`,
type: displayType.name,
displayId: `${snap.trackId}-${d.name}`,
type: d.name,
})
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { lazy, useEffect, useRef } from 'react'
import { Button, Paper, Typography } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import { LoadingEllipses } from '@jbrowse/core/ui'
import { getSession } from '@jbrowse/core/util'
import { observer } from 'mobx-react'

// icons
Expand All @@ -11,7 +12,6 @@ import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons'
import { LinearGenomeViewModel } from '..'
import TrackContainer from './TrackContainer'
import TracksContainer from './TracksContainer'
import { getSession } from '@jbrowse/core/util'

const ImportForm = lazy(() => import('./ImportForm'))

Expand All @@ -23,16 +23,45 @@ const useStyles = makeStyles()(theme => ({
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(1),
},
rel: {
position: 'relative',
},
}))

function NoTracksActive({ model }: { model: LinearGenomeViewModel }) {
const { classes } = useStyles()
const { hideNoTracksActive } = model
return (
<Paper className={classes.note}>
{!hideNoTracksActive ? (
<>
<Typography>No tracks active.</Typography>
<Button
variant="contained"
color="primary"
onClick={() => model.activateTrackSelector()}
style={{ zIndex: 1000 }}
startIcon={<TrackSelectorIcon />}
>
Open track selector
</Button>
</>
) : (
<div style={{ height: '48px' }}></div>
)}
</Paper>
)
}

const LinearGenomeView = observer(({ model }: { model: LGV }) => {
const { tracks, error, initialized, hasDisplayedRegions } = model
const { classes } = useStyles()
const ref = useRef<HTMLDivElement>(null)
const session = getSession(model)
const { classes } = useStyles()

useEffect(() => {
// sets the focused view id based on a click within the LGV; necessary for subviews to be focused properly
// sets the focused view id based on a click within the LGV;
// necessary for subviews to be focused properly
function handleSelectView(e: Event) {
if (e.target instanceof Element && ref?.current?.contains(e.target)) {
session.setFocusedViewId?.(model.id)
Expand All @@ -58,29 +87,12 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
const HeaderComponent = model.HeaderComponent()

return (
<div style={{ position: 'relative' }} ref={ref}>
<div className={classes.rel} ref={ref}>
<HeaderComponent model={model} />
<MiniControlsComponent model={model} />
<TracksContainer model={model}>
{!tracks.length ? (
<Paper variant="outlined" className={classes.note}>
{!model.hideNoTracksActive ? (
<>
<Typography>No tracks active.</Typography>
<Button
variant="contained"
color="primary"
onClick={model.activateTrackSelector}
style={{ zIndex: 1000 }}
startIcon={<TrackSelectorIcon />}
>
Open track selector
</Button>
</>
) : (
<div style={{ height: '48px' }}></div>
)}
</Paper>
<NoTracksActive model={model} />
) : (
tracks.map(track => (
<TrackContainer key={track.id} model={model} track={track} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ const useStyles = makeStyles()({
position: 'absolute',
zIndex: 10,
},
rel: {
position: 'relative',
},
})

const HoverTooltip = observer(function ({
Expand Down Expand Up @@ -155,7 +158,7 @@ const OverviewRubberband = observer(function OverviewRubberband({

if (startX === undefined) {
return (
<div style={{ position: 'relative' }}>
<div className={classes.rel}>
{guideX !== undefined ? (
<HoverTooltip
model={model}
Expand Down Expand Up @@ -195,7 +198,7 @@ const OverviewRubberband = observer(function OverviewRubberband({
}

return (
<div style={{ position: 'relative' }}>
<div className={classes.rel}>
{leftBpOffset && rightBpOffset ? (
<RubberbandSpan
leftBpOffset={leftBpOffset}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
exports[`renders one track, one region 1`] = `
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div
class="css-dznme2-rubberbandControl"
Expand Down Expand Up @@ -560,11 +560,11 @@ exports[`renders one track, one region 1`] = `
exports[`renders two tracks, two regions 1`] = `
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div
class="css-dznme2-rubberbandControl"
Expand Down
13 changes: 3 additions & 10 deletions plugins/linear-genome-view/src/LinearGenomeView/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1522,22 +1522,15 @@ export function stateModelFactory(pluginManager: PluginManager) {
if (session.focusedViewId === self.id && (e.ctrlKey || e.metaKey)) {
if (e.code === 'ArrowLeft') {
e.preventDefault()
// pan left
self.slide(-0.9)
}
if (e.code === 'ArrowRight') {
} else if (e.code === 'ArrowRight') {
e.preventDefault()
// pan right
self.slide(0.9)
}
if (e.code === 'ArrowUp' && self.scaleFactor === 1) {
} else if (e.code === 'ArrowUp' && self.scaleFactor === 1) {
e.preventDefault()
// zoom in
self.zoom(self.bpPerPx / 2)
}
if (e.code === 'ArrowDown' && self.scaleFactor === 1) {
} else if (e.code === 'ArrowDown' && self.scaleFactor === 1) {
e.preventDefault()
// zoom out
self.zoom(self.bpPerPx * 2)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ exports[`<JBrowseLinearGenomeView /> renders successfully 1`] = `
class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-1ps6pg7-MuiPaper-root"
>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div
class="css-dznme2-rubberbandControl"
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5836,9 +5836,9 @@ available-typed-arrays@^1.0.5:
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==

aws-sdk@^2.1231.0:
version "2.1477.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1477.0.tgz#ec878ea5584fee217eb02ec8f6ebfd9ace47f908"
integrity sha512-DLsrKosrKRe5P1E+BcJAVpOXkma4oUOrcyBUridDmUhdf9k3jj5dnL1roFuDpTmNDDhK8a1tUgY3wmXoKQtv7A==
version "2.1478.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1478.0.tgz#30edc3a34fb0c40f30e5512e5e02c630ef849022"
integrity sha512-F+Ud9FxMD4rwvGbEXn7qc25Q19N4p+9klRjiH1llFLYssPw6TRtY464Cry/jG4OzuYkE/DsnhcwVFEJjGvMmuQ==
dependencies:
buffer "4.9.2"
events "1.1.1"
Expand Down
Loading