react-msaview 3.1.11 → 3.2.0

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 (191) hide show
  1. package/bundle/index.js +32 -31
  2. package/dist/colorSchemes.d.ts +2 -2
  3. package/dist/colorSchemes.js +3 -4
  4. package/dist/colorSchemes.js.map +1 -1
  5. package/dist/components/Loading.d.ts +1 -1
  6. package/dist/components/Loading.js +4 -4
  7. package/dist/components/Loading.js.map +1 -1
  8. package/dist/components/MSAView.d.ts +1 -1
  9. package/dist/components/MSAView.js +13 -9
  10. package/dist/components/MSAView.js.map +1 -1
  11. package/dist/components/ResizeHandles.d.ts +1 -1
  12. package/dist/components/ResizeHandles.js +2 -2
  13. package/dist/components/SequenceTextArea.js +4 -0
  14. package/dist/components/SequenceTextArea.js.map +1 -1
  15. package/dist/components/TextTrack.d.ts +1 -1
  16. package/dist/components/Track.d.ts +1 -1
  17. package/dist/components/VerticalScrollbar.d.ts +6 -0
  18. package/dist/components/VerticalScrollbar.js +65 -0
  19. package/dist/components/VerticalScrollbar.js.map +1 -0
  20. package/dist/components/dialogs/AddTrackDialog.d.ts +1 -1
  21. package/dist/components/dialogs/DomainDialog.d.ts +6 -0
  22. package/dist/components/dialogs/DomainDialog.js +19 -0
  23. package/dist/components/dialogs/DomainDialog.js.map +1 -0
  24. package/dist/components/dialogs/ExportSVGDialog.d.ts +1 -1
  25. package/dist/components/dialogs/FeatureDialog.d.ts +1 -1
  26. package/dist/components/dialogs/FeatureDialog.js.map +1 -1
  27. package/dist/components/dialogs/InterProScanDialog.d.ts +4 -4
  28. package/dist/components/dialogs/InterProScanDialog.js +37 -8
  29. package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
  30. package/dist/components/dialogs/MetadataDialog.d.ts +1 -1
  31. package/dist/components/dialogs/SettingsDialog.d.ts +1 -1
  32. package/dist/components/dialogs/SettingsDialog.js +10 -1
  33. package/dist/components/dialogs/SettingsDialog.js.map +1 -1
  34. package/dist/components/dialogs/TabPanel.d.ts +6 -0
  35. package/dist/components/dialogs/TabPanel.js +6 -0
  36. package/dist/components/dialogs/TabPanel.js.map +1 -0
  37. package/dist/components/dialogs/TracklistDialog.d.ts +1 -1
  38. package/dist/components/dialogs/UserProvidedDomainsDialog.d.ts +7 -0
  39. package/dist/components/dialogs/UserProvidedDomainsDialog.js +58 -0
  40. package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +1 -0
  41. package/dist/components/header/Header.d.ts +1 -1
  42. package/dist/components/header/Header.js +8 -5
  43. package/dist/components/header/Header.js.map +1 -1
  44. package/dist/components/header/HeaderInfoArea.d.ts +1 -1
  45. package/dist/components/header/HeaderMenu.d.ts +1 -1
  46. package/dist/components/header/HeaderMenuExtra.d.ts +1 -1
  47. package/dist/components/header/HeaderMenuExtra.js +54 -41
  48. package/dist/components/header/HeaderMenuExtra.js.map +1 -1
  49. package/dist/components/header/HeaderStatusArea.d.ts +1 -1
  50. package/dist/components/header/HeaderStatusArea.js +2 -1
  51. package/dist/components/header/HeaderStatusArea.js.map +1 -1
  52. package/dist/components/header/MultiAlignmentSelector.d.ts +1 -1
  53. package/dist/components/header/ZoomControls.js +31 -1
  54. package/dist/components/header/ZoomControls.js.map +1 -1
  55. package/dist/components/import/ImportForm.d.ts +1 -1
  56. package/dist/components/import/ImportForm.js +1 -1
  57. package/dist/components/import/ImportForm.js.map +1 -1
  58. package/dist/components/import/ImportFormExamples.d.ts +1 -1
  59. package/dist/components/import/ImportFormExamples.js +10 -8
  60. package/dist/components/import/ImportFormExamples.js.map +1 -1
  61. package/dist/components/import/util.d.ts +2 -2
  62. package/dist/components/minimap/Minimap.d.ts +1 -1
  63. package/dist/components/minimap/Minimap.js +14 -15
  64. package/dist/components/minimap/Minimap.js.map +1 -1
  65. package/dist/components/minimap/MinimapSVG.d.ts +1 -1
  66. package/dist/components/minimap/MinimapSVG.js +1 -1
  67. package/dist/components/minimap/MinimapSVG.js.map +1 -1
  68. package/dist/components/msa/MSACanvas.d.ts +1 -1
  69. package/dist/components/msa/MSACanvas.js +3 -3
  70. package/dist/components/msa/MSACanvas.js.map +1 -1
  71. package/dist/components/msa/MSACanvasBlock.d.ts +3 -3
  72. package/dist/components/msa/MSACanvasBlock.js +4 -3
  73. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  74. package/dist/components/msa/MSAMouseoverCanvas.d.ts +2 -2
  75. package/dist/components/msa/MSAMouseoverCanvas.js +1 -1
  76. package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
  77. package/dist/components/msa/MSAPanel.d.ts +1 -1
  78. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +1 -1
  79. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +2 -3
  80. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  81. package/dist/components/msa/renderMSABlock.d.ts +2 -2
  82. package/dist/components/msa/renderMSABlock.js +12 -12
  83. package/dist/components/msa/renderMSABlock.js.map +1 -1
  84. package/dist/components/msa/renderMSAMouseover.d.ts +1 -1
  85. package/dist/components/tree/TreeBranchMenu.d.ts +1 -1
  86. package/dist/components/tree/TreeCanvas.d.ts +1 -1
  87. package/dist/components/tree/TreeCanvas.js +13 -12
  88. package/dist/components/tree/TreeCanvas.js.map +1 -1
  89. package/dist/components/tree/TreeCanvasBlock.d.ts +1 -1
  90. package/dist/components/tree/TreeCanvasBlock.js +2 -1
  91. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  92. package/dist/components/tree/TreeNodeMenu.d.ts +1 -1
  93. package/dist/components/tree/TreeNodeMenu.js +2 -2
  94. package/dist/components/tree/TreeNodeMenu.js.map +1 -1
  95. package/dist/components/tree/TreePanel.d.ts +1 -1
  96. package/dist/components/tree/TreeRuler.d.ts +1 -1
  97. package/dist/components/tree/dialogs/TreeNodeInfoDialog.d.ts +1 -1
  98. package/dist/components/tree/renderTreeCanvas.d.ts +3 -3
  99. package/dist/components/tree/renderTreeCanvas.js +25 -9
  100. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  101. package/dist/components/util.js +1 -1
  102. package/dist/components/util.js.map +1 -1
  103. package/dist/fetchUtils.d.ts +1 -1
  104. package/dist/fetchUtils.js.map +1 -1
  105. package/dist/launchInterProScan.d.ts +9 -3
  106. package/dist/launchInterProScan.js +57 -22
  107. package/dist/launchInterProScan.js.map +1 -1
  108. package/dist/model/DataModel.d.ts +5 -1
  109. package/dist/model/DataModel.js +10 -1
  110. package/dist/model/DataModel.js.map +1 -1
  111. package/dist/model/DialogQueue.d.ts +1 -1
  112. package/dist/model.d.ts +138 -43
  113. package/dist/model.js +235 -110
  114. package/dist/model.js.map +1 -1
  115. package/dist/parseNewick.js +1 -1
  116. package/dist/parseNewick.js.map +1 -1
  117. package/dist/parsers/ClustalMSA.d.ts +1 -1
  118. package/dist/parsers/FastaMSA.d.ts +1 -1
  119. package/dist/parsers/StockholmMSA.d.ts +1 -1
  120. package/dist/parsers/StockholmMSA.js.map +1 -1
  121. package/dist/renderToSvg.d.ts +2 -2
  122. package/dist/renderToSvg.js +3 -28
  123. package/dist/renderToSvg.js.map +1 -1
  124. package/dist/reparseTree.d.ts +1 -1
  125. package/dist/util.d.ts +2 -2
  126. package/dist/util.js +0 -2
  127. package/dist/util.js.map +1 -1
  128. package/dist/version.d.ts +1 -1
  129. package/dist/version.js +1 -1
  130. package/dist/version.js.map +1 -1
  131. package/package.json +5 -2
  132. package/src/colorSchemes.ts +3 -2
  133. package/src/components/Checkbox2.tsx +1 -1
  134. package/src/components/Loading.tsx +11 -5
  135. package/src/components/MSAView.tsx +27 -18
  136. package/src/components/ResizeHandles.tsx +3 -3
  137. package/src/components/SequenceTextArea.tsx +8 -0
  138. package/src/components/TextTrack.tsx +1 -1
  139. package/src/components/Track.tsx +1 -1
  140. package/src/components/VerticalScrollbar.tsx +85 -0
  141. package/src/components/dialogs/AddTrackDialog.tsx +2 -2
  142. package/src/components/dialogs/DomainDialog.tsx +38 -0
  143. package/src/components/dialogs/ExportSVGDialog.tsx +1 -1
  144. package/src/components/dialogs/FeatureDialog.tsx +3 -3
  145. package/src/components/dialogs/InterProScanDialog.tsx +49 -11
  146. package/src/components/dialogs/MetadataDialog.tsx +1 -1
  147. package/src/components/dialogs/SettingsDialog.tsx +38 -3
  148. package/src/components/dialogs/TabPanel.tsx +19 -0
  149. package/src/components/dialogs/TracklistDialog.tsx +1 -1
  150. package/src/components/dialogs/UserProvidedDomainsDialog.tsx +133 -0
  151. package/src/components/header/Header.tsx +9 -6
  152. package/src/components/header/HeaderInfoArea.tsx +1 -1
  153. package/src/components/header/HeaderMenu.tsx +1 -1
  154. package/src/components/header/HeaderMenuExtra.tsx +65 -48
  155. package/src/components/header/HeaderStatusArea.tsx +3 -2
  156. package/src/components/header/MultiAlignmentSelector.tsx +1 -1
  157. package/src/components/header/ZoomControls.tsx +34 -0
  158. package/src/components/import/ImportForm.tsx +3 -3
  159. package/src/components/import/ImportFormExamples.tsx +19 -17
  160. package/src/components/import/util.ts +2 -2
  161. package/src/components/minimap/Minimap.tsx +15 -22
  162. package/src/components/minimap/MinimapSVG.tsx +2 -2
  163. package/src/components/msa/MSACanvas.tsx +11 -4
  164. package/src/components/msa/MSACanvasBlock.tsx +5 -4
  165. package/src/components/msa/MSAMouseoverCanvas.tsx +2 -6
  166. package/src/components/msa/MSAPanel.tsx +1 -1
  167. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +5 -6
  168. package/src/components/msa/renderMSABlock.ts +37 -17
  169. package/src/components/msa/renderMSAMouseover.ts +1 -1
  170. package/src/components/tree/TreeBranchMenu.tsx +1 -1
  171. package/src/components/tree/TreeCanvas.tsx +15 -16
  172. package/src/components/tree/TreeCanvasBlock.tsx +3 -2
  173. package/src/components/tree/TreeNodeMenu.tsx +3 -3
  174. package/src/components/tree/TreePanel.tsx +1 -1
  175. package/src/components/tree/TreeRuler.tsx +1 -1
  176. package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +1 -1
  177. package/src/components/tree/renderTreeCanvas.ts +32 -12
  178. package/src/components/util.ts +1 -1
  179. package/src/fetchUtils.ts +2 -2
  180. package/src/launchInterProScan.ts +69 -24
  181. package/src/model/DataModel.ts +10 -0
  182. package/src/model/DialogQueue.ts +1 -1
  183. package/src/model.ts +262 -143
  184. package/src/parseNewick.ts +1 -1
  185. package/src/parsers/ClustalMSA.ts +1 -1
  186. package/src/parsers/FastaMSA.ts +1 -1
  187. package/src/parsers/StockholmMSA.ts +1 -1
  188. package/src/renderToSvg.tsx +6 -30
  189. package/src/reparseTree.ts +1 -1
  190. package/src/util.ts +2 -4
  191. package/src/version.ts +1 -1
