@jbrowse/plugin-circular-view 1.5.8 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-circular-view",
3
- "version": "1.5.8",
3
+ "version": "1.6.3",
4
4
  "description": "JBrowse 2 circular view",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -49,5 +49,5 @@
49
49
  "publishConfig": {
50
50
  "access": "public"
51
51
  },
52
- "gitHead": "f16afc382629a4a830f9040410a9ff1a3a328918"
52
+ "gitHead": "c6d6783d3dc82ea96390ab177ceb8ed38b439333"
53
53
  }
@@ -1,6 +1,11 @@
1
1
  import React from 'react'
2
2
  import { observer } from 'mobx-react'
3
+ import { ResizeHandle, ErrorMessage } from '@jbrowse/core/ui'
4
+ import { assembleLocString } from '@jbrowse/core/util'
5
+ import { IconButton, makeStyles } from '@material-ui/core'
6
+ import { grey } from '@material-ui/core/colors'
3
7
 
8
+ // icons
4
9
  import ZoomOut from '@material-ui/icons/ZoomOut'
5
10
  import ZoomIn from '@material-ui/icons/ZoomIn'
6
11
  import RotateLeft from '@material-ui/icons/RotateLeft'
@@ -9,84 +14,70 @@ import LockOutline from '@material-ui/icons/LockOutlined'
9
14
  import LockOpen from '@material-ui/icons/LockOpen'
10
15
  import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons'
11
16
 
12
- // material-ui stuff
13
- import { IconButton, makeStyles } from '@material-ui/core'
14
-
15
- import { grey } from '@material-ui/core/colors'
16
-
17
- import { ResizeHandle } from '@jbrowse/core/ui'
18
- import { assembleLocString } from '@jbrowse/core/util'
17
+ // locals
19
18
  import Ruler from './Ruler'
20
19
  import ImportForm from './ImportForm'
21
20
 
22
21
  const dragHandleHeight = 3
23
22
 
24
- const useStyles = makeStyles(theme => {
25
- return {
26
- root: {
27
- position: 'relative',
28
- marginBottom: theme.spacing(1),
29
- overflow: 'hidden',
30
- background: 'white',
31
- },
32
- scroller: {
33
- overflow: 'auto',
34
- },
35
- sliceRoot: {
36
- background: 'none',
37
- // background: theme.palette.background.paper,
38
- boxSizing: 'content-box',
39
- display: 'block',
40
- },
41
- iconButton: {
42
- padding: '4px',
43
- margin: '0 2px 0 2px',
44
- },
45
- controls: {
46
- overflow: 'hidden',
47
- whiteSpace: 'nowrap',
48
- position: 'absolute',
49
- background: grey[200],
50
- boxSizing: 'border-box',
51
- borderRight: '1px solid #a2a2a2',
52
- borderBottom: '1px solid #a2a2a2',
53
- left: 0,
54
- top: 0,
55
- },
56
- importFormContainer: {
57
- marginBottom: theme.spacing(4),
58
- },
59
- }
60
- })
23
+ const useStyles = makeStyles(theme => ({
24
+ root: {
25
+ position: 'relative',
26
+ marginBottom: theme.spacing(1),
27
+ overflow: 'hidden',
28
+ background: 'white',
29
+ },
30
+ scroller: {
31
+ overflow: 'auto',
32
+ },
33
+ sliceRoot: {
34
+ background: 'none',
35
+ // background: theme.palette.background.paper,
36
+ boxSizing: 'content-box',
37
+ display: 'block',
38
+ },
39
+ iconButton: {
40
+ padding: '4px',
41
+ margin: '0 2px 0 2px',
42
+ },
43
+ controls: {
44
+ overflow: 'hidden',
45
+ whiteSpace: 'nowrap',
46
+ position: 'absolute',
47
+ background: grey[200],
48
+ boxSizing: 'border-box',
49
+ borderRight: '1px solid #a2a2a2',
50
+ borderBottom: '1px solid #a2a2a2',
51
+ left: 0,
52
+ top: 0,
53
+ },
54
+ importFormContainer: {
55
+ marginBottom: theme.spacing(4),
56
+ },
57
+ }))
61
58
 
