@jbrowse/plugin-linear-genome-view 1.6.4 → 1.6.7

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 (31) hide show
  1. package/dist/BaseLinearDisplay/components/LinearBlocks.d.ts +0 -5
  2. package/dist/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.d.ts +1 -1
  3. package/dist/LinearBareDisplay/configSchema.d.ts +1 -1
  4. package/dist/LinearBasicDisplay/configSchema.d.ts +1 -1
  5. package/dist/LinearGenomeView/components/ScaleBar.d.ts +2 -0
  6. package/dist/LinearGenomeView/components/TrackContainer.d.ts +1 -1
  7. package/dist/LinearGenomeView/index.d.ts +1 -0
  8. package/dist/index.d.ts +1 -1
  9. package/dist/plugin-linear-genome-view.cjs.development.js +147 -249
  10. package/dist/plugin-linear-genome-view.cjs.development.js.map +1 -1
  11. package/dist/plugin-linear-genome-view.cjs.production.min.js +1 -1
  12. package/dist/plugin-linear-genome-view.cjs.production.min.js.map +1 -1
  13. package/dist/plugin-linear-genome-view.esm.js +149 -251
  14. package/dist/plugin-linear-genome-view.esm.js.map +1 -1
  15. package/package.json +2 -2
  16. package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +2 -4
  17. package/src/BaseLinearDisplay/components/LinearBlocks.tsx +4 -8
  18. package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +11 -3
  19. package/src/LinearBasicDisplay/model.ts +1 -1
  20. package/src/LinearGenomeView/components/HelpDialog.tsx +14 -1
  21. package/src/LinearGenomeView/components/LinearGenomeViewSvg.tsx +1 -13
  22. package/src/LinearGenomeView/components/OverviewScaleBar.tsx +7 -3
  23. package/src/LinearGenomeView/components/TrackContainer.tsx +35 -38
  24. package/src/LinearGenomeView/components/TrackLabel.tsx +5 -5
  25. package/src/LinearGenomeView/components/TracksContainer.tsx +0 -1
  26. package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.js.snap +23 -26
  27. package/src/LinearGenomeView/index.test.ts +44 -42
  28. package/src/LinearGenomeView/index.tsx +167 -242
  29. package/src/LinearGenomeView/volvoxDisplayedRegions.json +16 -0
  30. package/dist/LinearGenomeView/components/ReturnToImportFormDialog.d.ts +0 -9
  31. package/src/LinearGenomeView/components/ReturnToImportFormDialog.tsx +0 -83
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-linear-genome-view",
3
- "version": "1.6.4",
3
+ "version": "1.6.7",
4
4
  "description": "JBrowse 2 linear genome view",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -61,5 +61,5 @@
61
61
  "publishConfig": {
62
62
  "access": "public"
63
63
  },
64
- "gitHead": "7f157fbb2302d8825f99d01bcc0fd0616116c5d2"
64
+ "gitHead": "02012ec299c36647f755316571775d36b0fee5ec"
65
65
  }
