@jbrowse/plugin-linear-genome-view 2.2.0 → 2.2.1
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/dist/BaseLinearDisplay/components/Tooltip.d.ts +1 -1
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +3 -3
- package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -2
- package/dist/BasicTrack/index.d.ts +1 -1
- package/dist/BasicTrack/index.js +4 -4
- package/dist/BasicTrack/index.js.map +1 -1
- package/dist/LinearBasicDisplay/model.d.ts +2 -2
- package/dist/LinearGenomeView/components/CenterLine.d.ts +1 -1
- package/dist/LinearGenomeView/components/GetSequenceDialog.d.ts +1 -1
- package/dist/LinearGenomeView/components/Gridlines.d.ts +1 -1
- package/dist/LinearGenomeView/components/Header.d.ts +1 -1
- package/dist/LinearGenomeView/components/ImportForm.d.ts +1 -1
- package/dist/LinearGenomeView/components/ImportForm.js +8 -7
- package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.d.ts +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.js +1 -3
- package/dist/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +1 -1
- package/dist/LinearGenomeView/components/OverviewRubberBand.d.ts +1 -1
- package/dist/LinearGenomeView/components/OverviewScaleBar.d.ts +1 -1
- package/dist/LinearGenomeView/components/RubberBand.d.ts +1 -1
- package/dist/LinearGenomeView/components/ScaleBar.d.ts +1 -1
- package/dist/LinearGenomeView/components/TrackContainer.d.ts +1 -1
- package/dist/LinearGenomeView/components/TrackContainer.js +12 -9
- package/dist/LinearGenomeView/components/TrackContainer.js.map +1 -1
- package/dist/LinearGenomeView/components/TrackLabel.js +9 -1
- package/dist/LinearGenomeView/components/TrackLabel.js.map +1 -1
- package/dist/LinearGenomeView/components/TracksContainer.d.ts +1 -1
- package/dist/LinearGenomeView/index.d.ts +84 -3
- package/dist/LinearGenomeView/index.js +143 -63
- package/dist/LinearGenomeView/index.js.map +1 -1
- package/dist/index.d.ts +18 -6
- package/esm/BaseLinearDisplay/components/Tooltip.d.ts +1 -1
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +3 -3
- package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -2
- package/esm/BasicTrack/index.d.ts +1 -1
- package/esm/BasicTrack/index.js +4 -4
- package/esm/BasicTrack/index.js.map +1 -1
- package/esm/LinearBasicDisplay/model.d.ts +2 -2
- package/esm/LinearGenomeView/components/CenterLine.d.ts +1 -1
- package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +1 -1
- package/esm/LinearGenomeView/components/Gridlines.d.ts +1 -1
- package/esm/LinearGenomeView/components/Header.d.ts +1 -1
- package/esm/LinearGenomeView/components/ImportForm.d.ts +1 -1
- package/esm/LinearGenomeView/components/ImportForm.js +8 -7
- package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.js +2 -4
- package/esm/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +1 -1
- package/esm/LinearGenomeView/components/OverviewRubberBand.d.ts +1 -1
- package/esm/LinearGenomeView/components/OverviewScaleBar.d.ts +1 -1
- package/esm/LinearGenomeView/components/RubberBand.d.ts +1 -1
- package/esm/LinearGenomeView/components/ScaleBar.d.ts +1 -1
- package/esm/LinearGenomeView/components/TrackContainer.d.ts +1 -1
- package/esm/LinearGenomeView/components/TrackContainer.js +13 -10
- package/esm/LinearGenomeView/components/TrackContainer.js.map +1 -1
- package/esm/LinearGenomeView/components/TrackLabel.js +9 -1
- package/esm/LinearGenomeView/components/TrackLabel.js.map +1 -1
- package/esm/LinearGenomeView/components/TracksContainer.d.ts +1 -1
- package/esm/LinearGenomeView/index.d.ts +84 -3
- package/esm/LinearGenomeView/index.js +143 -63
- package/esm/LinearGenomeView/index.js.map +1 -1
- package/esm/index.d.ts +18 -6
- package/package.json +2 -2
- package/src/BasicTrack/index.ts +4 -8
- package/src/LinearGenomeView/components/ImportForm.tsx +9 -7
- package/src/LinearGenomeView/components/LinearGenomeView.tsx +2 -8
- package/src/LinearGenomeView/components/TrackContainer.tsx +38 -27
- package/src/LinearGenomeView/components/TrackLabel.tsx +10 -1
- package/src/LinearGenomeView/index.tsx +154 -73
package/src/BasicTrack/index.ts
CHANGED
|
@@ -5,18 +5,14 @@ import {
|
|
|
5
5
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
6
6
|
import configSchemaF from './configSchema'
|
|
7
7
|
|
|
8
|
-
export default (
|
|
9
|
-
|
|
10
|
-
const configSchema = configSchemaF(
|
|
8
|
+
export default (pm: PluginManager) => {
|
|
9
|
+
pm.addTrackType(() => {
|
|
10
|
+
const configSchema = configSchemaF(pm)
|
|
11
11
|
|
|
12
12
|
return new TrackType({
|
|
13
13
|
name: 'BasicTrack',
|
|
14
14
|
configSchema,
|
|
15
|
-
stateModel: createBaseTrackModel(
|
|
16
|
-
pluginManager,
|
|
17
|
-
'BasicTrack',
|
|
18
|
-
configSchema,
|
|
19
|
-
),
|
|
15
|
+
stateModel: createBaseTrackModel(pm, 'BasicTrack', configSchema),
|
|
20
16
|
})
|
|
21
17
|
})
|
|
22
18
|
}
|
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
} from '@mui/material'
|
|
12
12
|
import { ErrorMessage, AssemblySelector } from '@jbrowse/core/ui'
|
|
13
13
|
import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
|
|
14
|
+
|
|
15
|
+
// icons
|
|
14
16
|
import CloseIcon from '@mui/icons-material/Close'
|
|
15
17
|
|
|
16
18
|
// locals
|
|
@@ -39,7 +41,6 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
39
41
|
const { assemblyNames, assemblyManager, textSearchManager } = session
|
|
40
42
|
const { rankSearchResults, isSearchDialogDisplayed, error } = model
|
|
41
43
|
const [selectedAsm, setSelectedAsm] = useState(assemblyNames[0])
|
|
42
|
-
const [importError, setImportError] = useState(error)
|
|
43
44
|
const [option, setOption] = useState<BaseResult>()
|
|
44
45
|
|
|
45
46
|
const searchScope = model.searchScope(selectedAsm)
|
|
@@ -49,15 +50,17 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
49
50
|
? assembly?.error
|
|
50
51
|
: 'No configured assemblies'
|
|
51
52
|
const regions = assembly?.regions || []
|
|
52
|
-
const
|
|
53
|
+
const displayError = assemblyError || error
|
|
53
54
|
const [value, setValue] = useState('')
|
|
54
55
|
const r0 = regions[0]?.refName
|
|
55
56
|
|
|
56
57
|
// useEffect resets to an "initial state" of displaying first region from assembly
|
|
57
|
-
// after assembly change
|
|
58
|
+
// after assembly change. needs to react to selectedAsm as well as r0 because changing
|
|
59
|
+
// assembly will run setValue('') and then r0 may not change if assembly names are the
|
|
60
|
+
// same across assemblies, but it still needs to be reset
|
|
58
61
|
useEffect(() => {
|
|
59
62
|
setValue(r0)
|
|
60
|
-
}, [r0])
|
|
63
|
+
}, [r0, selectedAsm])
|
|
61
64
|
|
|
62
65
|
function navToOption(option: BaseResult) {
|
|
63
66
|
const location = option.getLocation()
|
|
@@ -116,7 +119,7 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
116
119
|
// having this wrapped in a form allows intuitive use of enter key to submit
|
|
117
120
|
return (
|
|
118
121
|
<div className={classes.container}>
|
|
119
|
-
{
|
|
122
|
+
{displayError ? <ErrorMessage error={displayError} /> : null}
|
|
120
123
|
<Container className={classes.importFormContainer}>
|
|
121
124
|
<form
|
|
122
125
|
onSubmit={event => {
|
|
@@ -137,7 +140,6 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
137
140
|
<FormControl>
|
|
138
141
|
<AssemblySelector
|
|
139
142
|
onChange={val => {
|
|
140
|
-
setImportError('')
|
|
141
143
|
setSelectedAsm(val)
|
|
142
144
|
setValue('')
|
|
143
145
|
}}
|
|
@@ -148,7 +150,7 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
148
150
|
</Grid>
|
|
149
151
|
<Grid item>
|
|
150
152
|
{selectedAsm ? (
|
|
151
|
-
|
|
153
|
+
assemblyError ? (
|
|
152
154
|
<CloseIcon style={{ color: 'red' }} />
|
|
153
155
|
) : value ? (
|
|
154
156
|
<FormControl>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { Button, Paper, Typography } from '@mui/material'
|
|
3
3
|
import { makeStyles } from 'tss-react/mui'
|
|
4
|
-
import { ErrorBoundary } from 'react-error-boundary'
|
|
5
4
|
import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons'
|
|
6
|
-
import { LoadingEllipses
|
|
5
|
+
import { LoadingEllipses } from '@jbrowse/core/ui'
|
|
7
6
|
import { observer } from 'mobx-react'
|
|
8
7
|
|
|
9
8
|
// locals
|
|
@@ -76,12 +75,7 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
|
|
|
76
75
|
</Paper>
|
|
77
76
|
) : (
|
|
78
77
|
tracks.map(track => (
|
|
79
|
-
<
|
|
80
|
-
key={track.id}
|
|
81
|
-
FallbackComponent={({ error }) => <ErrorMessage error={error} />}
|
|
82
|
-
>
|
|
83
|
-
<TrackContainer model={model} track={track} />
|
|
84
|
-
</ErrorBoundary>
|
|
78
|
+
<TrackContainer key={track.id} model={model} track={track} />
|
|
85
79
|
))
|
|
86
80
|
)}
|
|
87
81
|
</TracksContainer>
|
|
@@ -5,7 +5,8 @@ import { observer } from 'mobx-react'
|
|
|
5
5
|
import { isAlive } from 'mobx-state-tree'
|
|
6
6
|
import { BaseTrackModel } from '@jbrowse/core/pluggableElementTypes/models'
|
|
7
7
|
import { getConf } from '@jbrowse/core/configuration'
|
|
8
|
-
import { ResizeHandle } from '@jbrowse/core/ui'
|
|
8
|
+
import { ResizeHandle, ErrorMessage } from '@jbrowse/core/ui'
|
|
9
|
+
import { ErrorBoundary } from 'react-error-boundary'
|
|
9
10
|
import { useDebouncedCallback } from '@jbrowse/core/util'
|
|
10
11
|
|
|
11
12
|
// locals
|
|
@@ -92,6 +93,7 @@ function TrackContainer({
|
|
|
92
93
|
const trackId = getConf(track, 'trackId')
|
|
93
94
|
const ref = useRef(null)
|
|
94
95
|
const dimmed = draggingTrackId !== undefined && draggingTrackId !== display.id
|
|
96
|
+
const minimized = track.minimized
|
|
95
97
|
const debouncedOnDragEnter = useDebouncedCallback(() => {
|
|
96
98
|
if (isAlive(display) && dimmed) {
|
|
97
99
|
moveTrack(draggingTrackId, track.id)
|
|
@@ -109,36 +111,45 @@ function TrackContainer({
|
|
|
109
111
|
return (
|
|
110
112
|
<Paper className={classes.root} variant="outlined">
|
|
111
113
|
<TrackContainerLabel model={track} view={model} />
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
onScroll={event => display.setScrollTop(event.currentTarget.scrollTop)}
|
|
116
|
-
onDragEnter={debouncedOnDragEnter}
|
|
117
|
-
data-testid={`trackRenderingContainer-${model.id}-${trackId}`}
|
|
114
|
+
<ErrorBoundary
|
|
115
|
+
key={track.id}
|
|
116
|
+
FallbackComponent={({ error }) => <ErrorMessage error={error} />}
|
|
118
117
|
>
|
|
119
118
|
<div
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
className={classes.trackRenderingContainer}
|
|
120
|
+
style={{ height: minimized ? 20 : height }}
|
|
121
|
+
onScroll={evt => display.setScrollTop(evt.currentTarget.scrollTop)}
|
|
122
|
+
onDragEnter={debouncedOnDragEnter}
|
|
123
|
+
data-testid={`trackRenderingContainer-${model.id}-${trackId}`}
|
|
123
124
|
>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
{!minimized ? (
|
|
126
|
+
<>
|
|
127
|
+
<div
|
|
128
|
+
ref={ref}
|
|
129
|
+
className={classes.renderingComponentContainer}
|
|
130
|
+
style={{ transform: `scaleX(${model.scaleFactor})` }}
|
|
131
|
+
>
|
|
132
|
+
<RenderingComponent
|
|
133
|
+
model={display}
|
|
134
|
+
onHorizontalScroll={horizontalScroll}
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
129
137
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
{DisplayBlurb ? (
|
|
139
|
+
<div
|
|
140
|
+
style={{
|
|
141
|
+
position: 'absolute',
|
|
142
|
+
left: 0,
|
|
143
|
+
top: display.height - 20,
|
|
144
|
+
}}
|
|
145
|
+
>
|
|
146
|
+
<DisplayBlurb model={display} />
|
|
147
|
+
</div>
|
|
148
|
+
) : null}
|
|
149
|
+
</>
|
|
150
|
+
) : null}
|
|
151
|
+
</div>
|
|
152
|
+
</ErrorBoundary>
|
|
142
153
|
<div
|
|
143
154
|
className={classes.overlay}
|
|
144
155
|
style={{
|
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
import MoreVertIcon from '@mui/icons-material/MoreVert'
|
|
19
19
|
import DragIcon from '@mui/icons-material/DragIndicator'
|
|
20
20
|
import CloseIcon from '@mui/icons-material/Close'
|
|
21
|
+
import MinimizeIcon from '@mui/icons-material/Minimize'
|
|
22
|
+
import AddIcon from '@mui/icons-material/Add'
|
|
21
23
|
|
|
22
24
|
import { LinearGenomeViewModel } from '..'
|
|
23
25
|
|
|
@@ -64,6 +66,7 @@ const TrackLabel = React.forwardRef<HTMLDivElement, Props>(
|
|
|
64
66
|
const view = getContainingView(track) as LGV
|
|
65
67
|
const session = getSession(track)
|
|
66
68
|
const trackConf = track.configuration
|
|
69
|
+
const minimized = track.minimized
|
|
67
70
|
const trackId = getConf(track, 'trackId')
|
|
68
71
|
const trackName = getTrackName(trackConf, session)
|
|
69
72
|
|
|
@@ -73,6 +76,11 @@ const TrackLabel = React.forwardRef<HTMLDivElement, Props>(
|
|
|
73
76
|
})
|
|
74
77
|
|
|
75
78
|
const items = [
|
|
79
|
+
{
|
|
80
|
+
label: minimized ? 'Restore track' : 'Minimize track',
|
|
81
|
+
icon: minimized ? AddIcon : MinimizeIcon,
|
|
82
|
+
onClick: () => track.setMinimized(!minimized),
|
|
83
|
+
},
|
|
76
84
|
...(session.getTrackActionMenuItems?.(trackConf) || []),
|
|
77
85
|
...track.trackMenuItems(),
|
|
78
86
|
].sort((a, b) => (b.priority || 0) - (a.priority || 0))
|
|
@@ -103,12 +111,13 @@ const TrackLabel = React.forwardRef<HTMLDivElement, Props>(
|
|
|
103
111
|
>
|
|
104
112
|
<CloseIcon fontSize="small" />
|
|
105
113
|
</IconButton>
|
|
114
|
+
|
|
106
115
|
<Typography
|
|
107
116
|
variant="body1"
|
|
108
117
|
component="span"
|
|
109
118
|
className={classes.trackName}
|
|
110
119
|
>
|
|
111
|
-
{trackName}
|
|
120
|
+
{trackName + (minimized ? ' (minimized)' : '')}
|
|
112
121
|
</Typography>
|
|
113
122
|
<IconButton
|
|
114
123
|
{...bindTrigger(popupState)}
|
|
@@ -59,6 +59,7 @@ import Header from './components/Header'
|
|
|
59
59
|
import ZoomControls from './components/ZoomControls'
|
|
60
60
|
import LinearGenomeView from './components/LinearGenomeView'
|
|
61
61
|
|
|
62
|
+
// lazies
|
|
62
63
|
const SequenceSearchDialog = lazy(
|
|
63
64
|
() => import('./components/SequenceSearchDialog'),
|
|
64
65
|
)
|
|
@@ -136,8 +137,11 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
136
137
|
|
|
137
138
|
/**
|
|
138
139
|
* #property
|
|
140
|
+
* this is a string instead of the const literal 'LinearGenomeView' to reduce some
|
|
141
|
+
* typescripting strictness, but you should pass the string 'LinearGenomeView' to
|
|
142
|
+
* the model explicitly
|
|
139
143
|
*/
|
|
140
|
-
type: types.literal('LinearGenomeView'),
|
|
144
|
+
type: types.literal('LinearGenomeView') as unknown as string,
|
|
141
145
|
|
|
142
146
|
/**
|
|
143
147
|
* #property
|
|
@@ -274,16 +278,25 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
274
278
|
},
|
|
275
279
|
}))
|
|
276
280
|
.views(self => ({
|
|
281
|
+
/**
|
|
282
|
+
* #method
|
|
283
|
+
*/
|
|
277
284
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
278
285
|
MiniControlsComponent(): React.FC<any> {
|
|
279
286
|
return MiniControls
|
|
280
287
|
},
|
|
281
288
|
|
|
289
|
+
/**
|
|
290
|
+
* #method
|
|
291
|
+
*/
|
|
282
292
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
283
293
|
HeaderComponent(): React.FC<any> {
|
|
284
294
|
return Header
|
|
285
295
|
},
|
|
286
296
|
|
|
297
|
+
/**
|
|
298
|
+
* #getter
|
|
299
|
+
*/
|
|
287
300
|
get assemblyErrors() {
|
|
288
301
|
const { assemblyManager } = getSession(self)
|
|
289
302
|
const { assemblyNames } = self
|
|
@@ -293,23 +306,46 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
293
306
|
.join(', ')
|
|
294
307
|
},
|
|
295
308
|
|
|
309
|
+
/**
|
|
310
|
+
* #getter
|
|
311
|
+
*/
|
|
296
312
|
get assembliesInitialized() {
|
|
297
313
|
const { assemblyManager } = getSession(self)
|
|
298
314
|
const { assemblyNames } = self
|
|
299
315
|
return assemblyNames.every(a => assemblyManager.get(a)?.initialized)
|
|
300
316
|
},
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* #getter
|
|
320
|
+
*/
|
|
301
321
|
get initialized() {
|
|
302
322
|
return self.volatileWidth !== undefined && this.assembliesInitialized
|
|
303
323
|
},
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* #getter
|
|
327
|
+
*/
|
|
304
328
|
get hasDisplayedRegions() {
|
|
305
329
|
return self.displayedRegions.length > 0
|
|
306
330
|
},
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* #getter
|
|
334
|
+
*/
|
|
307
335
|
get isSearchDialogDisplayed() {
|
|
308
336
|
return self.searchResults !== undefined
|
|
309
337
|
},
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* #getter
|
|
341
|
+
*/
|
|
310
342
|
get scaleBarHeight() {
|
|
311
343
|
return SCALE_BAR_HEIGHT + RESIZE_HANDLE_HEIGHT
|
|
312
344
|
},
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* #getter
|
|
348
|
+
*/
|
|
313
349
|
get headerHeight() {
|
|
314
350
|
if (self.hideHeader) {
|
|
315
351
|
return 0
|
|
@@ -319,15 +355,26 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
319
355
|
}
|
|
320
356
|
return HEADER_BAR_HEIGHT + HEADER_OVERVIEW_HEIGHT
|
|
321
357
|
},
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* #getter
|
|
361
|
+
*/
|
|
322
362
|
get trackHeights() {
|
|
323
363
|
return self.tracks
|
|
324
364
|
.map(t => t.displays[0].height)
|
|
325
365
|
.reduce((a, b) => a + b, 0)
|
|
326
366
|
},
|
|
327
367
|
|
|
368
|
+
/**
|
|
369
|
+
* #getter
|
|
370
|
+
*/
|
|
328
371
|
get trackHeightsWithResizeHandles() {
|
|
329
372
|
return this.trackHeights + self.tracks.length * RESIZE_HANDLE_HEIGHT
|
|
330
373
|
},
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* #getter
|
|
377
|
+
*/
|
|
331
378
|
get height() {
|
|
332
379
|
return (
|
|
333
380
|
this.trackHeightsWithResizeHandles +
|
|
@@ -335,38 +382,63 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
335
382
|
this.scaleBarHeight
|
|
336
383
|
)
|
|
337
384
|
},
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* #getter
|
|
388
|
+
*/
|
|
338
389
|
get totalBp() {
|
|
339
390
|
return self.displayedRegions.reduce((a, b) => a + b.end - b.start, 0)
|
|
340
391
|
},
|
|
341
392
|
|
|
393
|
+
/**
|
|
394
|
+
* #getter
|
|
395
|
+
*/
|
|
342
396
|
get maxBpPerPx() {
|
|
343
397
|
return this.totalBp / (self.width * 0.9)
|
|
344
398
|
},
|
|
345
399
|
|
|
400
|
+
/**
|
|
401
|
+
* #getter
|
|
402
|
+
*/
|
|
346
403
|
get minBpPerPx() {
|
|
347
404
|
return 1 / 50
|
|
348
405
|
},
|
|
349
406
|
|
|
407
|
+
/**
|
|
408
|
+
* #getter
|
|
409
|
+
*/
|
|
350
410
|
get error() {
|
|
351
411
|
return self.volatileError || this.assemblyErrors
|
|
352
412
|
},
|
|
353
413
|
|
|
414
|
+
/**
|
|
415
|
+
* #getter
|
|
416
|
+
*/
|
|
354
417
|
get maxOffset() {
|
|
355
418
|
// objectively determined to keep the linear genome on the main screen
|
|
356
419
|
const leftPadding = 10
|
|
357
420
|
return this.displayedRegionsTotalPx - leftPadding
|
|
358
421
|
},
|
|
359
422
|
|
|
423
|
+
/**
|
|
424
|
+
* #getter
|
|
425
|
+
*/
|
|
360
426
|
get minOffset() {
|
|
361
427
|
// objectively determined to keep the linear genome on the main screen
|
|
362
428
|
const rightPadding = 30
|
|
363
429
|
return -self.width + rightPadding
|
|
364
430
|
},
|
|
365
431
|
|
|
432
|
+
/**
|
|
433
|
+
* #getter
|
|
434
|
+
*/
|
|
366
435
|
get displayedRegionsTotalPx() {
|
|
367
436
|
return this.totalBp / self.bpPerPx
|
|
368
437
|
},
|
|
369
438
|
|
|
439
|
+
/**
|
|
440
|
+
* #method
|
|
441
|
+
*/
|
|
370
442
|
renderProps() {
|
|
371
443
|
return {
|
|
372
444
|
...getParentRenderProps(self),
|
|
@@ -378,6 +450,9 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
378
450
|
}
|
|
379
451
|
},
|
|
380
452
|
|
|
453
|
+
/**
|
|
454
|
+
* #method
|
|
455
|
+
*/
|
|
381
456
|
searchScope(assemblyName: string) {
|
|
382
457
|
return {
|
|
383
458
|
assemblyName,
|
|
@@ -386,10 +461,16 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
386
461
|
}
|
|
387
462
|
},
|
|
388
463
|
|
|
464
|
+
/**
|
|
465
|
+
* #method
|
|
466
|
+
*/
|
|
389
467
|
getTrack(id: string) {
|
|
390
468
|
return self.tracks.find(t => t.configuration.trackId === id)
|
|
391
469
|
},
|
|
392
470
|
|
|
471
|
+
/**
|
|
472
|
+
* #method
|
|
473
|
+
*/
|
|
393
474
|
rankSearchResults(results: BaseResult[]) {
|
|
394
475
|
// order of rank
|
|
395
476
|
const openTrackIds = self.tracks.map(
|
|
@@ -403,7 +484,10 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
403
484
|
return results
|
|
404
485
|
},
|
|
405
486
|
|
|
406
|
-
|
|
487
|
+
/**
|
|
488
|
+
* #method
|
|
489
|
+
* modifies view menu action onClick to apply to all tracks of same type
|
|
490
|
+
*/
|
|
407
491
|
rewriteOnClicks(trackType: string, viewMenuActions: MenuItem[]) {
|
|
408
492
|
viewMenuActions.forEach(action => {
|
|
409
493
|
// go to lowest level menu
|
|
@@ -422,7 +506,9 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
422
506
|
}
|
|
423
507
|
})
|
|
424
508
|
},
|
|
425
|
-
|
|
509
|
+
/**
|
|
510
|
+
* #getter
|
|
511
|
+
*/
|
|
426
512
|
get trackTypeActions() {
|
|
427
513
|
const allActions: Map<string, MenuItem[]> = new Map()
|
|
428
514
|
self.tracks.forEach(track => {
|
|
@@ -609,7 +695,9 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
609
695
|
}
|
|
610
696
|
return t[0]
|
|
611
697
|
},
|
|
612
|
-
|
|
698
|
+
/**
|
|
699
|
+
* #action
|
|
700
|
+
*/
|
|
613
701
|
hideTrack(trackId: string) {
|
|
614
702
|
const schema = pluginManager.pluggableConfigSchemaType('track')
|
|
615
703
|
const conf = resolveIdentifier(schema, getRoot(self), trackId)
|
|
@@ -814,7 +902,7 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
814
902
|
* this "clears the view" and makes the view return to the import form
|
|
815
903
|
*/
|
|
816
904
|
clearView() {
|
|
817
|
-
|
|
905
|
+
self.displayedRegions.clear()
|
|
818
906
|
self.tracks.clear()
|
|
819
907
|
// it is necessary to run these after setting displayed regions empty
|
|
820
908
|
// or else model.offsetPx gets set to Infinity and breaks
|
|
@@ -973,59 +1061,57 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
973
1061
|
icon: SyncAltIcon,
|
|
974
1062
|
onClick: self.horizontallyFlip,
|
|
975
1063
|
},
|
|
976
|
-
{ type: 'divider' },
|
|
977
1064
|
{
|
|
978
|
-
label: 'Show
|
|
1065
|
+
label: 'Show...',
|
|
979
1066
|
icon: VisibilityIcon,
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1067
|
+
subMenu: [
|
|
1068
|
+
{
|
|
1069
|
+
label: 'Show all regions in assembly',
|
|
1070
|
+
onClick: self.showAllRegionsInAssembly,
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
label: 'Show center line',
|
|
1074
|
+
type: 'checkbox',
|
|
1075
|
+
checked: self.showCenterLine,
|
|
1076
|
+
onClick: self.toggleCenterLine,
|
|
1077
|
+
},
|
|
1078
|
+
{
|
|
1079
|
+
label: 'Show header',
|
|
1080
|
+
type: 'checkbox',
|
|
1081
|
+
checked: !self.hideHeader,
|
|
1082
|
+
onClick: self.toggleHeader,
|
|
1083
|
+
},
|
|
1084
|
+
{
|
|
1085
|
+
label: 'Show header overview',
|
|
1086
|
+
type: 'checkbox',
|
|
1087
|
+
checked: !self.hideHeaderOverview,
|
|
1088
|
+
onClick: self.toggleHeaderOverview,
|
|
1089
|
+
disabled: self.hideHeader,
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
label: 'Show no tracks active button',
|
|
1093
|
+
type: 'checkbox',
|
|
1094
|
+
checked: !self.hideNoTracksActive,
|
|
1095
|
+
onClick: self.toggleNoTracksActive,
|
|
1096
|
+
},
|
|
1097
|
+
{
|
|
1098
|
+
label: 'Show guidelines',
|
|
1099
|
+
type: 'checkbox',
|
|
1100
|
+
checked: self.showGridlines,
|
|
1101
|
+
onClick: self.toggleShowGridlines,
|
|
1102
|
+
},
|
|
1103
|
+
...(canShowCytobands
|
|
1104
|
+
? [
|
|
1105
|
+
{
|
|
1106
|
+
label: 'Show ideogram',
|
|
1107
|
+
type: 'checkbox' as const,
|
|
1108
|
+
checked: self.showCytobands,
|
|
1109
|
+
onClick: () => self.setShowCytobands(!showCytobands),
|
|
1110
|
+
},
|
|
1111
|
+
]
|
|
1112
|
+
: []),
|
|
1113
|
+
],
|
|
1017
1114
|
},
|
|
1018
|
-
...(canShowCytobands
|
|
1019
|
-
? [
|
|
1020
|
-
{
|
|
1021
|
-
label: 'Show ideogram',
|
|
1022
|
-
icon: VisibilityIcon,
|
|
1023
|
-
type: 'checkbox' as const,
|
|
1024
|
-
checked: self.showCytobands,
|
|
1025
|
-
onClick: () => self.setShowCytobands(!showCytobands),
|
|
1026
|
-
},
|
|
1027
|
-
]
|
|
1028
|
-
: []),
|
|
1029
1115
|
{
|
|
1030
1116
|
label: 'Track labels',
|
|
1031
1117
|
icon: LabelIcon,
|
|
@@ -1375,18 +1461,14 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
1375
1461
|
)
|
|
1376
1462
|
return
|
|
1377
1463
|
}
|
|
1378
|
-
let
|
|
1379
|
-
let
|
|
1380
|
-
let
|
|
1381
|
-
for (
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
const location = locations[locationIndex]
|
|
1387
|
-
const region = self.displayedRegions[index + locationIndex]
|
|
1388
|
-
locationStart = location.start || region.start
|
|
1389
|
-
locationEnd = location.end || region.end
|
|
1464
|
+
let idx = 0
|
|
1465
|
+
let start = 0
|
|
1466
|
+
let end = 0
|
|
1467
|
+
for (idx; idx < locations.length; idx++) {
|
|
1468
|
+
const location = locations[idx]
|
|
1469
|
+
const region = self.displayedRegions[index + idx]
|
|
1470
|
+
start = location.start || region.start
|
|
1471
|
+
end = location.end || region.end
|
|
1390
1472
|
if (location.refName !== region.refName) {
|
|
1391
1473
|
throw new Error(
|
|
1392
1474
|
`Entered location ${assembleLocString(
|
|
@@ -1395,10 +1477,9 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
1395
1477
|
)
|
|
1396
1478
|
}
|
|
1397
1479
|
}
|
|
1398
|
-
|
|
1480
|
+
idx -= 1
|
|
1399
1481
|
const startDisplayedRegion = self.displayedRegions[index]
|
|
1400
|
-
const endDisplayedRegion =
|
|
1401
|
-
self.displayedRegions[index + locationIndex]
|
|
1482
|
+
const endDisplayedRegion = self.displayedRegions[index + idx]
|
|
1402
1483
|
this.moveTo(
|
|
1403
1484
|
{
|
|
1404
1485
|
index,
|
|
@@ -1407,10 +1488,10 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
1407
1488
|
: s - startDisplayedRegion.start,
|
|
1408
1489
|
},
|
|
1409
1490
|
{
|
|
1410
|
-
index: index +
|
|
1491
|
+
index: index + idx,
|
|
1411
1492
|
offset: endDisplayedRegion.reversed
|
|
1412
|
-
? endDisplayedRegion.end -
|
|
1413
|
-
:
|
|
1493
|
+
? endDisplayedRegion.end - start
|
|
1494
|
+
: end - endDisplayedRegion.start,
|
|
1414
1495
|
},
|
|
1415
1496
|
)
|
|
1416
1497
|
return
|