@@ -0,0 +1,85 @@
1
+ import { observer } from 'mobx-react'
2
+ import React, { useEffect, useRef, useState } from 'react'
3
+ import type { MsaViewModel } from '../model'
4
+ import { clamp } from '../util'
5
+
6
+ const VerticalScrollbar = observer(({ model }: { model: MsaViewModel }) => {
7
+ const { msaAreaHeight, scrollY, totalHeight } = model
8
+ const [hovered, setHovered] = useState(false)
9
+ const scheduled = useRef(false)
10
+ const [mouseDown, setMouseDown] = useState<{
11
+ clientY: number
12
+ scrollY: number
13
+ }>()
14
+ const fill = 'rgba(66, 119, 127, 0.3)'
15
+ const unit = msaAreaHeight / totalHeight
16
+ const top = -scrollY
17
+ const bottom = top + msaAreaHeight
18
+ const t = top * unit
19
+ const b = bottom * unit
20
+ useEffect(() => {
21
+ function fn(event: MouseEvent) {
22
+ if (mouseDown !== undefined) {
23
+ if (!scheduled.current) {
24
+ scheduled.current = true
25
+ window.requestAnimationFrame(() => {
26
+ model.setScrollY(
27
+ clamp(
28
+ -totalHeight,
29
+ mouseDown.scrollY - (event.clientY - mouseDown.clientY) / unit,
30
+ 0,
31
+ ),
32
+ )
33
+ scheduled.current = false
34
+ })
35
+ }
36
+ }
37
+ }
38
+ function fn2() {
39
+ setMouseDown(undefined)
40
+ }
41
+ if (mouseDown !== undefined) {
42
+ document.addEventListener('mousemove', fn)
43
+ document.addEventListener('mouseup', fn2)
44
+ return () => {
45
+ document.removeEventListener('mousemove', fn)
46
+ document.removeEventListener('mousemove', fn2)
47
+ }
48
+ }
49
+ }, [model, unit, totalHeight, mouseDown])
50
+ return (
51
+ <div
52
+ style={{
53
+ position: 'relative',
54
+ width: 20,
55
+ height: msaAreaHeight,
56
+ borderLeft: '1px solid #555',
57
+ borderTop: '1px solid #555',
58
+ boxSizing: 'border-box',
59
+ }}
60
+ >
61
+ <div
62
+ style={{
63
+ position: 'absolute',
64
+ top: Math.max(0, t),
65
+ left: 0,
66
+ background: hovered ? 'rgba(66,119,127,0.6)' : fill,
67
+ cursor: 'pointer',
68
+ boxSizing: 'border-box',
69
+ width: 20,
70
+ height: Math.max(b - t, 20),
71
+ zIndex: 100,
72
+ }}
73
+ onMouseOver={() => setHovered(true)}
74
+ onMouseOut={() => setHovered(false)}
75
+ onMouseDown={event => {
76
+ setMouseDown({
77
+ clientY: event.clientY,
78
+ scrollY: model.scrollY,
79
+ })
80
+ }}
81
+ />
82
+ </div>
83
+ )
84
+ })
85
+ export default VerticalScrollbar
@@ -8,9 +8,9 @@ import {
8
8
  Typography,
9
9
  } from '@mui/material'
