@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.
Files changed (53) hide show
  1. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +1 -5
  2. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js +32 -120
  3. package/dist/BaseLinearDisplay/components/Tooltip.d.ts +8 -0
  4. package/dist/BaseLinearDisplay/components/Tooltip.js +125 -0
  5. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +4 -4
  6. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +3 -2
  7. package/dist/LinearBareDisplay/model.d.ts +1 -1
  8. package/dist/LinearBasicDisplay/model.d.ts +1 -2
  9. package/dist/LinearBasicDisplay/model.js +2 -2
  10. package/dist/LinearGenomeView/components/ExportSvgDialog.js +35 -25
  11. package/dist/LinearGenomeView/components/Header.d.ts +0 -1
  12. package/dist/LinearGenomeView/components/Header.js +3 -1
  13. package/dist/LinearGenomeView/components/HelpDialog.js +2 -3
  14. package/dist/LinearGenomeView/components/ImportForm.d.ts +0 -1
  15. package/dist/LinearGenomeView/components/ImportForm.js +40 -70
  16. package/dist/LinearGenomeView/components/LinearGenomeView.js +6 -2
  17. package/dist/LinearGenomeView/components/LinearGenomeView.test.js +2 -2
  18. package/dist/LinearGenomeView/components/OverviewScaleBar.d.ts +21 -5
  19. package/dist/LinearGenomeView/components/OverviewScaleBar.js +25 -18
  20. package/dist/LinearGenomeView/components/ScaleBar.d.ts +6 -2
  21. package/dist/LinearGenomeView/components/ScaleBar.js +8 -3
  22. package/dist/LinearGenomeView/components/SearchBox.js +36 -72
  23. package/dist/LinearGenomeView/components/SearchResultsDialog.d.ts +1 -1
  24. package/dist/LinearGenomeView/components/SearchResultsDialog.js +0 -1
  25. package/dist/LinearGenomeView/components/TrackLabel.js +25 -41
  26. package/dist/LinearGenomeView/components/util.d.ts +12 -0
  27. package/dist/LinearGenomeView/components/util.js +59 -0
  28. package/dist/LinearGenomeView/index.d.ts +7 -11
  29. package/dist/LinearGenomeView/index.js +60 -33
  30. package/dist/LinearGenomeView/index.test.js +22 -5
  31. package/dist/index.d.ts +3 -3
  32. package/dist/index.js +22 -11
  33. package/package.json +3 -2
  34. package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +4 -89
  35. package/src/BaseLinearDisplay/components/Tooltip.tsx +97 -0
  36. package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +11 -4
  37. package/src/LinearBasicDisplay/model.ts +2 -4
  38. package/src/LinearGenomeView/components/ExportSvgDialog.tsx +24 -11
  39. package/src/LinearGenomeView/components/Header.tsx +2 -1
  40. package/src/LinearGenomeView/components/HelpDialog.tsx +5 -4
  41. package/src/LinearGenomeView/components/ImportForm.tsx +18 -25
  42. package/src/LinearGenomeView/components/LinearGenomeView.test.js +2 -2
  43. package/src/LinearGenomeView/components/LinearGenomeView.tsx +16 -10
  44. package/src/LinearGenomeView/components/OverviewScaleBar.tsx +42 -34
  45. package/src/LinearGenomeView/components/ScaleBar.tsx +6 -9
  46. package/src/LinearGenomeView/components/SearchBox.tsx +18 -29
  47. package/src/LinearGenomeView/components/SearchResultsDialog.tsx +0 -1
  48. package/src/LinearGenomeView/components/TrackLabel.tsx +25 -28
  49. package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.js.snap +4 -21
  50. package/src/LinearGenomeView/components/util.ts +43 -0
  51. package/src/LinearGenomeView/index.test.ts +20 -5
  52. package/src/LinearGenomeView/index.tsx +56 -27
  53. 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
- <Typography>No tracks active.</Typography>
96
- <Button
97
- variant="contained"
98
- color="primary"
99
- onClick={model.activateTrackSelector}
100
- style={{ zIndex: 1000 }}
101
- startIcon={<TrackSelectorIcon />}
102
- >
103
- Open track selector
104
- </Button>
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?.cytobands
186
- ?.map(f => ({
187
- refName: assembly.getCanonicalRefName(f.get('refName')),
188
- start: f.get('start'),
189
- end: f.get('end'),
190
- type: f.get('type'),
191
- }))
192
- .filter(f => f.refName === block.refName)
193
- .map(f => {
194
- const { refName, start, end, type } = f
195
- return [
196
- overview.bpToPx({
197
- refName,
198
- coord: start,
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 cytobands ? (
218
+ return (
214
219
  <g transform={`translate(-${offsetPx})`}>
215
- {cytobands.map(([start, end, type], index) => {
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
- ) : null
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: showCytobands ? 'black' : refNameColor,
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
- showCytobands
340
+ canDisplayCytobands
333
341
  ? undefined
334
342
  : reversed
335
343
  ? classes.scaleBarContigReverse
336
344
  : classes.scaleBarContigForward,
337
- !showCytobands ? classes.scaleBarBorder : undefined,
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
- {!showCytobands
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.toLocaleString('en-US')}
365
+ {getTickDisplayStr(tickLabel, bpPerPx)}
358
366
  </Typography>
359
367
  ))
360
368
  : null}
361
369
 
362
- {showCytobands ? (
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 ticks = makeTicks(
104
- block.start,
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 = (tick.base + 1).toLocaleString('en-US')
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 { dedupe } from './util'
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(label, 'exact')
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={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',
@@ -156,7 +156,6 @@ export default function SearchResultsDialog({
156
156
  }
157
157
  handleClose()
158
158
  }}
159
- disabled={!getTrackName(result.getTrackId())}
160
159
  color="primary"
161
160
  variant="contained"
162
161
  >
@@ -1,6 +1,6 @@
1
1
  import React from 'react'
2
2
  import { getConf, readConfObject } from '@jbrowse/core/configuration'
3
- import { Menu } from '@jbrowse/core/ui'
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
- (props: { track: BaseTrackModel; className?: string }, ref) => {
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 handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
67
- setAnchorEl(event.currentTarget)
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
- readConfObject(trackConf, 'name') ||
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
- aria-controls="simple-menu"
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
- <Menu
150
- anchorEl={anchorEl}
151
- onMenuItemClick={handleMenuItemClick}
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
- 100
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
- 798
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 !str.includes(':')
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
- // { refName: 'ctgA', start: 0, end: 50001 },
994
- // { refName: 'ctgB', start: 0, end: 6079 },
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
  })