@jbrowse/app-core 2.6.1 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -7
- package/src/Assemblies/SessionAssembliesMixin.ts +0 -50
- package/src/Assemblies/TemporaryAssembliesMixin.ts +0 -51
- package/src/Assemblies/index.ts +0 -2
- package/src/HistoryManagement/index.ts +0 -56
- package/src/JBrowseConfig/index.ts +0 -173
- package/src/JBrowseModel/index.ts +0 -150
- package/src/RootMenu/index.ts +0 -157
- package/src/index.ts +0 -6
- package/src/ui/App/App.tsx +0 -117
- package/src/ui/App/AppFab.tsx +0 -45
- package/src/ui/App/AppToolbar.tsx +0 -89
- package/src/ui/App/DialogQueue.tsx +0 -22
- package/src/ui/App/Drawer.tsx +0 -56
- package/src/ui/App/DrawerWidget.tsx +0 -238
- package/src/ui/App/ViewContainer.tsx +0 -76
- package/src/ui/App/ViewContainerTitle.tsx +0 -55
- package/src/ui/App/ViewLauncher.tsx +0 -64
- package/src/ui/App/ViewMenu.tsx +0 -54
- package/src/ui/App/ViewPanel.tsx +0 -63
- package/src/ui/App/index.ts +0 -1
- package/src/ui/index.ts +0 -1
package/src/ui/App/App.tsx
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import React, { Suspense, lazy } from 'react'
|
|
2
|
-
import { AppBar } from '@mui/material'
|
|
3
|
-
import { makeStyles } from 'tss-react/mui'
|
|
4
|
-
import { observer } from 'mobx-react'
|
|
5
|
-
import { SessionWithDrawerWidgets } from '@jbrowse/core/util'
|
|
6
|
-
import Snackbar from '@jbrowse/core/ui/Snackbar'
|
|
7
|
-
import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel'
|
|
8
|
-
import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu'
|
|
9
|
-
|
|
10
|
-
// locals
|
|
11
|
-
import AppToolbar from './AppToolbar'
|
|
12
|
-
import ViewLauncher from './ViewLauncher'
|
|
13
|
-
import ViewPanel from './ViewPanel'
|
|
14
|
-
import DialogQueue from './DialogQueue'
|
|
15
|
-
import AppFab from './AppFab'
|
|
16
|
-
|
|
17
|
-
const DrawerWidget = lazy(() => import('./DrawerWidget'))
|
|
18
|
-
|
|
19
|
-
const useStyles = makeStyles()(theme => ({
|
|
20
|
-
root: {
|
|
21
|
-
display: 'grid',
|
|
22
|
-
height: '100vh',
|
|
23
|
-
width: '100%',
|
|
24
|
-
colorScheme: theme.palette.mode,
|
|
25
|
-
},
|
|
26
|
-
appContainer: {
|
|
27
|
-
gridColumn: 'main',
|
|
28
|
-
display: 'grid',
|
|
29
|
-
gridTemplateRows: '[menubar] min-content [components] auto',
|
|
30
|
-
height: '100vh',
|
|
31
|
-
},
|
|
32
|
-
viewContainer: {
|
|
33
|
-
overflowY: 'auto',
|
|
34
|
-
gridRow: 'components',
|
|
35
|
-
},
|
|
36
|
-
appBar: {
|
|
37
|
-
flexGrow: 1,
|
|
38
|
-
gridRow: 'menubar',
|
|
39
|
-
},
|
|
40
|
-
}))
|
|
41
|
-
|
|
42
|
-
type Props = {
|
|
43
|
-
HeaderButtons?: React.ReactElement
|
|
44
|
-
session: SessionWithDrawerWidgets & {
|
|
45
|
-
savedSessionNames: string[]
|
|
46
|
-
menus: { label: string; menuItems: JBMenuItem[] }[]
|
|
47
|
-
renameCurrentSession: (arg: string) => void
|
|
48
|
-
snackbarMessages: SnackbarMessage[]
|
|
49
|
-
popSnackbarMessage: () => unknown
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const LazyDrawerWidget = observer(function (props: Props) {
|
|
54
|
-
const { session } = props
|
|
55
|
-
return (
|
|
56
|
-
<Suspense fallback={<React.Fragment />}>
|
|
57
|
-
<DrawerWidget session={session} />
|
|
58
|
-
</Suspense>
|
|
59
|
-
)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
const ViewContainer = observer(function (props: Props) {
|
|
63
|
-
const { session } = props
|
|
64
|
-
const { views } = session
|
|
65
|
-
const { classes } = useStyles()
|
|
66
|
-
return (
|
|
67
|
-
<div className={classes.viewContainer}>
|
|
68
|
-
{views.length > 0 ? (
|
|
69
|
-
views.map(view => (
|
|
70
|
-
<ViewPanel key={`view-${view.id}`} view={view} session={session} />
|
|
71
|
-
))
|
|
72
|
-
) : (
|
|
73
|
-
<ViewLauncher {...props} />
|
|
74
|
-
)}
|
|
75
|
-
|
|
76
|
-
{/* blank space at the bottom of screen allows scroll */}
|
|
77
|
-
<div style={{ height: 300 }} />
|
|
78
|
-
</div>
|
|
79
|
-
)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
const App = observer(function (props: Props) {
|
|
83
|
-
const { session } = props
|
|
84
|
-
const { classes } = useStyles()
|
|
85
|
-
const { minimized, visibleWidget, drawerWidth, drawerPosition } = session
|
|
86
|
-
const drawerVisible = visibleWidget && !minimized
|
|
87
|
-
const d = drawerVisible ? `[drawer] ${drawerWidth}px` : undefined
|
|
88
|
-
const grid =
|
|
89
|
-
drawerPosition === 'right' ? ['[main] 1fr', d] : [d, '[main] 1fr']
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<div
|
|
93
|
-
className={classes.root}
|
|
94
|
-
style={{ gridTemplateColumns: grid?.filter(f => !!f).join(' ') }}
|
|
95
|
-
>
|
|
96
|
-
{drawerVisible && drawerPosition === 'left' ? (
|
|
97
|
-
<LazyDrawerWidget session={session} />
|
|
98
|
-
) : null}
|
|
99
|
-
<DialogQueue session={session} />
|
|
100
|
-
<div className={classes.appContainer}>
|
|
101
|
-
<AppBar className={classes.appBar} position="static">
|
|
102
|
-
<AppToolbar {...props} />
|
|
103
|
-
</AppBar>
|
|
104
|
-
<ViewContainer {...props} />
|
|
105
|
-
</div>
|
|
106
|
-
<AppFab session={session} />
|
|
107
|
-
|
|
108
|
-
{drawerVisible && drawerPosition === 'right' ? (
|
|
109
|
-
<LazyDrawerWidget session={session} />
|
|
110
|
-
) : null}
|
|
111
|
-
|
|
112
|
-
<Snackbar session={session} />
|
|
113
|
-
</div>
|
|
114
|
-
)
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
export { App }
|
package/src/ui/App/AppFab.tsx
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { Fab, Tooltip } from '@mui/material'
|
|
3
|
-
import { makeStyles } from 'tss-react/mui'
|
|
4
|
-
import { observer } from 'mobx-react'
|
|
5
|
-
import { SessionWithDrawerWidgets } from '@jbrowse/core/util'
|
|
6
|
-
|
|
7
|
-
// icons
|
|
8
|
-
import LaunchIcon from '@mui/icons-material/Launch'
|
|
9
|
-
|
|
10
|
-
const useStyles = makeStyles()(theme => ({
|
|
11
|
-
left: {
|
|
12
|
-
zIndex: 10000,
|
|
13
|
-
position: 'fixed',
|
|
14
|
-
bottom: theme.spacing(2),
|
|
15
|
-
left: theme.spacing(2),
|
|
16
|
-
},
|
|
17
|
-
right: {
|
|
18
|
-
zIndex: 10000,
|
|
19
|
-
position: 'fixed',
|
|
20
|
-
bottom: theme.spacing(2),
|
|
21
|
-
right: theme.spacing(2),
|
|
22
|
-
},
|
|
23
|
-
}))
|
|
24
|
-
|
|
25
|
-
export default observer(function AppFab({
|
|
26
|
-
session,
|
|
27
|
-
}: {
|
|
28
|
-
session: SessionWithDrawerWidgets
|
|
29
|
-
}) {
|
|
30
|
-
const { minimized, activeWidgets, drawerPosition } = session
|
|
31
|
-
const { classes } = useStyles()
|
|
32
|
-
|
|
33
|
-
return activeWidgets.size > 0 && minimized ? (
|
|
34
|
-
<Tooltip title="Open drawer widget">
|
|
35
|
-
<Fab
|
|
36
|
-
className={drawerPosition === 'right' ? classes.right : classes.left}
|
|
37
|
-
color="primary"
|
|
38
|
-
data-testid="drawer-maximize"
|
|
39
|
-
onClick={() => session.showWidgetDrawer()}
|
|
40
|
-
>
|
|
41
|
-
<LaunchIcon />
|
|
42
|
-
</Fab>
|
|
43
|
-
</Tooltip>
|
|
44
|
-
) : null
|
|
45
|
-
})
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { Toolbar, Tooltip } from '@mui/material'
|
|
3
|
-
import { makeStyles } from 'tss-react/mui'
|
|
4
|
-
import { observer } from 'mobx-react'
|
|
5
|
-
import { SessionWithDrawerWidgets } from '@jbrowse/core/util'
|
|
6
|
-
import DropDownMenu from '@jbrowse/core/ui/DropDownMenu'
|
|
7
|
-
import EditableTypography from '@jbrowse/core/ui/EditableTypography'
|
|
8
|
-
import AppLogo from '@jbrowse/core/ui/AppLogo'
|
|
9
|
-
import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu'
|
|
10
|
-
import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel'
|
|
11
|
-
|
|
12
|
-
const useStyles = makeStyles()(theme => ({
|
|
13
|
-
grow: {
|
|
14
|
-
flexGrow: 1,
|
|
15
|
-
},
|
|
16
|
-
inputBase: {
|
|
17
|
-
color: theme.palette.primary.contrastText,
|
|
18
|
-
},
|
|
19
|
-
inputRoot: {
|
|
20
|
-
'&:hover': {
|
|
21
|
-
backgroundColor: theme.palette.primary.light,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
inputFocused: {
|
|
25
|
-
borderColor: theme.palette.secondary.main,
|
|
26
|
-
backgroundColor: theme.palette.primary.light,
|
|
27
|
-
},
|
|
28
|
-
}))
|
|
29
|
-
|
|
30
|
-
type AppSession = SessionWithDrawerWidgets & {
|
|
31
|
-
savedSessionNames: string[]
|
|
32
|
-
menus: { label: string; menuItems: JBMenuItem[] }[]
|
|
33
|
-
renameCurrentSession: (arg: string) => void
|
|
34
|
-
snackbarMessages: SnackbarMessage[]
|
|
35
|
-
popSnackbarMessage: () => unknown
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const AppToolbar = observer(function ({
|
|
39
|
-
session,
|
|
40
|
-
HeaderButtons = <div />,
|
|
41
|
-
}: {
|
|
42
|
-
HeaderButtons?: React.ReactElement
|
|
43
|
-
session: AppSession
|
|
44
|
-
}) {
|
|
45
|
-
const { classes } = useStyles()
|
|
46
|
-
const { savedSessionNames, name, menus } = session
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<Toolbar>
|
|
50
|
-
{menus.map(menu => (
|
|
51
|
-
<DropDownMenu
|
|
52
|
-
key={menu.label}
|
|
53
|
-
menuTitle={menu.label}
|
|
54
|
-
menuItems={menu.menuItems}
|
|
55
|
-
session={session}
|
|
56
|
-
/>
|
|
57
|
-
))}
|
|
58
|
-
<div className={classes.grow} />
|
|
59
|
-
<Tooltip title="Rename Session" arrow>
|
|
60
|
-
<EditableTypography
|
|
61
|
-
value={name}
|
|
62
|
-
setValue={newName => {
|
|
63
|
-
if (savedSessionNames?.includes(newName)) {
|
|
64
|
-
session.notify(
|
|
65
|
-
`Cannot rename session to "${newName}", a saved session with that name already exists`,
|
|
66
|
-
'warning',
|
|
67
|
-
)
|
|
68
|
-
} else {
|
|
69
|
-
session.renameCurrentSession(newName)
|
|
70
|
-
}
|
|
71
|
-
}}
|
|
72
|
-
variant="body1"
|
|
73
|
-
classes={{
|
|
74
|
-
inputBase: classes.inputBase,
|
|
75
|
-
inputRoot: classes.inputRoot,
|
|
76
|
-
inputFocused: classes.inputFocused,
|
|
77
|
-
}}
|
|
78
|
-
/>
|
|
79
|
-
</Tooltip>
|
|
80
|
-
{HeaderButtons}
|
|
81
|
-
<div className={classes.grow} />
|
|
82
|
-
<div style={{ width: 150, maxHeight: 48 }}>
|
|
83
|
-
<AppLogo session={session} />
|
|
84
|
-
</div>
|
|
85
|
-
</Toolbar>
|
|
86
|
-
)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
export default AppToolbar
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import React, { Suspense } from 'react'
|
|
2
|
-
import { observer } from 'mobx-react'
|
|
3
|
-
|
|
4
|
-
// locals
|
|
5
|
-
import { SessionWithDrawerWidgets } from '@jbrowse/core/util'
|
|
6
|
-
|
|
7
|
-
export default observer(function ({
|
|
8
|
-
session,
|
|
9
|
-
}: {
|
|
10
|
-
session: SessionWithDrawerWidgets
|
|
11
|
-
}) {
|
|
12
|
-
const { DialogComponent, DialogProps } = session
|
|
13
|
-
return (
|
|
14
|
-
<>
|
|
15
|
-
{DialogComponent ? (
|
|
16
|
-
<Suspense fallback={<React.Fragment />}>
|
|
17
|
-
<DialogComponent {...DialogProps} />
|
|
18
|
-
</Suspense>
|
|
19
|
-
) : null}
|
|
20
|
-
</>
|
|
21
|
-
)
|
|
22
|
-
})
|
package/src/ui/App/Drawer.tsx
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { Paper } from '@mui/material'
|
|
3
|
-
import { makeStyles } from 'tss-react/mui'
|
|
4
|
-
import { observer } from 'mobx-react'
|
|
5
|
-
import ResizeHandle from '@jbrowse/core/ui/ResizeHandle'
|
|
6
|
-
import { SessionWithDrawerWidgets } from '@jbrowse/core/util/types'
|
|
7
|
-
|
|
8
|
-
const useStyles = makeStyles()(theme => ({
|
|
9
|
-
paper: {
|
|
10
|
-
overflowY: 'auto',
|
|
11
|
-
height: '100%',
|
|
12
|
-
zIndex: theme.zIndex.drawer,
|
|
13
|
-
outline: 'none',
|
|
14
|
-
background: theme.palette.background.default,
|
|
15
|
-
},
|
|
16
|
-
resizeHandle: {
|
|
17
|
-
width: 4,
|
|
18
|
-
position: 'fixed',
|
|
19
|
-
top: 0,
|
|
20
|
-
zIndex: theme.zIndex.drawer + 1,
|
|
21
|
-
},
|
|
22
|
-
}))
|
|
23
|
-
|
|
24
|
-
function Drawer({
|
|
25
|
-
children,
|
|
26
|
-
session,
|
|
27
|
-
}: {
|
|
28
|
-
children: React.ReactNode
|
|
29
|
-
session: SessionWithDrawerWidgets
|
|
30
|
-
}) {
|
|
31
|
-
const { drawerPosition, drawerWidth } = session
|
|
32
|
-
const { classes } = useStyles()
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<Paper className={classes.paper} elevation={16} square>
|
|
36
|
-
{drawerPosition === 'right' ? (
|
|
37
|
-
<ResizeHandle
|
|
38
|
-
onDrag={session.resizeDrawer}
|
|
39
|
-
className={classes.resizeHandle}
|
|
40
|
-
vertical
|
|
41
|
-
/>
|
|
42
|
-
) : null}
|
|
43
|
-
{children}
|
|
44
|
-
{drawerPosition === 'left' ? (
|
|
45
|
-
<ResizeHandle
|
|
46
|
-
onDrag={session.resizeDrawer}
|
|
47
|
-
className={classes.resizeHandle}
|
|
48
|
-
style={{ left: drawerWidth }}
|
|
49
|
-
vertical
|
|
50
|
-
/>
|
|
51
|
-
) : null}
|
|
52
|
-
</Paper>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export default observer(Drawer)
|
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
import React, { Suspense, useState } from 'react'
|
|
2
|
-
import { ErrorBoundary } from 'react-error-boundary'
|
|
3
|
-
import {
|
|
4
|
-
AppBar,
|
|
5
|
-
FormControl,
|
|
6
|
-
IconButton,
|
|
7
|
-
Menu,
|
|
8
|
-
MenuItem,
|
|
9
|
-
Select,
|
|
10
|
-
Toolbar,
|
|
11
|
-
Tooltip,
|
|
12
|
-
Typography,
|
|
13
|
-
} from '@mui/material'
|
|
14
|
-
import { makeStyles } from 'tss-react/mui'
|
|
15
|
-
import { observer } from 'mobx-react'
|
|
16
|
-
import { getEnv } from '@jbrowse/core/util'
|
|
17
|
-
import LoadingEllipses from '@jbrowse/core/ui/LoadingEllipses'
|
|
18
|
-
import ErrorMessage from '@jbrowse/core/ui/ErrorMessage'
|
|
19
|
-
import { SessionWithDrawerWidgets } from '@jbrowse/core/util/types'
|
|
20
|
-
|
|
21
|
-
// icons
|
|
22
|
-
import DeleteIcon from '@mui/icons-material/Delete'
|
|
23
|
-
import CloseIcon from '@mui/icons-material/Close'
|
|
24
|
-
import MinimizeIcon from '@mui/icons-material/Minimize'
|
|
25
|
-
import MoreVertIcon from '@mui/icons-material/MoreVert'
|
|
26
|
-
|
|
27
|
-
// locals
|
|
28
|
-
import Drawer from './Drawer'
|
|
29
|
-
|
|
30
|
-
const useStyles = makeStyles()(theme => ({
|
|
31
|
-
formControl: {
|
|
32
|
-
margin: 0,
|
|
33
|
-
},
|
|
34
|
-
spacer: {
|
|
35
|
-
flexGrow: 1,
|
|
36
|
-
},
|
|
37
|
-
drawerSelect: {
|
|
38
|
-
margin: 0,
|
|
39
|
-
color: theme.palette.secondary.contrastText,
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
dropDownIcon: {
|
|
43
|
-
color: theme.palette.secondary.contrastText,
|
|
44
|
-
},
|
|
45
|
-
header: {
|
|
46
|
-
background: theme.palette.secondary.main,
|
|
47
|
-
},
|
|
48
|
-
}))
|
|
49
|
-
|
|
50
|
-
const DrawerHeader = observer(function ({
|
|
51
|
-
session,
|
|
52
|
-
setToolbarHeight,
|
|
53
|
-
}: {
|
|
54
|
-
session: SessionWithDrawerWidgets
|
|
55
|
-
setToolbarHeight: (arg: number) => void
|
|
56
|
-
}) {
|
|
57
|
-
const { pluginManager } = getEnv(session)
|
|
58
|
-
const { visibleWidget, activeWidgets, drawerPosition } = session
|
|
59
|
-
const { classes } = useStyles()
|
|
60
|
-
|
|
61
|
-
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
|
|
62
|
-
|
|
63
|
-
return (
|
|
64
|
-
<AppBar
|
|
65
|
-
position="sticky"
|
|
66
|
-
className={classes.header}
|
|
67
|
-
ref={ref => setToolbarHeight(ref?.getBoundingClientRect().height || 0)}
|
|
68
|
-
>
|
|
69
|
-
<Toolbar disableGutters>
|
|
70
|
-
<FormControl className={classes.formControl}>
|
|
71
|
-
<Select
|
|
72
|
-
value={visibleWidget?.id}
|
|
73
|
-
data-testid="widget-drawer-selects"
|
|
74
|
-
className={classes.drawerSelect}
|
|
75
|
-
classes={{ icon: classes.dropDownIcon }}
|
|
76
|
-
renderValue={widgetId => {
|
|
77
|
-
const widget = session.activeWidgets.get(widgetId)
|
|
78
|
-
if (!widget) {
|
|
79
|
-
return (
|
|
80
|
-
<Typography variant="h6" color="inherit">
|
|
81
|
-
Unknown widget
|
|
82
|
-
</Typography>
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
const widgetType = pluginManager.getWidgetType(widget.type)
|
|
86
|
-
const { HeadingComponent, heading } = widgetType
|
|
87
|
-
return HeadingComponent ? (
|
|
88
|
-
<HeadingComponent model={widget} />
|
|
89
|
-
) : (
|
|
90
|
-
<Typography variant="h6" color="inherit">
|
|
91
|
-
{heading}
|
|
92
|
-
</Typography>
|
|
93
|
-
)
|
|
94
|
-
}}
|
|
95
|
-
onChange={e => {
|
|
96
|
-
const w = session.activeWidgets.get(e.target.value)
|
|
97
|
-
if (w) {
|
|
98
|
-
session.showWidget(w)
|
|
99
|
-
} else {
|
|
100
|
-
session.notify(`Widget not found ${e.target.value}`, 'warning')
|
|
101
|
-
}
|
|
102
|
-
}}
|
|
103
|
-
>
|
|
104
|
-
{[...activeWidgets.values()].map(widget => {
|
|
105
|
-
const widgetType = pluginManager.getWidgetType(widget.type)
|
|
106
|
-
const { HeadingComponent, heading } = widgetType
|
|
107
|
-
return (
|
|
108
|
-
<MenuItem
|
|
109
|
-
data-testid={`widget-drawer-selects-item-${widget.type}`}
|
|
110
|
-
key={widget.id}
|
|
111
|
-
value={widget.id}
|
|
112
|
-
>
|
|
113
|
-
{HeadingComponent ? (
|
|
114
|
-
<HeadingComponent model={widget} />
|
|
115
|
-
) : (
|
|
116
|
-
<Typography variant="h6" color="inherit">
|
|
117
|
-
{heading}
|
|
118
|
-
</Typography>
|
|
119
|
-
)}
|
|
120
|
-
<IconButton
|
|
121
|
-
data-testid={`${widget.type}-drawer-delete`}
|
|
122
|
-
color="inherit"
|
|
123
|
-
aria-label="Delete"
|
|
124
|
-
onClick={() => session.hideWidget(widget)}
|
|
125
|
-
>
|
|
126
|
-
<DeleteIcon />
|
|
127
|
-
</IconButton>
|
|
128
|
-
</MenuItem>
|
|
129
|
-
)
|
|
130
|
-
})}
|
|
131
|
-
</Select>
|
|
132
|
-
</FormControl>
|
|
133
|
-
<div className={classes.spacer} />
|
|
134
|
-
<div>
|
|
135
|
-
<IconButton
|
|
136
|
-
data-testid="drawer-close"
|
|
137
|
-
color="inherit"
|
|
138
|
-
onClick={event => setAnchorEl(event.currentTarget)}
|
|
139
|
-
>
|
|
140
|
-
<MoreVertIcon />
|
|
141
|
-
</IconButton>
|
|
142
|
-
<Tooltip title="Minimize drawer">
|
|
143
|
-
<IconButton
|
|
144
|
-
data-testid="drawer-minimize"
|
|
145
|
-
color="inherit"
|
|
146
|
-
onClick={() => {
|
|
147
|
-
session.notify(
|
|
148
|
-
`Drawer minimized, click button on ${drawerPosition} side of screen to re-open`,
|
|
149
|
-
'info',
|
|
150
|
-
)
|
|
151
|
-
session.minimizeWidgetDrawer()
|
|
152
|
-
}}
|
|
153
|
-
>
|
|
154
|
-
<MinimizeIcon />
|
|
155
|
-
</IconButton>
|
|
156
|
-
</Tooltip>
|
|
157
|
-
<Tooltip title="Close drawer">
|
|
158
|
-
<IconButton
|
|
159
|
-
data-testid="drawer-close"
|
|
160
|
-
color="inherit"
|
|
161
|
-
onClick={() => session.hideWidget(visibleWidget)}
|
|
162
|
-
>
|
|
163
|
-
<CloseIcon />
|
|
164
|
-
</IconButton>
|
|
165
|
-
</Tooltip>
|
|
166
|
-
</div>
|
|
167
|
-
</Toolbar>
|
|
168
|
-
<Menu
|
|
169
|
-
anchorEl={anchorEl}
|
|
170
|
-
open={Boolean(anchorEl)}
|
|
171
|
-
onClose={() => setAnchorEl(null)}
|
|
172
|
-
>
|
|
173
|
-
{['left', 'right'].map(option => (
|
|
174
|
-
<MenuItem
|
|
175
|
-
key={option}
|
|
176
|
-
selected={drawerPosition === 'option'}
|
|
177
|
-
onClick={() => {
|
|
178
|
-
session.setDrawerPosition(option)
|
|
179
|
-
setAnchorEl(null)
|
|
180
|
-
}}
|
|
181
|
-
>
|
|
182
|
-
{option}
|
|
183
|
-
</MenuItem>
|
|
184
|
-
))}
|
|
185
|
-
</Menu>
|
|
186
|
-
</AppBar>
|
|
187
|
-
)
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
const DrawerWidget = observer(function ({
|
|
191
|
-
session,
|
|
192
|
-
}: {
|
|
193
|
-
session: SessionWithDrawerWidgets
|
|
194
|
-
}) {
|
|
195
|
-
const { visibleWidget } = session
|
|
196
|
-
const { pluginManager } = getEnv(session)
|
|
197
|
-
|
|
198
|
-
const DrawerComponent = visibleWidget
|
|
199
|
-
? (pluginManager.evaluateExtensionPoint(
|
|
200
|
-
'Core-replaceWidget',
|
|
201
|
-
pluginManager.getWidgetType(visibleWidget.type).ReactComponent,
|
|
202
|
-
{
|
|
203
|
-
session,
|
|
204
|
-
model: visibleWidget,
|
|
205
|
-
},
|
|
206
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
207
|
-
) as React.FC<any>)
|
|
208
|
-
: null
|
|
209
|
-
|
|
210
|
-
// we track the toolbar height because components that use virtualized
|
|
211
|
-
// height want to be able to fill the contained, minus the toolbar height
|
|
212
|
-
// (the position static/sticky is included in AutoSizer estimates)
|
|
213
|
-
const [toolbarHeight, setToolbarHeight] = useState(0)
|
|
214
|
-
|
|
215
|
-
return (
|
|
216
|
-
<Drawer session={session}>
|
|
217
|
-
<DrawerHeader session={session} setToolbarHeight={setToolbarHeight} />
|
|
218
|
-
<Suspense fallback={<LoadingEllipses />}>
|
|
219
|
-
<ErrorBoundary
|
|
220
|
-
FallbackComponent={({ error }) => <ErrorMessage error={error} />}
|
|
221
|
-
>
|
|
222
|
-
{DrawerComponent ? (
|
|
223
|
-
<>
|
|
224
|
-
<DrawerComponent
|
|
225
|
-
model={visibleWidget}
|
|
226
|
-
session={session}
|
|
227
|
-
toolbarHeight={toolbarHeight}
|
|
228
|
-
/>
|
|
229
|
-
<div style={{ height: 300 }} />
|
|
230
|
-
</>
|
|
231
|
-
) : null}
|
|
232
|
-
</ErrorBoundary>
|
|
233
|
-
</Suspense>
|
|
234
|
-
</Drawer>
|
|
235
|
-
)
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
export default DrawerWidget
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useRef } from 'react'
|
|
2
|
-
import { IconButton, Paper, useTheme } from '@mui/material'
|
|
3
|
-
import { makeStyles } from 'tss-react/mui'
|
|
4
|
-
import { observer } from 'mobx-react'
|
|
5
|
-
import { useWidthSetter } from '@jbrowse/core/util'
|
|
6
|
-
import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes/models'
|
|
7
|
-
|
|
8
|
-
// icons
|
|
9
|
-
import CloseIcon from '@mui/icons-material/Close'
|
|
10
|
-
import MinimizeIcon from '@mui/icons-material/Minimize'
|
|
11
|
-
import AddIcon from '@mui/icons-material/Add'
|
|
12
|
-
|
|
13
|
-
// locals
|
|
14
|
-
import ViewMenu from './ViewMenu'
|
|
15
|
-
import ViewContainerTitle from './ViewContainerTitle'
|
|
16
|
-
|
|
17
|
-
const useStyles = makeStyles()(theme => ({
|
|
18
|
-
viewContainer: {
|
|
19
|
-
overflow: 'hidden',
|
|
20
|
-
background: theme.palette.secondary.main,
|
|
21
|
-
margin: theme.spacing(0.5),
|
|
22
|
-
padding: `0 ${theme.spacing(1)} ${theme.spacing(1)}`,
|
|
23
|
-
},
|
|
24
|
-
icon: {
|
|
25
|
-
color: theme.palette.secondary.contrastText,
|
|
26
|
-
},
|
|
27
|
-
grow: {
|
|
28
|
-
flexGrow: 1,
|
|
29
|
-
},
|
|
30
|
-
}))
|
|
31
|
-
|
|
32
|
-
export default observer(function ({
|
|
33
|
-
view,
|
|
34
|
-
onClose,
|
|
35
|
-
onMinimize,
|
|
36
|
-
children,
|
|
37
|
-
}: {
|
|
38
|
-
view: IBaseViewModel
|
|
39
|
-
onClose: () => void
|
|
40
|
-
onMinimize: () => void
|
|
41
|
-
children: React.ReactNode
|
|
42
|
-
}) {
|
|
43
|
-
const { classes } = useStyles()
|
|
44
|
-
const theme = useTheme()
|
|
45
|
-
const ref = useWidthSetter(view, theme.spacing(1))
|
|
46
|
-
const scrollRef = useRef<HTMLDivElement>(null)
|
|
47
|
-
|
|
48
|
-
// scroll the view into view when first mounted. note: this effect will run
|
|
49
|
-
// only once, because of the empty array second param
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
scrollRef.current?.scrollIntoView?.({ block: 'center' })
|
|
52
|
-
}, [])
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<Paper ref={ref} elevation={12} className={classes.viewContainer}>
|
|
56
|
-
<div ref={scrollRef} style={{ display: 'flex' }}>
|
|
57
|
-
<ViewMenu model={view} IconProps={{ className: classes.icon }} />
|
|
58
|
-
<div className={classes.grow} />
|
|
59
|
-
|
|
60
|
-
<ViewContainerTitle view={view} />
|
|
61
|
-
<div className={classes.grow} />
|
|
62
|
-
<IconButton data-testid="minimize_view" onClick={onMinimize}>
|
|
63
|
-
{view.minimized ? (
|
|
64
|
-
<AddIcon className={classes.icon} fontSize="small" />
|
|
65
|
-
) : (
|
|
66
|
-
<MinimizeIcon className={classes.icon} fontSize="small" />
|
|
67
|
-
)}
|
|
68
|
-
</IconButton>
|
|
69
|
-
<IconButton data-testid="close_view" onClick={onClose}>
|
|
70
|
-
<CloseIcon className={classes.icon} fontSize="small" />
|
|
71
|
-
</IconButton>
|
|
72
|
-
</div>
|
|
73
|
-
<Paper>{children}</Paper>
|
|
74
|
-
</Paper>
|
|
75
|
-
)
|
|
76
|
-
})
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { Tooltip } from '@mui/material'
|
|
3
|
-
import { makeStyles } from 'tss-react/mui'
|
|
4
|
-
import { observer } from 'mobx-react'
|
|
5
|
-
|
|
6
|
-
// locals
|
|
7
|
-
import EditableTypography from '@jbrowse/core/ui/EditableTypography'
|
|
8
|
-
import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes'
|
|
9
|
-
|
|
10
|
-
const useStyles = makeStyles()(theme => ({
|
|
11
|
-
input: {
|
|
12
|
-
paddingBottom: 0,
|
|
13
|
-
paddingTop: 2,
|
|
14
|
-
},
|
|
15
|
-
inputBase: {
|
|
16
|
-
color: theme.palette.secondary.contrastText,
|
|
17
|
-
},
|
|
18
|
-
inputRoot: {
|
|
19
|
-
'&:hover': {
|
|
20
|
-
backgroundColor: theme.palette.secondary.light,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
inputFocused: {
|
|
24
|
-
borderColor: theme.palette.primary.main,
|
|
25
|
-
backgroundColor: theme.palette.secondary.light,
|
|
26
|
-
},
|
|
27
|
-
}))
|
|
28
|
-
export default observer(function ViewContainerTitle({
|
|
29
|
-
view,
|
|
30
|
-
}: {
|
|
31
|
-
view: IBaseViewModel
|
|
32
|
-
}) {
|
|
33
|
-
const { classes } = useStyles()
|
|
34
|
-
return (
|
|
35
|
-
<Tooltip title="Rename view" arrow>
|
|
36
|
-
<EditableTypography
|
|
37
|
-
value={
|
|
38
|
-
view.displayName ||
|
|
39
|
-
// @ts-expect-error
|
|
40
|
-
`${view.assemblyNames?.join(',') || 'Untitled view'}${
|
|
41
|
-
view.minimized ? ' (minimized)' : ''
|
|
42
|
-
}`
|
|
43
|
-
}
|
|
44
|
-
setValue={val => view.setDisplayName(val)}
|
|
45
|
-
variant="body2"
|
|
46
|
-
classes={{
|
|
47
|
-
input: classes.input,
|
|
48
|
-
inputBase: classes.inputBase,
|
|
49
|
-
inputRoot: classes.inputRoot,
|
|
50
|
-
inputFocused: classes.inputFocused,
|
|
51
|
-
}}
|
|
52
|
-
/>
|
|
53
|
-
</Tooltip>
|
|
54
|
-
)
|
|
55
|
-
})
|