10
10
  import { Dialog, FileSelector } from '@jbrowse/core/ui'
11
- import { FileLocation } from '@jbrowse/core/util/types'
11
+ import type { FileLocation } from '@jbrowse/core/util/types'
12
12
  import { observer } from 'mobx-react'
13
- import { MsaViewModel } from '../../model'
13
+ import type { MsaViewModel } from '../../model'
14
14
 
15
15
  export default observer(function ({
16
16
  model,
@@ -0,0 +1,38 @@
1
+ import React, { useState } from 'react'
2
+ import { Dialog } from '@jbrowse/core/ui'
3
+ import { Tab, Tabs } from '@mui/material'
4
+
5
+ // locals
6
+ import InterProScanPanel from './InterProScanDialog'
7
+ import UserProvidedResultPanel from './UserProvidedDomainsDialog'
8
+ import TabPanel from './TabPanel'
9
+ import type { MsaViewModel } from '../../model'
10
+
11
+ export default function LaunchDomainViewDialog({
12
+ handleClose,
13
+ model,
14
+ }: {
15
+ handleClose: () => void
16
+ model: MsaViewModel
17
+ }) {
18
+ const [choice, setChoice] = useState(0)
19
+ return (
20
+ <Dialog
21
+ maxWidth="xl"
22
+ title="Launch protein view"
23
+ onClose={() => handleClose()}
24
+ open
25
+ >
26
+ <Tabs value={choice} onChange={(_, val) => setChoice(val)}>
27
+ <Tab value={0} label="Automatic lookup" />
28
+ <Tab value={1} label="Manual" />
29
+ </Tabs>
30
+ <TabPanel value={choice} index={0}>
31
+ <InterProScanPanel model={model} handleClose={handleClose} />
32
+ </TabPanel>
33
+ <TabPanel value={choice} index={1}>
34
+ <UserProvidedResultPanel model={model} handleClose={handleClose} />
35
+ </TabPanel>
36
+ </Dialog>
37
+ )
38
+ }
@@ -13,7 +13,7 @@ import {
13
13
  useTheme,
14
14
  } from '@mui/material'
15
15
  // locals
16
- import { MsaViewModel } from '../../model'
16
+ import type { MsaViewModel } from '../../model'
17
17
  import Checkbox2 from '../Checkbox2'
18
18
 
19
19
  export default function ExportSVGDialog({
@@ -4,7 +4,7 @@ import { Dialog } from '@jbrowse/core/ui'
4
4
  import { Button, DialogContent } from '@mui/material'
5
5
 
6
6
  // locals
7
- import { MsaViewModel } from '../../model'
7
+ import type { MsaViewModel } from '../../model'
8
8
  import { getPalette } from '../../ggplotPalettes'
9
9
 
10
10
  const Toggles = observer(function ({ model }: { model: MsaViewModel }) {
@@ -44,7 +44,7 @@ const Table = observer(function ({ model }: { model: MsaViewModel }) {
44
44
  <table>
45
45
  <thead>
46
46
  <tr>
47
- <td></td>
47
+ <td />
48
48
  <td>accession</td>
49
49
  <td>name</td>
50
50
  <td>description</td>
@@ -75,7 +75,7 @@ const Table = observer(function ({ model }: { model: MsaViewModel }) {
75
75
  height: 20,
76
76
  background: palette[idx] || 'black',
77
77
  }}
78
- ></div>
78
+ />
79
79
  </td>
80
80
  </tr>
81
81
  ))}
@@ -1,16 +1,18 @@
1
1
  import React, { useState } from 'react'
2
2
  import { observer } from 'mobx-react'
3
- import { Dialog } from '@jbrowse/core/ui'
4
3
  import { Button, DialogActions, DialogContent, Typography } from '@mui/material'
5
4
 
6
5
  // locals
7
- import { MsaViewModel } from '../../model'
6
+ import type { MsaViewModel } from '../../model'
7
+ import { getSession } from '@jbrowse/core/util'
8
+ import { launchInterProScan } from '../../launchInterProScan'
9
+ import { Dialog } from '@jbrowse/core/ui'
8
10
 
9
- const FeatureTypeDialog = observer(function ({
10
- onClose,
11
+ const InterProScanDialog = observer(function ({
12
+ handleClose,
11
13
  model,
12
14
  }: {
13
- onClose: () => void
15
+ handleClose: () => void
14
16
  model: MsaViewModel
15
17
  }) {
16
18
  const [vals, setVals] = useState([
@@ -146,10 +148,16 @@ const FeatureTypeDialog = observer(function ({
146
148
  const [show, setShow] = useState(false)
147
149
 
148
150
  return (
149
- <Dialog onClose={() => onClose()} open title="Feature types" maxWidth="xl">
151
+ <Dialog
152
+ maxWidth="xl"
153
+ title="Query InterProScan API for domains"
154
+ onClose={() => handleClose()}
155
+ open
156
+ >
150
157
  <DialogContent>
151
158
  <Typography>
152
- This will run InterProScan on all rows of the current MSA
159
+ This will run InterProScan via the InterProScan API on all rows of the
160
+ current MSA
153
161
  </Typography>
154
162
  <Button onClick={() => setShow(!show)}>
155
163
  {show ? 'Hide' : 'Show'} advanced options
@@ -209,15 +217,45 @@ const FeatureTypeDialog = observer(function ({
209
217
  ) : null}
210
218
  </DialogContent>
211
219
  <DialogActions>
212
- <Button variant="contained" color="secondary" onClick={() => onClose()}>
220
+ <Button
221
+ variant="contained"
222
+ color="secondary"
223
+ onClick={() => handleClose()}
224
+ >
213
225
  Cancel
214
226
  </Button>
215
227
  <Button
216
228
  variant="contained"
217
229
  color="primary"
218
230
  onClick={() => {
219
- model.queryInterProScan(programs).catch(e => model.setError(e))
220
- onClose()
231
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
232
+ ;(async () => {
233
+ try {
234
+ const { rows } = model
235
+ if (rows.length > 140) {
236
+ throw new Error(
237
+ 'Too many sequences, please run InterProScan offline',
238
+ )
239
+ }
240
+ await launchInterProScan({
241
+ algorithm: 'interproscan',
242
+ programs: programs,
243
+ seq: rows
244
+ .map(row => [row[0], row[1].replaceAll('-', '')])
245
+ .filter(f => !!f[1])
246
+ .map(row => `>${row[0]}\n${row[1]}`)
247
+ .join('\n'),
248
+ onProgress: arg => model.setStatus(arg),
249
+ model,
250
+ })
251
+ } catch (e) {
252
+ console.error(e)
253
+ getSession(model).notifyError(`${e}`, e)
254
+ } finally {
255
+ model.setStatus()
256
+ }
257
+ })()
258
+ handleClose()
221
259
  }}
222
260
  >
223
261
  Send sequences to InterProScan
@@ -227,4 +265,4 @@ const FeatureTypeDialog = observer(function ({
227
265
  )
228
266
  })
229
267
 
230
- export default FeatureTypeDialog
268
+ export default InterProScanDialog
@@ -8,7 +8,7 @@ import {
8
8
  } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
9
9
 
10
10
  // locals
11
- import { MsaViewModel } from '../../model'
11
+ import type { MsaViewModel } from '../../model'
12
12
  import SequenceTextArea from '../SequenceTextArea'
13
13
 
14
14
  const MetadataDialog = observer(function ({
@@ -12,7 +12,7 @@ import {
12
12
  Typography,
13
13
  } from '@mui/material'
14
14
 
15
- import { MsaViewModel } from '../../model'
15
+ import type { MsaViewModel } from '../../model'
16
16
  import colorSchemes from '../../colorSchemes'
17
17
  import Checkbox2 from '../Checkbox2'
18
18
 
@@ -115,17 +115,40 @@ const MSASettings = observer(function MSASettings({
115
115
  model: MsaViewModel
116
116
  }) {
117
117
  const { classes } = useStyles()
118
- const { bgColor, colWidth, colorSchemeName, rowHeight } = model
118
+ const {
119
+ bgColor,
120
+ contrastLettering,
121
+ colWidth,
122
+ allowedGappyness,
123
+ drawMsaLetters,
124
+ colorSchemeName,
125
+ hideGaps,
126
+ rowHeight,
127
+ } = model
119
128
 
120
129
  return (
121
130
  <div>
122
131
  <h1>MSA options</h1>
123
-
132
+ <Checkbox2
133
+ checked={drawMsaLetters}
134
+ onChange={() => model.setDrawMsaLetters(!drawMsaLetters)}
135
+ label="Draw letters"
136
+ />
124
137
  <Checkbox2
125
138
  checked={bgColor}
126
139
  onChange={() => model.setBgColor(!bgColor)}
127
140
  label="Color background tiles of MSA?"
128
141
  />
142
+ <Checkbox2
143
+ checked={contrastLettering}
144
+ onChange={() => model.setContrastLettering(!contrastLettering)}
145
+ label="Use contrast lettering"
146
+ />
147
+ <Checkbox2
148
+ checked={hideGaps}
149
+ onChange={() => model.setHideGaps(!hideGaps)}
150
+ label={`Hide columns that are ${100 - allowedGappyness}% gaps`}
151
+ />
129
152
 
130
153
  <div className={classes.flex}>
131
154
  <Typography>Column width ({colWidth}px)</Typography>
@@ -147,6 +170,18 @@ const MSASettings = observer(function MSASettings({
147
170
  onChange={(_, val) => model.setRowHeight(val as number)}
148
171
  />
149
172
  </div>
173
+ {hideGaps ? (
174
+ <div className={classes.flex}>
175
+ <Typography>Allowed gappyness ({100 - allowedGappyness}%)</Typography>
176
+ <Slider
177
+ className={classes.field}
178
+ min={1}
179
+ max={100}
180
+ value={allowedGappyness}
181
+ onChange={(_, val) => model.setAllowedGappyness(val as number)}
182
+ />
183
+ </div>
184
+ ) : null}
150
185
 
151
186
  <TextField
152
187
  select
@@ -0,0 +1,19 @@
1
+ import React from 'react'
2
+
3
+ // this is from MUI example
4
+ export default function TabPanel({
5
+ children,
6
+ value,
7
+ index,
8
+ ...other
9
+ }: {
10
+ children?: React.ReactNode
11
+ index: number
12
+ value: number
13
+ }) {
14
+ return (
15
+ <div role="tabpanel" hidden={value !== index} {...other}>
16
+ {value === index && <div>{children}</div>}
17
+ </div>
18
+ )
19
+ }
@@ -12,7 +12,7 @@ import {
12
12
  import { observer } from 'mobx-react'
13
13
 
14
14
  // locals
15
- import { MsaViewModel } from '../../model'
15
+ import type { MsaViewModel } from '../../model'
16
16
 
17
17
  export default observer(function ({
18
18
  model,
@@ -0,0 +1,133 @@
1
+ import React, { useState } from 'react'
2
+ import { observer } from 'mobx-react'
3
+ import {
4
+ Button,
5
+ DialogActions,
6
+ DialogContent,
7
+ FormControlLabel,
8
+ FormControl,
9
+ Radio,
10
+ RadioGroup,
11
+ TextField,
12
+ Typography,
13
+ } from '@mui/material'
14
+ import { getSession } from '@jbrowse/core/util'
15
+ import { Dialog } from '@jbrowse/core/ui'
16
+
17
+ // locals
18
+ import type { MsaViewModel } from '../../model'
19
+ import { jsonfetch } from '../../fetchUtils'
20
+ import type { InterProScanResponse } from '../../launchInterProScan'
21
+
22
+ const UserProvidedDomainsDialog = observer(function ({
23
+ handleClose,
24
+ model,
25
+ }: {
26
+ handleClose: () => void
27
+ model: MsaViewModel
28
+ }) {
29
+ const [file, setFile] = useState<File>()
30
+ const [choice, setChoice] = useState('file')
31
+ const [interProURL, setInterProURL] = useState('')
32
+
33
+ return (
34
+ <Dialog
35
+ maxWidth="xl"
36
+ title="Open protein domains from file"
37
+ onClose={() => handleClose()}
38
+ open
39
+ >
40
+ <DialogContent>
41
+ <div>
42
+ <Typography>
43
+ Open a JSON file of InterProScan results that you run remotely on
44
+ EBI servers or locally
45
+ </Typography>
46
+
47
+ <div style={{ display: 'flex', margin: 30 }}>
48
+ <FormControl component="fieldset">
49
+ <RadioGroup
50
+ value={choice}
51
+ onChange={event => setChoice(event.target.value)}
52
+ >
53
+ <FormControlLabel value="url" control={<Radio />} label="URL" />
54
+ <FormControlLabel
55
+ value="file"
56
+ control={<Radio />}
57
+ label="File"
58
+ />
59
+ </RadioGroup>
60
+ </FormControl>
61
+ {choice === 'url' ? (
62
+ <div>
63
+ <Typography>
64
+ Open a InterProScan JSON file remote URL
65
+ </Typography>
66
+ <TextField
67
+ label="URL"
68
+ value={interProURL}
69
+ onChange={event => setInterProURL(event.target.value)}
70
+ />
71
+ </div>
72
+ ) : null}
73
+ {choice === 'file' ? (
74
+ <div style={{ paddingTop: 20 }}>
75
+ <Typography>
76
+ Open a InterProScan JSON file file from your local drive
77
+ </Typography>
78
+ <Button variant="outlined" component="label">
79
+ Choose File
80
+ <input
81
+ type="file"
82
+ hidden
83
+ onChange={({ target }) => {
84
+ const file = target?.files?.[0]
85
+ if (file) {
86
+ setFile(file)
87
+ }
88
+ }}
89
+ />
90
+ </Button>
91
+ </div>
92
+ ) : null}
93
+ </div>
94
+ </div>
95
+ </DialogContent>
96
+ <DialogActions>
97
+ <Button
98
+ variant="contained"
99
+ color="primary"
100
+ onClick={() => {
101
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
102
+ ;(async () => {
103
+ try {
104
+ const ret: InterProScanResponse = file
105
+ ? JSON.parse(await file.text())
106
+ : await jsonfetch(interProURL)
107
+
108
+ model.setInterProAnnotations(
109
+ Object.fromEntries(ret.results.map(r => [r.xref[0].id, r])),
110
+ )
111
+ model.setShowDomains(true)
112
+ getSession(model).notify(
113
+ 'Loaded interproscan results',
114
+ 'success',
115
+ )
116
+ } catch (e) {
117
+ console.error(e)
118
+ getSession(model).notifyError(`${e}`, e)
119
+ } finally {
120
+ model.setStatus()
121
+ }
122
+ })()
123
+ handleClose()
124
+ }}
125
+ >
126
+ Open results
127
+ </Button>
128
+ </DialogActions>
129
+ </Dialog>
130
+ )
131
+ })
132
+
133
+ export default UserProvidedDomainsDialog
@@ -1,9 +1,10 @@
1
- import React, { lazy } from 'react'
1
+ import React, { lazy, useEffect } from 'react'
2
2
  import { IconButton } from '@mui/material'
3
3
  import { observer } from 'mobx-react'
4
+ import useMeasure from '@jbrowse/core/util/useMeasure'
4
5
 
5
6
  // locals
6
- import { MsaViewModel } from '../../model'
7
+ import type { MsaViewModel } from '../../model'
7
8
 
8
9
  // icons
9
10
  import Help from '@mui/icons-material/Help'
@@ -13,17 +14,19 @@ import ZoomControls from './ZoomControls'
13
14
  import MultiAlignmentSelector from './MultiAlignmentSelector'
14
15
  import HeaderInfoArea from './HeaderInfoArea'
15
16
  import HeaderStatusArea from './HeaderStatusArea'
16
- import HeaderMenu from './HeaderMenu'
17
17
  import HeaderMenuExtra from './HeaderMenuExtra'
18
18
 
19
19
  const AboutDialog = lazy(() => import('../dialogs/AboutDialog'))
20
20
 
21
21
  const Header = observer(function ({ model }: { model: MsaViewModel }) {
22
+ const [ref, { height }] = useMeasure()
23
+ useEffect(() => {
24
+ model.setHeaderHeight(height || 0)
25
+ }, [model, height])
22
26
  return (
23
- <div style={{ display: 'flex' }}>
24
- <HeaderMenu model={model} />
25
- <ZoomControls model={model} />
27
+ <div ref={ref} style={{ display: 'flex' }}>
26
28
  <HeaderMenuExtra model={model} />
29
+ <ZoomControls model={model} />
27
30
  <MultiAlignmentSelector model={model} />
28
31
  <HeaderInfoArea model={model} />
29
32
  <Spacer />
@@ -4,7 +4,7 @@ import { observer } from 'mobx-react'
4
4
  import { makeStyles } from 'tss-react/mui'
5
5
 
6
6
  // locals
7
- import { MsaViewModel } from '../../model'
7
+ import type { MsaViewModel } from '../../model'
8
8
 
9
9
  const useStyles = makeStyles()({
10
10
  margin: {
@@ -10,7 +10,7 @@ import List from '@mui/icons-material/List'
10
10
  import Menu from '@mui/icons-material/Menu'
11
11
 
12
12
  // locals
13
- import { MsaViewModel } from '../../model'
13
+ import type { MsaViewModel } from '../../model'
14
14
 
15
15
  // lazies
16
16
  const SettingsDialog = lazy(() => import('../dialogs/SettingsDialog'))