62
59
  const Slices = observer(({ model }) => {
63
60
  return (
64
61
  <>
65
- <>
66
- {model.staticSlices.map(slice => {
67
- return (
68
- <Ruler
69
- key={assembleLocString(
70
- slice.region.elided ? slice.region.regions[0] : slice.region,
71
- )}
72
- model={model}
73
- slice={slice}
74
- />
75
- )
76
- })}
77
- </>
78
- <>
79
- {model.tracks.map(track => {
80
- const display = track.displays[0]
81
- return (
82
- <display.RenderingComponent
83
- key={display.id}
84
- display={display}
85
- view={model}
86
- />
87
- )
88
- })}
89
- </>
62
+ {model.staticSlices.map(slice => (
63
+ <Ruler
64
+ key={assembleLocString(
65
+ slice.region.elided ? slice.region.regions[0] : slice.region,
66
+ )}
67
+ model={model}
68
+ slice={slice}
69
+ />
70
+ ))}
71
+ {model.tracks.map(track => {
72
+ const display = track.displays[0]
73
+ return (
74
+ <display.RenderingComponent
75
+ key={display.id}
76
+ display={display}
77
+ view={model}
78
+ />
79
+ )
80
+ })}
90
81
  </>
91
82
  )
92
83
  })
@@ -183,7 +174,7 @@ const CircularView = observer(({ model }) => {
183
174
  data-testid={model.id}
184
175
  >
185
176
  {model.error ? (
186
- <p style={{ color: 'red' }}>{model.error.message}</p>
177
+ <ErrorMessage error={model.error} />
187
178
  ) : (
188
179
  <>
189
180
  {showImportForm ? <ImportForm model={model} /> : null}
@@ -1,15 +1,8 @@
1
1
  import React, { useState } from 'react'
2
+ import { Button, Container, Grid, makeStyles } from '@material-ui/core'
2
3
  import { observer } from 'mobx-react'
3
4
  import { getSession } from '@jbrowse/core/util'
4
-
5
- // material-ui stuff
6
- import {
7
- Button,
8
- Container,
9
- Grid,
10
- Typography,
11
- makeStyles,
12
- } from '@material-ui/core'
5
+ import ErrorMessage from '@jbrowse/core/ui/ErrorMessage'
13
6
  import AssemblySelector from '@jbrowse/core/ui/AssemblySelector'
14
7
 
15
8
  const useStyles = makeStyles(theme => ({
@@ -18,14 +11,6 @@ const useStyles = makeStyles(theme => ({
18
11
  },
19
12
  }))
20
13
 
21
- const ErrorDisplay = observer(({ error }: { error?: Error | string }) => {
22
- return (
23
- <Typography variant="h6" color="error">
24
- {`${error}`}
25
- </Typography>
26
- )
27
- })
28
-
29
14
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
15
  const ImportForm = observer(({ model }: { model: any }) => {
31
16
  const classes = useStyles()
@@ -42,45 +27,38 @@ const ImportForm = observer(({ model }: { model: any }) => {
42
27
  const err = assemblyError || error
43
28
 
44
29
  return (
45
- <>
46
- <Container className={classes.importFormContainer}>
47
- {err ? (
48
- <Grid
49
- container
50
- spacing={1}
51
- justifyContent="center"
52
- alignItems="center"
53
- >
54
- <Grid item>
55
- <ErrorDisplay error={err} />
56
- </Grid>
57
- </Grid>
58
- ) : null}
30
+ <Container className={classes.importFormContainer}>
31
+ {err ? (
59
32
  <Grid container spacing={1} justifyContent="center" alignItems="center">
60
33
  <Grid item>
61
- <AssemblySelector
62
- onChange={val => {
63
- setError(undefined)
64
- setSelectedAsm(val)
65
- }}
66
- session={session}
67
- selected={selectedAsm}
68
- />
34
+ <ErrorMessage error={err} />
69
35
  </Grid>
36
+ </Grid>
37
+ ) : null}
38
+ <Grid container spacing={1} justifyContent="center" alignItems="center">
39
+ <Grid item>
40
+ <AssemblySelector
41
+ onChange={val => {
42
+ setError(undefined)
43
+ setSelectedAsm(val)
44
+ }}
45
+ session={session}
46
+ selected={selectedAsm}
47
+ />
48
+ </Grid>
70
49
 
71
- <Grid item>
72
- <Button
73
- disabled={!(regions && regions.length)}
74
- onClick={() => model.setDisplayedRegions(regions)}
75
- variant="contained"
76
- color="primary"
77
- >
78
- {regions.length ? 'Open' : 'Loading…'}
79
- </Button>
80
- </Grid>
50
+ <Grid item>
51
+ <Button
52
+ disabled={!regions?.length}
53
+ onClick={() => model.setDisplayedRegions(regions)}
54
+ variant="contained"
55
+ color="primary"
56
+ >
57
+ {regions.length ? 'Open' : 'Loading…'}
58
+ </Button>
81
59
  </Grid>
82
- </Container>
83
- </>
60
+ </Grid>
61
+ </Container>
84
62
  )
85
63
  })
86
64
 
@@ -58,7 +58,7 @@ export default function CircularView(pluginManager: PluginManager) {
58
58
  trackSelectorType: 'hierarchical',
59
59
  })
60
60
  .volatile(() => ({
61
- width: 800,
61
+ width: 0,
62
62
  }))
63
63
  .views(self => ({
64
64
  get staticSlices() {
@@ -203,20 +203,16 @@ export default function CircularView(pluginManager: PluginManager) {
203
203
  // it to be loaded. this is done by looking in the assemblyManager's
204
204
  // assembly list, and then waiting on it's initialized state which is
205
205
  // updated later
206
- const assembliesInitialized = this.assemblyNames.every(
207
- assemblyName => {
208
- if (
209
- assemblyManager.assemblyList
210
- ?.map(asm => asm.name)
211
- .includes(assemblyName)
212
- ) {
213
- return (assemblyManager.get(assemblyName) || {}).initialized
214
- }
215
- return true
216
- },
217
- )
218
-
219
- return assembliesInitialized
206
+ return this.assemblyNames.every(assemblyName => {
207
+ if (
208
+ assemblyManager.assemblyList
209
+ ?.map(asm => asm.name)
210
+ .includes(assemblyName)
211
+ ) {
212
+ return assemblyManager.get(assemblyName)?.initialized
213
+ }
214
+ return true
215
+ })
220
216
  },
221
217
  }))
222
218
  .volatile(() => ({
package/src/index.ts CHANGED
@@ -1,10 +1,15 @@
1
1
  import { lazy } from 'react'
2
+ import { when } from 'mobx'
2
3
  import { AbstractSessionModel, isAbstractMenuManager } from '@jbrowse/core/util'
3
4
  import PluginManager from '@jbrowse/core/PluginManager'
4
5
  import Plugin from '@jbrowse/core/Plugin'
5
6
  import ViewType from '@jbrowse/core/pluggableElementTypes/ViewType'
6
7
  import DataUsageIcon from '@material-ui/icons/DataUsage'
7
- import stateModelFactory from './CircularView/models/CircularView'
8
+ import stateModelFactory, {
9
+ CircularViewModel,
10
+ } from './CircularView/models/CircularView'
11
+
12
+ type CGV = CircularViewModel
8
13
 
9
14
  export default class CircularViewPlugin extends Plugin {
10
15
  name = 'CircularViewPlugin'
@@ -20,6 +25,44 @@ export default class CircularViewPlugin extends Plugin {
20
25
  name: 'CircularView',
21
26
  }),
22
27
  )
28
+
29
+ pluginManager.addToExtensionPoint(
30
+ 'LaunchView-CircularView',
31
+ // @ts-ignore
32
+ async ({
33
+ session,
34
+ assembly,
35
+ loc,
36
+ tracks = [],
37
+ }: {
38
+ session: AbstractSessionModel
39
+ assembly?: string
40
+ loc: string
41
+ tracks?: string[]
42
+ }) => {
43
+ const { assemblyManager } = session
44
+ const view = session.addView('CircularView', {}) as CGV
45
+
46
+ await when(() => view.initialized)
47
+
48
+ if (!assembly) {
49
+ throw new Error(
50
+ 'No assembly provided when launching circular genome view',
51
+ )
52
+ }
53
+
54
+ const asm = await assemblyManager.waitForAssembly(assembly)
55
+ if (!asm) {
56
+ throw new Error(
57
+ `Assembly "${assembly}" not found when launching circular genome view`,
58
+ )
59
+ }
60
+
61
+ view.setDisplayedRegions(asm.regions || [])
62
+
63
+ tracks.forEach(track => view.showTrack(track))
64
+ },
65
+ )
23
66
  }
24
67
 
25
68
  configure(pluginManager: PluginManager) {