@@ -31,7 +31,7 @@ const useStyles = makeStyles(theme => ({
31
31
  color: theme.palette.common.white,
32
32
  fontFamily: theme.typography.fontFamily,
33
33
  padding: '4px 8px',
34
- fontSize: theme.typography.pxToRem(10),
34
+ fontSize: theme.typography.pxToRem(12),
35
35
  lineHeight: `${round(14 / 10)}em`,
36
36
  maxWidth: 300,
37
37
  wordWrap: 'break-word',
@@ -96,9 +96,7 @@ const Tooltip = observer(
96
96
  {...attributes.popper}
97
97
  >
98
98
  <TooltipContents
99
- ref={(elt: HTMLDivElement) =>
100
- setWidth(elt?.getBoundingClientRect().width || 0)
101
- }
99
+ ref={elt => setWidth(elt?.getBoundingClientRect().width || 0)}
102
100
  message={contents}
103
101
  />
104
102
  </div>
@@ -1,7 +1,7 @@
1
+ import React from 'react'
1
2
  import { makeStyles } from '@material-ui/core/styles'
2
3
  import { getContainingView } from '@jbrowse/core/util'
3
- import { observer, PropTypes } from 'mobx-react'
4
- import React from 'react'
4
+ import { observer } from 'mobx-react'
5
5
  import {
6
6
  ContentBlock,
7
7
  ElidedBlock,
@@ -14,6 +14,7 @@ import {
14
14
  ElidedBlock as ElidedBlockComponent,
15
15
  InterRegionPaddingBlock as InterRegionPaddingBlockComponent,
16
16
  } from './Block'
17
+ import { LinearGenomeViewModel } from '../../LinearGenomeView'
17
18
 
18
19
  const useStyles = makeStyles({
19
20
  linearBlocks: {
@@ -96,8 +97,7 @@ const RenderedBlocks = observer(
96
97
  function LinearBlocks({ model }: { model: BaseLinearDisplayModel }) {
97
98
  const classes = useStyles()
98
99
  const { blockDefinitions } = model
99
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
- const viewModel = getContainingView(model) as any
100
+ const viewModel = getContainingView(model) as LinearGenomeViewModel
101
101
  return (
102
102
  <div
103
103
  data-testid="Blockset"
@@ -111,9 +111,5 @@ function LinearBlocks({ model }: { model: BaseLinearDisplayModel }) {
111
111
  )
112
112
  }
113
113
 
114
- LinearBlocks.propTypes = {
115
- model: PropTypes.observableObject.isRequired,
116
- }
117
-
118
114
  export { RenderedBlocks, useStyles }
119
115
  export default observer(LinearBlocks)
@@ -387,7 +387,10 @@ export const BaseLinearDisplay = types
387
387
  self.setError()
388
388
  const aborter = new AbortController()
389
389
  const view = getContainingView(self) as LGV
390
- if (!view.initialized) {
390
+
391
+ // extra check for contentBlocks.length
392
+ // https://github.com/GMOD/jbrowse-components/issues/2694
393
+ if (!view.initialized || !view.staticBlocks.contentBlocks.length) {
391
394
  return
392
395
  }
393
396
 
@@ -411,7 +414,7 @@ export const BaseLinearDisplay = types
411
414
  afterAttach() {
412
415
  // this autorun performs stats estimation
413
416
  //
414
- // the chain of events calls estimateRegionStats against the data
417
+ // the chain of events calls estimateRegionsStats against the data
415
418
  // adapter which by default uses featureDensity, but can also respond
416
419
  // with a byte size estimate and fetch size limit (data adapter can
417
420
  // define what is too much data)
@@ -423,7 +426,12 @@ export const BaseLinearDisplay = types
423
426
  const aborter = new AbortController()
424
427
  const view = getContainingView(self) as LGV
425
428
 
426
- if (!view.initialized) {
429
+ // extra check for contentBlocks.length
430
+ // https://github.com/GMOD/jbrowse-components/issues/2694
431
+ if (
432
+ !view.initialized ||
433
+ !view.staticBlocks.contentBlocks.length
434
+ ) {
427
435
  return
428
436
  }
429
437
 
@@ -139,7 +139,7 @@ const stateModelFactory = (configSchema: AnyConfigurationSchemaType) =>
139
139
  {
140
140
  label: 'Set max height',
141
141
  onClick: () => {
142
- getSession(self).queueDialog((doneCallback: Function) => [
142
+ getSession(self).queueDialog(doneCallback => [
143
143
  SetMaxHeightDlg,
144
144
  { model: self, handleClose: doneCallback },
145
145
  ])
@@ -53,7 +53,9 @@ export default function HelpDialog({
53
53
  <li>
54
54
  Jump to a specific region by typing the region into the location box
55
55
  as: <code>ref:start..end</code> or <code>ref:start-end</code>.
56
- Commas are allowed in the start and end coordinates.
56
+ Commas are allowed in the start and end coordinates. A
57
+ space-separated list of locstrings can be used to open up multiple
58
+ chromosomes at a time
57
59
  </li>
58
60
  </ul>
59
61
  <h3>Example Searches</h3>
@@ -68,6 +70,17 @@ export default function HelpDialog({
68
70
  <code>chr4:79,500,000..80,000,000</code> - jumps the region on
69
71
  chromosome 4 between 79.5Mb and 80Mb.
70
72
  </li>
73
+ <li>
74
+ <code>chr1:1-100 chr2:1-100</code> - create a split view of
75
+ chr1:1-100 and chr2:1-100
76
+ </li>
77
+ <li>
78
+ <code>chr1 chr2 chr3</code> - open up multiple chromosomes at once
79
+ </li>
80
+ <li>
81
+ <code>chr1:1-100[rev] chr2:1-100</code> - open up the first region
82
+ in the horizontally flipped orientation
83
+ </li>
71
84
  </ul>
72
85
  </DialogContent>
73
86
  <Divider />
@@ -3,7 +3,7 @@ import { renderToStaticMarkup } from 'react-dom/server'
3
3
  import { when } from 'mobx'
4
4
  import { getParent } from 'mobx-state-tree'
5
5
  import { getConf, readConfObject } from '@jbrowse/core/configuration'
6
- import { getSession } from '@jbrowse/core/util'
6
+ import { getSession, getBpDisplayStr } from '@jbrowse/core/util'
7
7
  import { AnyConfigurationModel } from '@jbrowse/core/configuration/configurationSchema'
8
8
  import Base1DView from '@jbrowse/core/util/Base1DViewModel'
9
9
 
@@ -18,18 +18,6 @@ import { Polygon, Cytobands } from './OverviewScaleBar'
18
18
 
19
19
  type LGV = LinearGenomeViewModel
20
20
 
21
- function getBpDisplayStr(totalBp: number) {
22
- let displayBp
23
- if (Math.floor(totalBp / 1000000) > 0) {
24
- displayBp = `${parseFloat((totalBp / 1000000).toPrecision(3))}Mbp`
25
- } else if (Math.floor(totalBp / 1000) > 0) {
26
- displayBp = `${parseFloat((totalBp / 1000).toPrecision(3))}Kbp`
27
- } else {
28
- displayBp = `${Math.floor(totalBp)}bp`
29
- }
30
- return displayBp
31
- }
32
-
33
21
  function ScaleBar({ model, fontSize }: { model: LGV; fontSize: number }) {
34
22
  const {
35
23
  offsetPx,
@@ -181,7 +181,7 @@ const Cytobands = observer(
181
181
  assembly?: Assembly
182
182
  block: ContentBlock
183
183
  }) => {
184
- const { offsetPx } = block
184
+ const { offsetPx, reversed } = block
185
185
  const cytobands = assembly?.cytobands
186
186
  ?.map(f => ({
187
187
  refName: assembly.getCanonicalRefName(f.get('refName')),
@@ -205,6 +205,10 @@ const Cytobands = observer(
205
205
  ]
206
206
  })
207
207
 
208
+ const arr = cytobands || []
209
+ const lcap = reversed ? arr.length - 1 : 0
210
+ const rcap = reversed ? 0 : arr.length - 1
211
+
208
212
  let firstCent = true
209
213
  return cytobands ? (
210
214
  <g transform={`translate(-${offsetPx})`}>
@@ -238,7 +242,7 @@ const Cytobands = observer(
238
242
  )
239
243
  }
240
244
 
241
- if (index === 0) {
245
+ if (lcap === index) {
242
246
  return (
243
247
  <path
244
248
  key={key}
@@ -252,7 +256,7 @@ const Cytobands = observer(
252
256
  fill={colorMap[type]}
253
257
  />
254
258
  )
255
- } else if (index === cytobands.length - 1) {
259
+ } else if (rcap === index) {
256
260
  return (
257
261
  <path
258
262
  key={key}
@@ -4,7 +4,7 @@ import { isAlive } from 'mobx-state-tree'
4
4
  import { BaseTrackModel } from '@jbrowse/core/pluggableElementTypes/models'
5
5
  import { getConf } from '@jbrowse/core/configuration'
6
6
  import { ResizeHandle } from '@jbrowse/core/ui'
7
- import { useDebouncedCallback, getContainingView } from '@jbrowse/core/util'
7
+ import { useDebouncedCallback } from '@jbrowse/core/util'
8
8
  import clsx from 'clsx'
9
9
  import Paper from '@material-ui/core/Paper'
10
10
  import { makeStyles } from '@material-ui/core/styles'
@@ -13,7 +13,9 @@ import { LinearGenomeViewModel, RESIZE_HANDLE_HEIGHT } from '..'
13
13
  import TrackLabel from './TrackLabel'
14
14
 
15
15
  const useStyles = makeStyles(theme => ({
16
- root: {},
16
+ root: {
17
+ margin: 2,
18
+ },
17
19
  resizeHandle: {
18
20
  height: RESIZE_HANDLE_HEIGHT,
19
21
  boxSizing: 'border-box',
@@ -29,16 +31,8 @@ const useStyles = makeStyles(theme => ({
29
31
  zIndex: 3,
30
32
  borderRadius: theme.shape.borderRadius,
31
33
  },
32
- renderingComponentContainer: {
33
- position: 'absolute',
34
- // -1 offset because of the 1px border of the Paper
35
- left: -1,
36
- height: '100%',
37
- width: '100%',
38
- },
39
34
  trackLabel: {
40
35
  zIndex: 3,
41
- margin: theme.spacing(1),
42
36
  },
43
37
  trackLabelInline: {
44
38
  position: 'relative',
@@ -60,16 +54,37 @@ const useStyles = makeStyles(theme => ({
60
54
 
61
55
  type LGV = LinearGenomeViewModel
62
56
 
63
- function TrackContainer(props: {
57
+ function TrackContainerLabel({
58
+ model,
59
+ view,
60
+ }: {
61
+ model: BaseTrackModel
62
+ view: LGV
63
+ }) {
64
+ const classes = useStyles()
65
+ const labelStyle =
66
+ view.trackLabels === 'overlapping'
67
+ ? classes.trackLabelOverlap
68
+ : classes.trackLabelInline
69
+ return view.trackLabels !== 'hidden' ? (
70
+ <TrackLabel
71
+ track={model}
72
+ className={clsx(classes.trackLabel, labelStyle)}
73
+ />
74
+ ) : null
75
+ }
76
+
77
+ function TrackContainer({
78
+ model,
79
+ track,
80
+ }: {
64
81
  model: LinearGenomeViewModel
65
82
  track: BaseTrackModel
66
83
  }) {
67
84
  const classes = useStyles()
68
- const { model, track } = props
69
85
  const display = track.displays[0]
70
86
  const { horizontalScroll, draggingTrackId, moveTrack } = model
71
87
  const { height } = display
72
- const view = getContainingView(display) as LGV
73
88
  const trackId = getConf(track, 'trackId')
74
89
  const ref = useRef(null)
75
90
 
@@ -95,21 +110,9 @@ function TrackContainer(props: {
95
110
  const dimmed = draggingTrackId !== undefined && draggingTrackId !== display.id
96
111
 
97
112
  return (
98
- <div className={classes.root}>
99
- {view.trackLabels !== 'hidden' ? (
100
- <TrackLabel
101
- track={track}
102
- className={clsx(
103
- classes.trackLabel,
104
- view.trackLabels === 'overlapping'
105
- ? classes.trackLabelOverlap
106
- : classes.trackLabelInline,
107
- )}
108
- />
109
- ) : null}
110
-
111
- <Paper
112
- variant="outlined"
113
+ <Paper className={classes.root} variant="outlined">
114
+ <TrackContainerLabel model={track} view={model} />
115
+ <div
113
116
  className={classes.trackRenderingContainer}
114
117
  style={{ height }}
115
118
  onScroll={event => {
@@ -117,17 +120,12 @@ function TrackContainer(props: {
117
120
  display.setScrollTop(target.scrollTop)
118
121
  }}
119
122
  onDragEnter={debouncedOnDragEnter}
120
- data-testid={`trackRenderingContainer-${view.id}-${trackId}`}
123
+ data-testid={`trackRenderingContainer-${model.id}-${trackId}`}
121
124
  role="presentation"
122
125
  >
123
- <div
124
- ref={ref}
125
- className={classes.renderingComponentContainer}
126
- style={{ transform: `scaleX(${model.scaleFactor})` }}
127
- >
126
+ <div ref={ref} style={{ transform: `scaleX(${model.scaleFactor})` }}>
128
127
  <RenderingComponent
129
128
  model={display}
130
- blockState={{}}
131
129
  onHorizontalScroll={horizontalScroll}
132
130
  />
133
131
  </div>
@@ -140,11 +138,10 @@ function TrackContainer(props: {
140
138
  top: display.height - 20,
141
139
  }}
142
140
  >
143
- {' '}
144
141
  <DisplayBlurb model={display} />
145
142
  </div>
146
143
  ) : null}
147
- </Paper>
144
+ </div>
148
145
  <div
149
146
  className={classes.overlay}
150
147
  style={{
@@ -157,7 +154,7 @@ function TrackContainer(props: {
157
154
  onDrag={display.resizeHeight}
158
155
  className={classes.resizeHandle}
159
156
  />
160
- </div>
157
+ </Paper>
161
158
  )
162
159
  }
163
160
 
@@ -102,7 +102,10 @@ const TrackLabel = React.forwardRef(
102
102
  handleClose()
103
103
  }
104
104
 
105
- const items = track.trackMenuItems()
105
+ const items = [
106
+ ...session.getTrackActionMenuItems?.(trackConf),
107
+ ...track.trackMenuItems(),
108
+ ].sort((a, b) => (b.priority || 0) - (a.priority || 0))
106
109
 
107
110
  return (
108
111
  <>
@@ -148,10 +151,7 @@ const TrackLabel = React.forwardRef(
148
151
  onMenuItemClick={handleMenuItemClick}
149
152
  open={Boolean(anchorEl)}
150
153
  onClose={handleClose}
151
- menuItems={[
152
- ...session.getTrackActionMenuItems?.(trackConf),
153
- ...items,
154
- ].sort((a, b) => (b.priority || 0) - (a.priority || 0))}
154
+ menuItems={items}
155
155
  />
156
156
  </>
157
157
  )
@@ -185,7 +185,6 @@ function TracksContainer({
185
185
  />
186
186
  }
187
187
  />
188
- <div className={classes.spacer} />
189
188
  {children}
190
189
  </div>
191
190
  )
@@ -449,10 +449,7 @@ exports[`<LinearGenomeView /> renders one track, one region 1`] = `
449
449
  </div>
450
450
  </div>
451
451
  <div
452
- class="makeStyles-spacer"
453
- />
454
- <div
455
- class="makeStyles-root"
452
+ class="MuiPaper-root makeStyles-root MuiPaper-outlined MuiPaper-rounded"
456
453
  >
457
454
  <div
458
455
  class="MuiPaper-root makeStyles-trackLabel makeStyles-trackLabelOverlap makeStyles-root MuiPaper-elevation1 MuiPaper-rounded"
@@ -505,10 +502,9 @@ exports[`<LinearGenomeView /> renders one track, one region 1`] = `
505
502
  <button
506
503
  aria-controls="simple-menu"
507
504
  aria-haspopup="true"
508
- class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary MuiIconButton-disabled MuiButtonBase-disabled"
505
+ class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary"
509
506
  data-testid="track_menu_icon"
510
- disabled=""
511
- tabindex="-1"
507
+ tabindex="0"
512
508
  type="button"
513
509
  >
514
510
  <span
@@ -525,16 +521,18 @@ exports[`<LinearGenomeView /> renders one track, one region 1`] = `
525
521
  />
526
522
  </svg>
527
523
  </span>
524
+ <span
525
+ class="MuiTouchRipple-root"
526
+ />
528
527
  </button>
529
528
  </div>
530
529
  <div
531
- class="MuiPaper-root makeStyles-trackRenderingContainer MuiPaper-outlined MuiPaper-rounded"
530
+ class="makeStyles-trackRenderingContainer"
532
531
  data-testid="trackRenderingContainer-lgv-testConfig"
533
532
  role="presentation"
534
533
  style="height: 100px;"
535
534
  >
536
535
  <div
537
- class="makeStyles-renderingComponentContainer"
538
536
  style="transform: scaleX(1);"
539
537
  >
540
538
  <div
@@ -768,7 +766,7 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
768
766
  class="MuiAutocomplete-root"
769
767
  data-testid="autocomplete"
770
768
  role="combobox"
771
- style="width: 255.22500000000002px;"
769
+ style="width: 255.27500000000003px;"
772
770
  >
773
771
  <div
774
772
  class="MuiFormControl-root MuiTextField-root makeStyles-headerRefName MuiFormControl-fullWidth"
@@ -788,7 +786,7 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
788
786
  placeholder="Search for location"
789
787
  spellcheck="false"
790
788
  type="text"
791
- value="ctgA:1..100;ctgB:1,001..1,698"
789
+ value="ctgA:1..100 ctgB:1,001..1,698"
792
790
  />
793
791
  <div
794
792
  class="MuiInputAdornment-root MuiInputAdornment-positionEnd"
@@ -1341,10 +1339,7 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
1341
1339
  </div>
1342
1340
  </div>
1343
1341
  <div
1344
- class="makeStyles-spacer"
1345
- />
1346
- <div
1347
- class="makeStyles-root"
1342
+ class="MuiPaper-root makeStyles-root MuiPaper-outlined MuiPaper-rounded"
1348
1343
  >
1349
1344
  <div
1350
1345
  class="MuiPaper-root makeStyles-trackLabel makeStyles-trackLabelOverlap makeStyles-root MuiPaper-elevation1 MuiPaper-rounded"
@@ -1397,10 +1392,9 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
1397
1392
  <button
1398
1393
  aria-controls="simple-menu"
1399
1394
  aria-haspopup="true"
1400
- class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary MuiIconButton-disabled MuiButtonBase-disabled"
1395
+ class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary"
1401
1396
  data-testid="track_menu_icon"
1402
- disabled=""
1403
- tabindex="-1"
1397
+ tabindex="0"
1404
1398
  type="button"
1405
1399
  >
1406
1400
  <span
@@ -1417,16 +1411,18 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
1417
1411
  />
1418
1412
  </svg>
1419
1413
  </span>
1414
+ <span
1415
+ class="MuiTouchRipple-root"
1416
+ />
1420
1417
  </button>
1421
1418
  </div>
1422
1419
  <div
1423
- class="MuiPaper-root makeStyles-trackRenderingContainer MuiPaper-outlined MuiPaper-rounded"
1420
+ class="makeStyles-trackRenderingContainer"
1424
1421
  data-testid="trackRenderingContainer-lgv-testConfig"
1425
1422
  role="presentation"
1426
1423
  style="height: 100px;"
1427
1424
  >
1428
1425
  <div
1429
- class="makeStyles-renderingComponentContainer"
1430
1426
  style="transform: scaleX(1);"
1431
1427
  >
1432
1428
  <div
@@ -1498,7 +1494,7 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
1498
1494
  />
1499
1495
  </div>
1500
1496
  <div
1501
- class="makeStyles-root"
1497
+ class="MuiPaper-root makeStyles-root MuiPaper-outlined MuiPaper-rounded"
1502
1498
  >
1503
1499
  <div
1504
1500
  class="MuiPaper-root makeStyles-trackLabel makeStyles-trackLabelOverlap makeStyles-root MuiPaper-elevation1 MuiPaper-rounded"
@@ -1551,10 +1547,9 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
1551
1547
  <button
1552
1548
  aria-controls="simple-menu"
1553
1549
  aria-haspopup="true"
1554
- class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary MuiIconButton-disabled MuiButtonBase-disabled"
1550
+ class="MuiButtonBase-root MuiIconButton-root makeStyles-iconButton MuiIconButton-colorSecondary"
1555
1551
  data-testid="track_menu_icon"
1556
- disabled=""
1557
- tabindex="-1"
1552
+ tabindex="0"
1558
1553
  type="button"
1559
1554
  >
1560
1555
  <span
@@ -1571,16 +1566,18 @@ exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
1571
1566
  />
1572
1567
  </svg>
1573
1568
  </span>
1569
+ <span
1570
+ class="MuiTouchRipple-root"
1571
+ />
1574
1572
  </button>
1575
1573
  </div>
1576
1574
  <div
1577
- class="MuiPaper-root makeStyles-trackRenderingContainer MuiPaper-outlined MuiPaper-rounded"
1575
+ class="makeStyles-trackRenderingContainer"
1578
1576
  data-testid="trackRenderingContainer-lgv-testConfig2"
1579
1577
  role="presentation"
1580
1578
  style="height: 100px;"
1581
1579
  >
1582
1580
  <div
1583
- class="makeStyles-renderingComponentContainer"
1584
1581
  style="transform: scaleX(1);"
1585
1582
  >
1586
1583
  <div
@@ -11,6 +11,7 @@ import { LinearGenomeViewStateModel, stateModelFactory } from '.'
11
11
  import { BaseLinearDisplayComponent } from '..'
12
12
  import { stateModelFactory as LinearBasicDisplayStateModelFactory } from '../LinearBareDisplay'
13
13
  import hg38DisplayedRegions from './hg38DisplayedRegions.json'
14
+ import volvoxDisplayedRegions from './volvoxDisplayedRegions.json'
14
15
 
15
16
  // use initializer function to avoid having console.warn jest.fn in a global
16
17
  function initialize() {
@@ -54,22 +55,7 @@ function initialize() {
54
55
  const Assembly = types
55
56
  .model({})
56
57
  .volatile(() => ({
57
- regions: [
58
- {
59
- assemblyName: 'volvox',
60
- start: 0,
61
- end: 50001,
62
- refName: 'ctgA',
63
- reversed: false,
64
- },
65
- {
66
- assemblyName: 'volvox',
67
- start: 0,
68
- end: 6079,
69
- refName: 'ctgB',
70
- reversed: false,
71
- },
72
- ],
58
+ regions: volvoxDisplayedRegions,
73
59
  }))
74
60
  .views(() => ({
75
61
  getCanonicalRefName(refName: string) {
@@ -79,6 +65,19 @@ function initialize() {
79
65
  return refName
80
66
  },
81
67
  }))
68
+
69
+ const AssemblyManager = types
70
+ .model({
71
+ assemblies: types.map(Assembly),
72
+ })
73
+ .actions(self => ({
74
+ isValidRefName(str: string) {
75
+ return !str.includes(':')
76
+ },
77
+ get(str: string) {
78
+ return self.assemblies.get(str)
79
+ },
80
+ }))
82
81
  const LinearGenomeModel = stateModelFactory(stubManager)
83
82
  const Session = types
84
83
  .model({
@@ -86,6 +85,13 @@ function initialize() {
86
85
  rpcManager: 'rpcManagerExists',
87
86
  view: types.maybe(LinearGenomeModel),
88
87
  configuration: types.map(types.string),
88
+ assemblyManager: types.optional(AssemblyManager, {
89
+ assemblies: {
90
+ volvox: {
91
+ regions: volvoxDisplayedRegions,
92
+ },
93
+ },
94
+ }),
89
95
  })
90
96
  .actions(self => ({
91
97
  setView(view: Instance<LinearGenomeViewStateModel>) {
@@ -93,9 +99,6 @@ function initialize() {
93
99
  return view
94
100
  },
95
101
  }))
96
- .volatile((/* self */) => ({
97
- assemblyManager: new Map([['volvox', Assembly.create({})]]),
98
- }))
99
102
 
100
103
  return { Session, LinearGenomeModel, Assembly }
101
104
  }
@@ -294,29 +297,6 @@ test('can navToMultiple', () => {
294
297
  ])
295
298
  expect(model.offsetPx).toBe(2799)
296
299
  expect(model.bpPerPx).toBeCloseTo(12.531)
297
-
298
- expect(() =>
299
- model.navToMultiple([
300
- { refName: 'ctgB', start: 5000, end: 10000 },
301
- { refName: 'ctgC', start: 5000, end: 10000 },
302
- ]),
303
- ).toThrow('Start of region ctgC:5,001..10,000 should be 1, but it is not')
304
-
305
- expect(() =>
306
- model.navToMultiple([
307
- { refName: 'ctgB', start: 0, end: 5000 },
308
- { refName: 'ctgC', start: 0, end: 5000 },
309
- ]),
310
- ).toThrow('End of region ctgB:1..5,000 should be 10,000, but it is not')
311
-
312
- expect(() =>
313
- model.navToMultiple([
314
- { refName: 'ctgA', start: 5000, end: 10000 },
315
- { refName: 'ctgA', start: 0, end: 5000 },
316
- ]),
317
- ).toThrow(
318
- 'Entered location ctgA:1..5,000 does not match with displayed regions',
319
- )
320
300
  })
321
301
 
322
302
  describe('Zoom to selected displayed regions', () => {
@@ -992,3 +972,25 @@ test('navToLocString with human assembly', () => {
992
972
  expect(model.view.offsetPx).toBe(9914777550)
993
973
  model.view.navToLocString('chr3:-1,100,000,000..-1,000,000,000')
994
974
  })
975
+
976
+ test('multi region', () => {
977
+ const { Session, LinearGenomeModel } = initialize()
978
+ const model = Session.create({
979
+ configuration: {},
980
+ }).setView(
981
+ LinearGenomeModel.create({
982
+ type: 'LinearGenomeView',
983
+ tracks: [{ name: 'foo track', type: 'BasicTrack' }],
984
+ }),
985
+ )
986
+ model.setWidth(800)
987
+ model.setDisplayedRegions(volvoxDisplayedRegions.slice(0, 1))
988
+
989
+ model.navToLocString('ctgA ctgB')
990
+ expect(model.displayedRegions[0].refName).toBe('ctgA')
991
+ expect(model.displayedRegions[1].refName).toBe('ctgB')
992
+ // [
993
+ // { refName: 'ctgA', start: 0, end: 50001 },
994
+ // { refName: 'ctgB', start: 0, end: 6079 },
995
+ // ])
996
+ })