@jbrowse/plugin-linear-genome-view 1.7.8 → 1.7.11
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/BaseLinearDisplay.d.ts +1 -5
- package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js +32 -120
- package/dist/BaseLinearDisplay/components/Tooltip.d.ts +8 -0
- package/dist/BaseLinearDisplay/components/Tooltip.js +125 -0
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +4 -4
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +3 -2
- package/dist/LinearBareDisplay/model.d.ts +1 -1
- package/dist/LinearBasicDisplay/model.d.ts +1 -2
- package/dist/LinearBasicDisplay/model.js +2 -2
- package/dist/LinearGenomeView/components/ExportSvgDialog.js +35 -25
- package/dist/LinearGenomeView/components/Header.d.ts +0 -1
- package/dist/LinearGenomeView/components/Header.js +3 -1
- package/dist/LinearGenomeView/components/HelpDialog.js +2 -3
- package/dist/LinearGenomeView/components/ImportForm.d.ts +0 -1
- package/dist/LinearGenomeView/components/ImportForm.js +40 -70
- package/dist/LinearGenomeView/components/LinearGenomeView.js +6 -2
- package/dist/LinearGenomeView/components/LinearGenomeView.test.js +2 -2
- package/dist/LinearGenomeView/components/OverviewScaleBar.d.ts +21 -5
- package/dist/LinearGenomeView/components/OverviewScaleBar.js +25 -18
- package/dist/LinearGenomeView/components/ScaleBar.d.ts +6 -2
- package/dist/LinearGenomeView/components/ScaleBar.js +8 -3
- package/dist/LinearGenomeView/components/SearchBox.js +36 -72
- package/dist/LinearGenomeView/components/SearchResultsDialog.d.ts +1 -1
- package/dist/LinearGenomeView/components/SearchResultsDialog.js +0 -1
- package/dist/LinearGenomeView/components/TrackLabel.js +25 -41
- package/dist/LinearGenomeView/components/util.d.ts +12 -0
- package/dist/LinearGenomeView/components/util.js +59 -0
- package/dist/LinearGenomeView/index.d.ts +7 -11
- package/dist/LinearGenomeView/index.js +60 -33
- package/dist/LinearGenomeView/index.test.js +22 -5
- package/dist/index.d.ts +3 -3
- package/dist/index.js +22 -11
- package/package.json +3 -2
- package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +4 -89
- package/src/BaseLinearDisplay/components/Tooltip.tsx +97 -0
- package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +11 -4
- package/src/LinearBasicDisplay/model.ts +2 -4
- package/src/LinearGenomeView/components/ExportSvgDialog.tsx +24 -11
- package/src/LinearGenomeView/components/Header.tsx +2 -1
- package/src/LinearGenomeView/components/HelpDialog.tsx +5 -4
- package/src/LinearGenomeView/components/ImportForm.tsx +18 -25
- package/src/LinearGenomeView/components/LinearGenomeView.test.js +2 -2
- package/src/LinearGenomeView/components/LinearGenomeView.tsx +16 -10
- package/src/LinearGenomeView/components/OverviewScaleBar.tsx +42 -34
- package/src/LinearGenomeView/components/ScaleBar.tsx +6 -9
- package/src/LinearGenomeView/components/SearchBox.tsx +18 -29
- package/src/LinearGenomeView/components/SearchResultsDialog.tsx +0 -1
- package/src/LinearGenomeView/components/TrackLabel.tsx +25 -28
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.js.snap +4 -21
- package/src/LinearGenomeView/components/util.ts +43 -0
- package/src/LinearGenomeView/index.test.ts +20 -5
- package/src/LinearGenomeView/index.tsx +56 -27
- package/src/index.ts +35 -30
|
@@ -92,16 +92,22 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
|
|
|
92
92
|
<TracksContainer model={model}>
|
|
93
93
|
{!tracks.length ? (
|
|
94
94
|
<Paper variant="outlined" className={classes.note}>
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
95
|
+
{!model.hideNoTracksActive ? (
|
|
96
|
+
<>
|
|
97
|
+
<Typography>No tracks active.</Typography>
|
|
98
|
+
<Button
|
|
99
|
+
variant="contained"
|
|
100
|
+
color="primary"
|
|
101
|
+
onClick={model.activateTrackSelector}
|
|
102
|
+
style={{ zIndex: 1000 }}
|
|
103
|
+
startIcon={<TrackSelectorIcon />}
|
|
104
|
+
>
|
|
105
|
+
Open track selector
|
|
106
|
+
</Button>
|
|
107
|
+
</>
|
|
108
|
+
) : (
|
|
109
|
+
<div style={{ height: '48px' }}></div>
|
|
110
|
+
)}
|
|
105
111
|
</Paper>
|
|
106
112
|
) : (
|
|
107
113
|
tracks.map(track => (
|
|
@@ -5,7 +5,7 @@ import { Instance } from 'mobx-state-tree'
|
|
|
5
5
|
import clsx from 'clsx'
|
|
6
6
|
|
|
7
7
|
import Base1DView, { Base1DViewModel } from '@jbrowse/core/util/Base1DViewModel'
|
|
8
|
-
import { getSession } from '@jbrowse/core/util'
|
|
8
|
+
import { getSession, getTickDisplayStr } from '@jbrowse/core/util'
|
|
9
9
|
import { ContentBlock } from '@jbrowse/core/util/blockTypes'
|
|
10
10
|
import { Assembly } from '@jbrowse/core/assemblyManager/assembly'
|
|
11
11
|
|
|
@@ -51,7 +51,6 @@ const useStyles = makeStyles(theme => {
|
|
|
51
51
|
},
|
|
52
52
|
scaleBarLabel: {
|
|
53
53
|
height: HEADER_OVERVIEW_HEIGHT,
|
|
54
|
-
width: 1,
|
|
55
54
|
position: 'absolute',
|
|
56
55
|
display: 'flex',
|
|
57
56
|
justifyContent: 'center',
|
|
@@ -171,6 +170,19 @@ const colorMap: { [key: string]: string | undefined } = {
|
|
|
171
170
|
acen: '#800',
|
|
172
171
|
}
|
|
173
172
|
|
|
173
|
+
function getCytobands(assembly: Assembly | undefined, refName: string) {
|
|
174
|
+
return (
|
|
175
|
+
assembly?.cytobands
|
|
176
|
+
?.map(f => ({
|
|
177
|
+
refName: assembly.getCanonicalRefName(f.get('refName')),
|
|
178
|
+
start: f.get('start'),
|
|
179
|
+
end: f.get('end'),
|
|
180
|
+
type: f.get('type'),
|
|
181
|
+
}))
|
|
182
|
+
.filter(f => f.refName === refName) || []
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
|
|
174
186
|
const Cytobands = observer(
|
|
175
187
|
({
|
|
176
188
|
overview,
|
|
@@ -182,37 +194,30 @@ const Cytobands = observer(
|
|
|
182
194
|
block: ContentBlock
|
|
183
195
|
}) => {
|
|
184
196
|
const { offsetPx, reversed } = block
|
|
185
|
-
const cytobands = assembly
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
overview.bpToPx({
|
|
201
|
-
refName,
|
|
202
|
-
coord: end,
|
|
203
|
-
}),
|
|
204
|
-
type,
|
|
205
|
-
]
|
|
206
|
-
})
|
|
197
|
+
const cytobands = getCytobands(assembly, block.refName)
|
|
198
|
+
const coords = cytobands.map(f => {
|
|
199
|
+
const { refName, start, end, type } = f
|
|
200
|
+
return [
|
|
201
|
+
overview.bpToPx({
|
|
202
|
+
refName,
|
|
203
|
+
coord: start,
|
|
204
|
+
}),
|
|
205
|
+
overview.bpToPx({
|
|
206
|
+
refName,
|
|
207
|
+
coord: end,
|
|
208
|
+
}),
|
|
209
|
+
type,
|
|
210
|
+
]
|
|
211
|
+
})
|
|
207
212
|
|
|
208
213
|
const arr = cytobands || []
|
|
209
214
|
const lcap = reversed ? arr.length - 1 : 0
|
|
210
215
|
const rcap = reversed ? 0 : arr.length - 1
|
|
211
216
|
|
|
212
217
|
let firstCent = true
|
|
213
|
-
return
|
|
218
|
+
return (
|
|
214
219
|
<g transform={`translate(-${offsetPx})`}>
|
|
215
|
-
{
|
|
220
|
+
{coords.map(([start, end, type], index) => {
|
|
216
221
|
const key = `${start}-${end}-${type}`
|
|
217
222
|
if (type === 'acen' && firstCent) {
|
|
218
223
|
firstCent = false
|
|
@@ -284,7 +289,7 @@ const Cytobands = observer(
|
|
|
284
289
|
}
|
|
285
290
|
})}
|
|
286
291
|
</g>
|
|
287
|
-
)
|
|
292
|
+
)
|
|
288
293
|
},
|
|
289
294
|
)
|
|
290
295
|
|
|
@@ -301,7 +306,7 @@ const OverviewBox = observer(
|
|
|
301
306
|
overview: Base1DViewModel
|
|
302
307
|
}) => {
|
|
303
308
|
const classes = useStyles()
|
|
304
|
-
const { cytobandOffset, showCytobands } = model
|
|
309
|
+
const { cytobandOffset, bpPerPx, showCytobands } = model
|
|
305
310
|
const { start, end, reversed, refName, assemblyName } = block
|
|
306
311
|
const { majorPitch } = chooseGridPitch(scale, 120, 15)
|
|
307
312
|
const { assemblyManager } = getSession(model)
|
|
@@ -314,13 +319,16 @@ const OverviewBox = observer(
|
|
|
314
319
|
tickLabels.push(reversed ? end - offsetLabel : start + offsetLabel)
|
|
315
320
|
}
|
|
316
321
|
|
|
322
|
+
const canDisplayCytobands =
|
|
323
|
+
showCytobands && getCytobands(assembly, block.refName).length
|
|
324
|
+
|
|
317
325
|
return (
|
|
318
326
|
<div>
|
|
319
327
|
{/* name of sequence */}
|
|
320
328
|
<Typography
|
|
321
329
|
style={{
|
|
322
330
|
left: block.offsetPx + 3,
|
|
323
|
-
color:
|
|
331
|
+
color: canDisplayCytobands ? 'black' : refNameColor,
|
|
324
332
|
}}
|
|
325
333
|
className={classes.scaleBarRefName}
|
|
326
334
|
>
|
|
@@ -329,12 +337,12 @@ const OverviewBox = observer(
|
|
|
329
337
|
<div
|
|
330
338
|
className={clsx(
|
|
331
339
|
classes.scaleBarContig,
|
|
332
|
-
|
|
340
|
+
canDisplayCytobands
|
|
333
341
|
? undefined
|
|
334
342
|
: reversed
|
|
335
343
|
? classes.scaleBarContigReverse
|
|
336
344
|
: classes.scaleBarContigForward,
|
|
337
|
-
!
|
|
345
|
+
!canDisplayCytobands ? classes.scaleBarBorder : undefined,
|
|
338
346
|
)}
|
|
339
347
|
style={{
|
|
340
348
|
left: block.offsetPx + cytobandOffset,
|
|
@@ -342,7 +350,7 @@ const OverviewBox = observer(
|
|
|
342
350
|
borderColor: refNameColor,
|
|
343
351
|
}}
|
|
344
352
|
>
|
|
345
|
-
{!
|
|
353
|
+
{!canDisplayCytobands
|
|
346
354
|
? tickLabels.map((tickLabel, labelIdx) => (
|
|
347
355
|
<Typography
|
|
348
356
|
key={`${JSON.stringify(block)}-${tickLabel}-${labelIdx}`}
|
|
@@ -354,12 +362,12 @@ const OverviewBox = observer(
|
|
|
354
362
|
color: refNameColor,
|
|
355
363
|
}}
|
|
356
364
|
>
|
|
357
|
-
{tickLabel
|
|
365
|
+
{getTickDisplayStr(tickLabel, bpPerPx)}
|
|
358
366
|
</Typography>
|
|
359
367
|
))
|
|
360
368
|
: null}
|
|
361
369
|
|
|
362
|
-
{
|
|
370
|
+
{canDisplayCytobands ? (
|
|
363
371
|
<svg style={{ width: '100%' }}>
|
|
364
372
|
<Cytobands
|
|
365
373
|
overview={overview}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
InterRegionPaddingBlock as InterRegionPaddingBlockComponent,
|
|
15
15
|
} from '../../BaseLinearDisplay/components/Block'
|
|
16
16
|
import { makeTicks } from '../util'
|
|
17
|
+
import { getTickDisplayStr } from '@jbrowse/core/util'
|
|
17
18
|
|
|
18
19
|
type LGV = LinearGenomeViewModel
|
|
19
20
|
|
|
@@ -95,18 +96,14 @@ const RenderedRefNameLabels = observer(({ model }: { model: LGV }) => {
|
|
|
95
96
|
|
|
96
97
|
const RenderedScaleBarLabels = observer(({ model }: { model: LGV }) => {
|
|
97
98
|
const classes = useStyles()
|
|
99
|
+
const { bpPerPx } = model
|
|
98
100
|
|
|
99
101
|
return (
|
|
100
102
|
<>
|
|
101
103
|
{model.staticBlocks.map((block, index) => {
|
|
102
104
|
if (block instanceof ContentBlock) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
block.end,
|
|
106
|
-
model.bpPerPx,
|
|
107
|
-
true,
|
|
108
|
-
false,
|
|
109
|
-
)
|
|
105
|
+
const { start, end } = block
|
|
106
|
+
const ticks = makeTicks(start, end, bpPerPx, true, false)
|
|
110
107
|
|
|
111
108
|
return (
|
|
112
109
|
<ContentBlockComponent key={`${block.key}-${index}`} block={block}>
|
|
@@ -116,7 +113,7 @@ const RenderedScaleBarLabels = observer(({ model }: { model: LGV }) => {
|
|
|
116
113
|
(block.reversed
|
|
117
114
|
? block.end - tick.base
|
|
118
115
|
: tick.base - block.start) / model.bpPerPx
|
|
119
|
-
const baseNumber =
|
|
116
|
+
const baseNumber = tick.base + 1
|
|
120
117
|
return (
|
|
121
118
|
<div
|
|
122
119
|
key={tick.base}
|
|
@@ -125,7 +122,7 @@ const RenderedScaleBarLabels = observer(({ model }: { model: LGV }) => {
|
|
|
125
122
|
>
|
|
126
123
|
{baseNumber ? (
|
|
127
124
|
<Typography className={classes.majorTickLabel}>
|
|
128
|
-
{baseNumber}
|
|
125
|
+
{getTickDisplayStr(baseNumber, bpPerPx)}
|
|
129
126
|
</Typography>
|
|
130
127
|
) : null}
|
|
131
128
|
</div>
|
|
@@ -3,11 +3,10 @@ import { observer } from 'mobx-react'
|
|
|
3
3
|
import { makeStyles, useTheme, alpha } from '@material-ui/core'
|
|
4
4
|
import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
|
|
5
5
|
import { getSession } from '@jbrowse/core/util'
|
|
6
|
-
import { SearchType } from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
7
6
|
|
|
8
7
|
// locals
|
|
9
8
|
import RefNameAutocomplete from './RefNameAutocomplete'
|
|
10
|
-
import {
|
|
9
|
+
import { fetchResults } from './util'
|
|
11
10
|
import { LinearGenomeViewModel, SPACING, WIDGET_HEIGHT } from '..'
|
|
12
11
|
|
|
13
12
|
const useStyles = makeStyles(() => ({
|
|
@@ -33,31 +32,6 @@ function SearchBox({
|
|
|
33
32
|
const assembly = assemblyManager.get(assemblyName)
|
|
34
33
|
const searchScope = model.searchScope(assemblyName)
|
|
35
34
|
|
|
36
|
-
async function fetchResults(query: string, searchType?: SearchType) {
|
|
37
|
-
if (!textSearchManager) {
|
|
38
|
-
console.warn('No text search manager')
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const textSearchResults = await textSearchManager?.search(
|
|
42
|
-
{
|
|
43
|
-
queryString: query,
|
|
44
|
-
searchType,
|
|
45
|
-
},
|
|
46
|
-
searchScope,
|
|
47
|
-
rankSearchResults,
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
const refNameResults = assembly?.allRefNames
|
|
51
|
-
?.filter(refName => refName.startsWith(query))
|
|
52
|
-
.map(r => new BaseResult({ label: r }))
|
|
53
|
-
.slice(0, 10)
|
|
54
|
-
|
|
55
|
-
return dedupe(
|
|
56
|
-
[...(refNameResults || []), ...(textSearchResults || [])],
|
|
57
|
-
elt => elt.getId(),
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
35
|
// gets a string as input, or use stored option results from previous query,
|
|
62
36
|
// then re-query and
|
|
63
37
|
// 1) if it has multiple results: pop a dialog
|
|
@@ -82,7 +56,14 @@ function SearchBox({
|
|
|
82
56
|
) {
|
|
83
57
|
model.navToLocString(location, assemblyName)
|
|
84
58
|
} else {
|
|
85
|
-
const results = await fetchResults(
|
|
59
|
+
const results = await fetchResults({
|
|
60
|
+
queryString: label,
|
|
61
|
+
searchType: 'exact',
|
|
62
|
+
searchScope,
|
|
63
|
+
rankSearchResults,
|
|
64
|
+
textSearchManager,
|
|
65
|
+
assembly,
|
|
66
|
+
})
|
|
86
67
|
if (results.length > 1) {
|
|
87
68
|
model.setSearchResults(results, label.toLowerCase())
|
|
88
69
|
return
|
|
@@ -106,7 +87,15 @@ function SearchBox({
|
|
|
106
87
|
showHelp={showHelp}
|
|
107
88
|
onSelect={handleSelectedRegion}
|
|
108
89
|
assemblyName={assemblyName}
|
|
109
|
-
fetchResults={
|
|
90
|
+
fetchResults={queryString =>
|
|
91
|
+
fetchResults({
|
|
92
|
+
queryString,
|
|
93
|
+
searchScope,
|
|
94
|
+
rankSearchResults,
|
|
95
|
+
textSearchManager,
|
|
96
|
+
assembly,
|
|
97
|
+
})
|
|
98
|
+
}
|
|
110
99
|
model={model}
|
|
111
100
|
TextFieldProps={{
|
|
112
101
|
variant: 'outlined',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { getConf, readConfObject } from '@jbrowse/core/configuration'
|
|
3
|
-
import
|
|
3
|
+
import CascadingMenu from '@jbrowse/core/ui/CascadingMenu'
|
|
4
4
|
import { getSession, getContainingView } from '@jbrowse/core/util'
|
|
5
5
|
import { BaseTrackModel } from '@jbrowse/core/pluggableElementTypes/models'
|
|
6
6
|
import {
|
|
@@ -11,14 +11,21 @@ import {
|
|
|
11
11
|
makeStyles,
|
|
12
12
|
} from '@material-ui/core'
|
|
13
13
|
|
|
14
|
+
import {
|
|
15
|
+
bindTrigger,
|
|
16
|
+
bindPopover,
|
|
17
|
+
usePopupState,
|
|
18
|
+
} from 'material-ui-popup-state/hooks'
|
|
19
|
+
|
|
20
|
+
import clsx from 'clsx'
|
|
21
|
+
import { observer } from 'mobx-react'
|
|
22
|
+
import { Instance } from 'mobx-state-tree'
|
|
23
|
+
|
|
14
24
|
// icons
|
|
15
25
|
import MoreVertIcon from '@material-ui/icons/MoreVert'
|
|
16
26
|
import DragIcon from '@material-ui/icons/DragIndicator'
|
|
17
27
|
import CloseIcon from '@material-ui/icons/Close'
|
|
18
28
|
|
|
19
|
-
import clsx from 'clsx'
|
|
20
|
-
import { observer } from 'mobx-react'
|
|
21
|
-
import { Instance } from 'mobx-state-tree'
|
|
22
29
|
import { LinearGenomeViewStateModel } from '..'
|
|
23
30
|
|
|
24
31
|
const useStyles = makeStyles(theme => ({
|
|
@@ -54,22 +61,20 @@ const useStyles = makeStyles(theme => ({
|
|
|
54
61
|
type LGV = Instance<LinearGenomeViewStateModel>
|
|
55
62
|
|
|
56
63
|
const TrackLabel = React.forwardRef(
|
|
57
|
-
(
|
|
64
|
+
(
|
|
65
|
+
{ track, className }: { track: BaseTrackModel; className?: string },
|
|
66
|
+
ref,
|
|
67
|
+
) => {
|
|
58
68
|
const classes = useStyles()
|
|
59
|
-
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
|
|
60
|
-
const { track, className } = props
|
|
61
69
|
const view = getContainingView(track) as LGV
|
|
62
70
|
const session = getSession(track)
|
|
63
71
|
const trackConf = track.configuration
|
|
64
72
|
const trackId = getConf(track, 'trackId')
|
|
65
73
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const handleClose = () => {
|
|
71
|
-
setAnchorEl(null)
|
|
72
|
-
}
|
|
74
|
+
const popupState = usePopupState({
|
|
75
|
+
popupId: 'trackLabelMenu',
|
|
76
|
+
variant: 'popover',
|
|
77
|
+
})
|
|
73
78
|
|
|
74
79
|
const onDragStart = (event: React.DragEvent<HTMLSpanElement>) => {
|
|
75
80
|
const target = event.target as HTMLElement
|
|
@@ -91,17 +96,12 @@ const TrackLabel = React.forwardRef(
|
|
|
91
96
|
if (getConf(track, 'type') === 'ReferenceSequenceTrack') {
|
|
92
97
|
const r = session.assemblies.find(a => a.sequence === trackConf)
|
|
93
98
|
trackName =
|
|
94
|
-
|
|
99
|
+
trackName ||
|
|
95
100
|
(r
|
|
96
101
|
? `Reference Sequence (${readConfObject(r, 'name')})`
|
|
97
102
|
: 'Reference Sequence')
|
|
98
103
|
}
|
|
99
104
|
|
|
100
|
-
function handleMenuItemClick(_: unknown, callback: Function) {
|
|
101
|
-
callback()
|
|
102
|
-
handleClose()
|
|
103
|
-
}
|
|
104
|
-
|
|
105
105
|
const items = [
|
|
106
106
|
...(session.getTrackActionMenuItems?.(trackConf) || []),
|
|
107
107
|
...track.trackMenuItems(),
|
|
@@ -135,9 +135,7 @@ const TrackLabel = React.forwardRef(
|
|
|
135
135
|
{trackName}
|
|
136
136
|
</Typography>
|
|
137
137
|
<IconButton
|
|
138
|
-
|
|
139
|
-
aria-haspopup="true"
|
|
140
|
-
onClick={handleClick}
|
|
138
|
+
{...bindTrigger(popupState)}
|
|
141
139
|
className={classes.iconButton}
|
|
142
140
|
color="secondary"
|
|
143
141
|
data-testid="track_menu_icon"
|
|
@@ -146,12 +144,11 @@ const TrackLabel = React.forwardRef(
|
|
|
146
144
|
<MoreVertIcon />
|
|
147
145
|
</IconButton>
|
|
148
146
|
</Paper>
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
onMenuItemClick={
|
|
152
|
-
open={Boolean(anchorEl)}
|
|
153
|
-
onClose={handleClose}
|
|
147
|
+
<CascadingMenu
|
|
148
|
+
{...bindPopover(popupState)}
|
|
149
|
+
onMenuItemClick={(_: unknown, callback: Function) => callback()}
|
|
154
150
|
menuItems={items}
|
|
151
|
+
popupState={popupState}
|
|
155
152
|
/>
|
|
156
153
|
</>
|
|
157
154
|
)
|
|
@@ -255,8 +255,7 @@ exports[`<LinearGenomeView /> renders one track, one region 1`] = `
|
|
|
255
255
|
<p
|
|
256
256
|
class="MuiTypography-root makeStyles-bp MuiTypography-body2 MuiTypography-colorTextSecondary"
|
|
257
257
|
>
|
|
258
|
-
|
|
259
|
-
bp
|
|
258
|
+
100bp
|
|
260
259
|
</p>
|
|
261
260
|
<div
|
|
262
261
|
class="makeStyles-container"
|
|
@@ -425,13 +424,7 @@ exports[`<LinearGenomeView /> renders one track, one region 1`] = `
|
|
|
425
424
|
<div
|
|
426
425
|
class="makeStyles-tick"
|
|
427
426
|
style="left: -1px;"
|
|
428
|
-
|
|
429
|
-
<p
|
|
430
|
-
class="MuiTypography-root makeStyles-majorTickLabel MuiTypography-body1"
|
|
431
|
-
>
|
|
432
|
-
0
|
|
433
|
-
</p>
|
|
434
|
-
</div>
|
|
427
|
+
/>
|
|
435
428
|
</div>
|
|
436
429
|
<div
|
|
437
430
|
class="makeStyles-boundaryPaddingBlock"
|
|
@@ -500,7 +493,6 @@ exports[`<LinearGenomeView /> renders one track, one region 1`] = `
|
|
|
500
493
|
Foo Track
|
|
501
494
|
</span>
|
|
502
495
|
<button
|
|
503
|
-
aria-controls="simple-menu"
|
|
504
496
|
aria-haspopup="true"
|
|
505
497
|
class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary"
|
|
506
498
|
data-testid="track_menu_icon"
|
|
@@ -850,8 +842,7 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
|
|
|
850
842
|
<p
|
|
851
843
|
class="MuiTypography-root makeStyles-bp MuiTypography-body2 MuiTypography-colorTextSecondary"
|
|
852
844
|
>
|
|
853
|
-
|
|
854
|
-
bp
|
|
845
|
+
798bp
|
|
855
846
|
</p>
|
|
856
847
|
<div
|
|
857
848
|
class="makeStyles-container"
|
|
@@ -1239,13 +1230,7 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
|
|
|
1239
1230
|
<div
|
|
1240
1231
|
class="makeStyles-tick"
|
|
1241
1232
|
style="left: -1px;"
|
|
1242
|
-
|
|
1243
|
-
<p
|
|
1244
|
-
class="MuiTypography-root makeStyles-majorTickLabel MuiTypography-body1"
|
|
1245
|
-
>
|
|
1246
|
-
0
|
|
1247
|
-
</p>
|
|
1248
|
-
</div>
|
|
1233
|
+
/>
|
|
1249
1234
|
</div>
|
|
1250
1235
|
<div
|
|
1251
1236
|
class="makeStyles-interRegionPaddingBlock"
|
|
@@ -1390,7 +1375,6 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
|
|
|
1390
1375
|
Foo Track
|
|
1391
1376
|
</span>
|
|
1392
1377
|
<button
|
|
1393
|
-
aria-controls="simple-menu"
|
|
1394
1378
|
aria-haspopup="true"
|
|
1395
1379
|
class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary"
|
|
1396
1380
|
data-testid="track_menu_icon"
|
|
@@ -1533,7 +1517,6 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
|
|
|
1533
1517
|
Bar Track
|
|
1534
1518
|
</span>
|
|
1535
1519
|
<button
|
|
1536
|
-
aria-controls="simple-menu"
|
|
1537
1520
|
aria-haspopup="true"
|
|
1538
1521
|
class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary"
|
|
1539
1522
|
data-testid="track_menu_icon"
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { Assembly } from '@jbrowse/core/assemblyManager/assembly'
|
|
2
|
+
import { SearchType } from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
1
3
|
import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
|
|
4
|
+
import { SearchScope } from '@jbrowse/core/TextSearch/TextSearchManager'
|
|
5
|
+
import { TextSearchManager } from '@jbrowse/core/util'
|
|
2
6
|
|
|
3
7
|
export function dedupe(
|
|
4
8
|
results: BaseResult[] = [],
|
|
@@ -8,3 +12,42 @@ export function dedupe(
|
|
|
8
12
|
(elt, idx, self) => idx === self.findIndex(t => cb(t) === cb(elt)),
|
|
9
13
|
)
|
|
10
14
|
}
|
|
15
|
+
|
|
16
|
+
export async function fetchResults({
|
|
17
|
+
queryString,
|
|
18
|
+
searchType,
|
|
19
|
+
searchScope,
|
|
20
|
+
rankSearchResults,
|
|
21
|
+
textSearchManager,
|
|
22
|
+
assembly,
|
|
23
|
+
}: {
|
|
24
|
+
queryString: string
|
|
25
|
+
searchScope: SearchScope
|
|
26
|
+
rankSearchResults: (results: BaseResult[]) => BaseResult[]
|
|
27
|
+
searchType?: SearchType
|
|
28
|
+
textSearchManager?: TextSearchManager
|
|
29
|
+
assembly?: Assembly
|
|
30
|
+
}) {
|
|
31
|
+
if (!textSearchManager) {
|
|
32
|
+
console.warn('No text search manager')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const textSearchResults = await textSearchManager?.search(
|
|
36
|
+
{
|
|
37
|
+
queryString,
|
|
38
|
+
searchType,
|
|
39
|
+
},
|
|
40
|
+
searchScope,
|
|
41
|
+
rankSearchResults,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
const refNameResults = assembly?.allRefNames
|
|
45
|
+
?.filter(ref => ref.toLowerCase().startsWith(queryString.toLowerCase()))
|
|
46
|
+
.slice(0, 10)
|
|
47
|
+
.map(r => new BaseResult({ label: r }))
|
|
48
|
+
|
|
49
|
+
return dedupe(
|
|
50
|
+
[...(refNameResults || []), ...(textSearchResults || [])],
|
|
51
|
+
elt => elt.getId(),
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -72,7 +72,7 @@ function initialize() {
|
|
|
72
72
|
})
|
|
73
73
|
.actions(self => ({
|
|
74
74
|
isValidRefName(str: string) {
|
|
75
|
-
return
|
|
75
|
+
return str === 'ctgA' || str === 'ctgB'
|
|
76
76
|
},
|
|
77
77
|
get(str: string) {
|
|
78
78
|
return self.assemblies.get(str)
|
|
@@ -989,8 +989,23 @@ test('multi region', () => {
|
|
|
989
989
|
model.navToLocString('ctgA ctgB')
|
|
990
990
|
expect(model.displayedRegions[0].refName).toBe('ctgA')
|
|
991
991
|
expect(model.displayedRegions[1].refName).toBe('ctgB')
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
992
|
+
})
|
|
993
|
+
|
|
994
|
+
test('space separated locstring', () => {
|
|
995
|
+
const { Session, LinearGenomeModel } = initialize()
|
|
996
|
+
const model = Session.create({
|
|
997
|
+
configuration: {},
|
|
998
|
+
}).setView(
|
|
999
|
+
LinearGenomeModel.create({
|
|
1000
|
+
type: 'LinearGenomeView',
|
|
1001
|
+
tracks: [{ name: 'foo track', type: 'BasicTrack' }],
|
|
1002
|
+
}),
|
|
1003
|
+
)
|
|
1004
|
+
model.setWidth(800)
|
|
1005
|
+
model.setDisplayedRegions(volvoxDisplayedRegions.slice(0, 1))
|
|
1006
|
+
|
|
1007
|
+
model.navToLocString('ctgA 0 100')
|
|
1008
|
+
|
|
1009
|
+
expect(model.offsetPx).toBe(0)
|
|
1010
|
+
expect(model.bpPerPx).toBe(0.125)
|
|
996
1011
|
})
|