jbrowse-plugin-msaview 2.3.5 → 2.3.8

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 (62) hide show
  1. package/README.md +15 -216
  2. package/dist/AddHighlightModel/GenomeMouseoverHighlight.js.map +1 -1
  3. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +19 -4
  4. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js.map +1 -1
  5. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js +16 -7
  6. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js.map +1 -1
  7. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js +4 -2
  8. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js.map +1 -1
  9. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js +4 -1
  10. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js.map +1 -1
  11. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js +8 -1
  12. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js.map +1 -1
  13. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js +15 -7
  14. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js.map +1 -1
  15. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.js +8 -1
  16. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.js.map +1 -1
  17. package/dist/LaunchMsaView/components/NCBIBlastQuery/useCachedBlastResults.js +3 -0
  18. package/dist/LaunchMsaView/components/NCBIBlastQuery/useCachedBlastResults.js.map +1 -1
  19. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +7 -2
  20. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js.map +1 -1
  21. package/dist/LaunchMsaView/components/TabPanel.js +1 -1
  22. package/dist/LaunchMsaView/components/TabPanel.js.map +1 -1
  23. package/dist/LaunchMsaView/components/TranscriptSelector.js +7 -3
  24. package/dist/LaunchMsaView/components/TranscriptSelector.js.map +1 -1
  25. package/dist/MsaViewPanel/afterCreateAutoruns.js +9 -15
  26. package/dist/MsaViewPanel/afterCreateAutoruns.js.map +1 -1
  27. package/dist/MsaViewPanel/components/ConnectStructureDialog.js +15 -10
  28. package/dist/MsaViewPanel/components/ConnectStructureDialog.js.map +1 -1
  29. package/dist/MsaViewPanel/components/MsaViewPanel.js +8 -1
  30. package/dist/MsaViewPanel/components/MsaViewPanel.js.map +1 -1
  31. package/dist/MsaViewPanel/model.d.ts +2 -2
  32. package/dist/MsaViewPanel/model.js +13 -10
  33. package/dist/MsaViewPanel/model.js.map +1 -1
  34. package/dist/MsaViewPanel/pairwiseAlignment.js +6 -6
  35. package/dist/MsaViewPanel/pairwiseAlignment.js.map +1 -1
  36. package/dist/MsaViewPanel/structureConnection.d.ts +22 -0
  37. package/dist/MsaViewPanel/structureConnection.js +4 -0
  38. package/dist/MsaViewPanel/structureConnection.js.map +1 -1
  39. package/dist/jbrowse-plugin-msaview.umd.production.min.js +24 -24
  40. package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
  41. package/dist/version.d.ts +1 -1
  42. package/dist/version.js +1 -1
  43. package/package.json +2 -4
  44. package/src/AddHighlightModel/GenomeMouseoverHighlight.tsx +1 -2
  45. package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +22 -7
  46. package/src/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.tsx +17 -9
  47. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx +8 -3
  48. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.tsx +4 -1
  49. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.tsx +9 -1
  50. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.tsx +15 -8
  51. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.tsx +9 -1
  52. package/src/LaunchMsaView/components/NCBIBlastQuery/useCachedBlastResults.ts +3 -0
  53. package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +11 -2
  54. package/src/LaunchMsaView/components/TabPanel.tsx +1 -1
  55. package/src/LaunchMsaView/components/TranscriptSelector.tsx +7 -3
  56. package/src/MsaViewPanel/afterCreateAutoruns.ts +9 -27
  57. package/src/MsaViewPanel/components/ConnectStructureDialog.tsx +23 -25
  58. package/src/MsaViewPanel/components/MsaViewPanel.tsx +9 -1
  59. package/src/MsaViewPanel/model.ts +23 -18
  60. package/src/MsaViewPanel/pairwiseAlignment.ts +6 -6
  61. package/src/MsaViewPanel/structureConnection.ts +23 -0
  62. package/src/version.ts +1 -1
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.3.5";
1
+ export declare const version = "2.3.8";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '2.3.5';
1
+ export const version = '2.3.8';
2
2
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.3.5",
2
+ "version": "2.3.8",
3
3
  "license": "MIT",
4
4
  "name": "jbrowse-plugin-msaview",
5
5
  "repository": {
@@ -73,8 +73,6 @@
73
73
  "test:setup:version": "node scripts/test-versions.mjs setup",
74
74
  "test:versions": "node scripts/test-versions.mjs run",
75
75
  "test:version": "node scripts/test-versions.mjs run",
76
- "preversion": "pnpm lint",
77
- "version": "node -e \"console.log('export const version = \\'' + require('./package.json').version + '\\'')\" > src/version.ts && git add src/version.ts",
78
- "postversion": "git push --follow-tags"
76
+ "release": "node scripts/release.mjs"
79
77
  }
80
78
  }
@@ -38,8 +38,7 @@ const GenomeMouseoverHighlightRenderer = observer(function ({
38
38
  hovered,
39
39
  }: {
40
40
  model: LinearGenomeViewModel
41
-
42
- hovered: any
41
+ hovered: object & Record<'hoverPosition', unknown>
43
42
  }) {
44
43
  const { classes } = useStyles()
45
44
  const { offsetPx } = model
@@ -35,6 +35,21 @@ const useStyles = makeStyles()({
35
35
  textAreaFont: {
36
36
  fontFamily: 'Courier New',
37
37
  },
38
+ inputContainer: {
39
+ marginBottom: 30,
40
+ },
41
+ fileContainer: {
42
+ maxWidth: 500,
43
+ },
44
+ msaInput: {
45
+ marginBottom: 20,
46
+ },
47
+ queryNameInput: {
48
+ marginTop: 20,
49
+ },
50
+ warningAlert: {
51
+ marginTop: 10,
52
+ },
38
53
  })
39
54
 
40
55
  const ManualMSALoader = observer(function PreLoadedMSA2({
@@ -91,9 +106,9 @@ const ManualMSALoader = observer(function PreLoadedMSA2({
91
106
  </RadioGroup>
92
107
  </FormControl>
93
108
 
94
- <div style={{ marginBottom: 30 }}>
109
+ <div className={classes.inputContainer}>
95
110
  {inputMethod === 'file' ? (
96
- <div style={{ maxWidth: 500 }}>
111
+ <div className={classes.fileContainer}>
97
112
  <FileSelector
98
113
  name="MSA File .aln (Clustal), .fa/.mfa (aligned FASTA), .stock (Stockholm), etc)"
99
114
  inline
@@ -114,7 +129,7 @@ const ManualMSALoader = observer(function PreLoadedMSA2({
114
129
  name="MSA"
115
130
  multiline
116
131
  minRows={5}
117
- style={{ marginBottom: '20px' }}
132
+ className={classes.msaInput}
118
133
  maxRows={10}
119
134
  fullWidth
120
135
  placeholder="Paste MSA here"
@@ -154,7 +169,7 @@ const ManualMSALoader = observer(function PreLoadedMSA2({
154
169
  name="MSA row name"
155
170
  fullWidth
156
171
  required
157
- style={{ marginTop: 20 }}
172
+ className={classes.queryNameInput}
158
173
  placeholder="Row name in MSA that corresponds to the selected transcript"
159
174
  helperText="Required: Specify the name of the row in your MSA that should be aligned with the selected transcript"
160
175
  value={querySeqName}
@@ -163,13 +178,13 @@ const ManualMSALoader = observer(function PreLoadedMSA2({
163
178
  }}
164
179
  />
165
180
 
166
- {!querySeqName.trim() && (
167
- <Alert severity="warning" style={{ marginTop: 10 }}>
181
+ {!querySeqName.trim() ? (
182
+ <Alert severity="warning" className={classes.warningAlert}>
168
183
  Without specifying the MSA row name, clicking on the MSA will not
169
184
  navigate to the corresponding genome position, and hovering
170
185
  highlights will not work.
171
186
  </Alert>
172
- )}
187
+ ) : null}
173
188
  </DialogContent>
174
189
 
175
190
  <DialogActions>
@@ -13,6 +13,7 @@ import {
13
13
  Typography,
14
14
  } from '@mui/material'
15
15
  import { observer } from 'mobx-react'
16
+ import { makeStyles } from 'tss-react/mui'
16
17
 
17
18
  import { blastLaunchViewFromCache } from './blastLaunchView'
18
19
  import { useCachedBlastResults } from './useCachedBlastResults'
@@ -22,6 +23,19 @@ import type { CachedBlastResult } from '../../../utils/blastCache'
22
23
  import type { AbstractTrackModel, Feature } from '@jbrowse/core/util'
23
24
  import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
24
25
 
26
+ const useStyles = makeStyles()({
27
+ header: {
28
+ display: 'flex',
29
+ justifyContent: 'space-between',
30
+ alignItems: 'center',
31
+ marginBottom: 8,
32
+ },
33
+ resultList: {
34
+ maxHeight: 300,
35
+ overflow: 'auto',
36
+ },
37
+ })
38
+
25
39
  function getResultDisplayName(result: CachedBlastResult): string {
26
40
  const parts = []
27
41
  if (result.geneName) {
@@ -45,6 +59,7 @@ const CachedBlastResults = observer(function ({
45
59
  handleClose: () => void
46
60
  feature: Feature
47
61
  }) {
62
+ const { classes } = useStyles()
48
63
  const view = getContainingView(model) as LinearGenomeViewModel
49
64
  const [operationError, setOperationError] = useState<unknown>()
50
65
 
@@ -82,14 +97,7 @@ const CachedBlastResults = observer(function ({
82
97
 
83
98
  return (
84
99
  <div>
85
- <div
86
- style={{
87
- display: 'flex',
88
- justifyContent: 'space-between',
89
- alignItems: 'center',
90
- marginBottom: 8,
91
- }}
92
- >
100
+ <div className={classes.header}>
93
101
  <Typography variant="subtitle1">
94
102
  Cached BLAST Results ({results.length})
95
103
  </Typography>
@@ -108,7 +116,7 @@ const CachedBlastResults = observer(function ({
108
116
  Clear All
109
117
  </Button>
110
118
  </div>
111
- <List dense style={{ maxHeight: 300, overflow: 'auto' }}>
119
+ <List dense className={classes.resultList}>
112
120
  {results.map(result => (
113
121
  <ListItem
114
122
  key={result.id}
@@ -229,18 +229,23 @@ const NCBIBlastAutomaticPanel = observer(function ({
229
229
  proteinSequence,
230
230
  },
231
231
  })
232
+ handleClose()
232
233
  } catch (e) {
233
234
  console.error(e)
234
235
  setLaunchViewError(e)
235
236
  }
236
-
237
- handleClose()
238
237
  }}
239
238
  disabled={!proteinSequence}
240
239
  >
241
240
  Submit
242
241
  </Button>
243
- <Button color="secondary" variant="contained" onClick={handleClose}>
242
+ <Button
243
+ color="secondary"
244
+ variant="contained"
245
+ onClick={() => {
246
+ handleClose()
247
+ }}
248
+ >
244
249
  Cancel
245
250
  </Button>
246
251
  </DialogActions>
@@ -26,6 +26,9 @@ const useStyles = makeStyles()({
26
26
  margin: 30,
27
27
  maxWidth: 600,
28
28
  },
29
+ infoText: {
30
+ marginTop: 20,
31
+ },
29
32
  })
30
33
 
31
34
  const NCBIBlastManualPanel = observer(function ({
@@ -77,7 +80,7 @@ const NCBIBlastManualPanel = observer(function ({
77
80
  </div>
78
81
  ) : null}
79
82
 
80
- <Typography style={{ marginTop: 20 }}>
83
+ <Typography className={classes.infoText}>
81
84
  Click the link above and run your BLAST query, and once you have
82
85
  results, click "Multiple Alignment" at the top of the results page to
83
86
  be redirected to COBALT, NCBI's multiple sequence aligner. Once COBALT
@@ -3,6 +3,7 @@ import React, { useState } from 'react'
3
3
  import { useLocalStorage } from '@jbrowse/core/util'
4
4
  import SettingsIcon from '@mui/icons-material/Settings'
5
5
  import { IconButton } from '@mui/material'
6
+ import { makeStyles } from 'tss-react/mui'
6
7
 
7
8
  import NCBIBlastAutomaticPanel from './NCBIBlastAutomaticPanel'
8
9
  import NCBIBlastManualPanel from './NCBIBlastManualPanel'
@@ -13,6 +14,12 @@ import { BASE_BLAST_URL } from './consts'
13
14
 
14
15
  import type { AbstractTrackModel, Feature } from '@jbrowse/core/util'
15
16
 
17
+ const useStyles = makeStyles()({
18
+ settingsButton: {
19
+ float: 'right',
20
+ },
21
+ })
22
+
16
23
  const panelMap = {
17
24
  automatic: NCBIBlastAutomaticPanel,
18
25
  rid: NCBIBlastRIDPanel,
@@ -34,13 +41,14 @@ export default function NCBIBlastPanel({
34
41
  BASE_BLAST_URL,
35
42
  )
36
43
  const [settingsOpen, setSettingsOpen] = useState(false)
44
+ const { classes } = useStyles()
37
45
 
38
46
  const Panel = panelMap[lookupMethod as keyof typeof panelMap]
39
47
 
40
48
  return (
41
49
  <>
42
50
  <IconButton
43
- style={{ float: 'right' }}
51
+ className={classes.settingsButton}
44
52
  size="small"
45
53
  onClick={() => {
46
54
  setSettingsOpen(true)
@@ -28,6 +28,15 @@ const useStyles = makeStyles()({
28
28
  dialogContent: {
29
29
  width: '80em',
30
30
  },
31
+ marginBottom: {
32
+ marginBottom: 16,
33
+ },
34
+ ridField: {
35
+ width: 150,
36
+ },
37
+ infoText: {
38
+ marginTop: 20,
39
+ },
31
40
  })
32
41
 
33
42
  const NCBIBlastRIDPanel = observer(function ({
@@ -60,7 +69,6 @@ const NCBIBlastRIDPanel = observer(function ({
60
69
  } = useTranscriptSelection({ feature, view })
61
70
 
62
71
  const e = proteinSequenceError ?? launchViewError
63
- const style = { width: 150 }
64
72
  const trimmedRid = rid.trim()
65
73
 
66
74
  return (
@@ -69,7 +77,7 @@ const NCBIBlastRIDPanel = observer(function ({
69
77
  {children}
70
78
  {e ? <ErrorMessage error={e} /> : null}
71
79
 
72
- <Typography variant="body2" style={{ marginBottom: 16 }}>
80
+ <Typography variant="body2" className={classes.marginBottom}>
73
81
  Enter the RID (Request ID) from a previously submitted NCBI BLAST
74
82
  query. You can find the RID in the BLAST results page URL or at the
75
83
  top of the results page. RIDs are typically valid for 24-36 hours
@@ -81,7 +89,7 @@ const NCBIBlastRIDPanel = observer(function ({
81
89
  label="BLAST RID"
82
90
  placeholder="e.g., ABC12345"
83
91
  fullWidth
84
- style={{ marginBottom: 16 }}
92
+ className={classes.marginBottom}
85
93
  value={rid}
86
94
  onChange={event => {
87
95
  setRid(event.target.value)
@@ -89,7 +97,7 @@ const NCBIBlastRIDPanel = observer(function ({
89
97
  />
90
98
 
91
99
  {trimmedRid ? (
92
- <Typography variant="body2" style={{ marginBottom: 16 }}>
100
+ <Typography variant="body2" className={classes.marginBottom}>
93
101
  <ExternalLink href={`${baseUrl}?CMD=Get&RID=${trimmedRid}`}>
94
102
  View BLAST results on NCBI
95
103
  </ExternalLink>
@@ -99,7 +107,7 @@ const NCBIBlastRIDPanel = observer(function ({
99
107
  <TextField2
100
108
  variant="outlined"
101
109
  label="MSA Algorithm"
102
- style={style}
110
+ className={classes.ridField}
103
111
  select
104
112
  value={selectedMsaAlgorithm}
105
113
  onChange={event => {
@@ -122,7 +130,7 @@ const NCBIBlastRIDPanel = observer(function ({
122
130
  proteinSequence={proteinSequence}
123
131
  />
124
132
 
125
- <Typography style={{ marginTop: 20 }}>
133
+ <Typography className={classes.infoText}>
126
134
  This will fetch the BLAST results for the provided RID and run them
127
135
  through a multiple sequence alignment. The protein sequence from the
128
136
  selected transcript will be added as the query sequence in the MSA.
@@ -152,12 +160,11 @@ const NCBIBlastRIDPanel = observer(function ({
152
160
  rid: trimmedRid,
153
161
  },
154
162
  })
163
+ handleClose()
155
164
  } catch (e) {
156
165
  console.error(e)
157
166
  setLaunchViewError(e)
158
167
  }
159
-
160
- handleClose()
161
168
  }}
162
169
  disabled={!proteinSequence || !trimmedRid}
163
170
  >
@@ -7,10 +7,17 @@ import {
7
7
  DialogContent,
8
8
  DialogTitle,
9
9
  } from '@mui/material'
10
+ import { makeStyles } from 'tss-react/mui'
10
11
 
11
12
  import { BASE_BLAST_URL } from './consts'
12
13
  import TextField2 from '../../../components/TextField2'
13
14
 
15
+ const useStyles = makeStyles()({
16
+ urlField: {
17
+ minWidth: 300,
18
+ },
19
+ })
20
+
14
21
  export default function NCBISettingsDialog({
15
22
  handleClose,
16
23
  baseUrl,
@@ -18,6 +25,7 @@ export default function NCBISettingsDialog({
18
25
  handleClose: (arg?: string) => void
19
26
  baseUrl: string
20
27
  }) {
28
+ const { classes } = useStyles()
21
29
  const [tempBaseUrl, setTempBaseUrl] = useState(baseUrl)
22
30
  return (
23
31
  <Dialog
@@ -36,7 +44,7 @@ export default function NCBISettingsDialog({
36
44
  fullWidth
37
45
  variant="outlined"
38
46
  value={tempBaseUrl}
39
- style={{ minWidth: '300px' }}
47
+ className={classes.urlField}
40
48
  onChange={e => {
41
49
  setTempBaseUrl(e.target.value)
42
50
  }}
@@ -10,6 +10,9 @@ const swrConfig = {
10
10
  revalidateOnFocus: false,
11
11
  revalidateOnReconnect: false,
12
12
  revalidateIfStale: false,
13
+ refreshWhenHidden: false,
14
+ refreshWhenOffline: false,
15
+ shouldRetryOnError: false,
13
16
  }
14
17
 
15
18
  export function useCachedBlastResults(geneIds: string[]) {
@@ -24,6 +24,9 @@ const useStyles = makeStyles()({
24
24
  dialogContent: {
25
25
  width: '80em',
26
26
  },
27
+ selectedContainer: {
28
+ marginTop: 50,
29
+ },
27
30
  })
28
31
 
29
32
  const PreLoadedMSA = observer(function ({
@@ -120,7 +123,7 @@ const PreLoadedMSA = observer(function ({
120
123
  </TextField2>
121
124
 
122
125
  {selectedDataset ? (
123
- <div style={{ marginTop: 50 }}>
126
+ <div className={classes.selectedContainer}>
124
127
  {!msaListLoading && msaDataLoading ? (
125
128
  <LoadingEllipses
126
129
  variant="h6"
@@ -183,7 +186,13 @@ const PreLoadedMSA = observer(function ({
183
186
  >
184
187
  Submit
185
188
  </Button>
186
- <Button color="secondary" variant="contained" onClick={handleClose}>
189
+ <Button
190
+ color="secondary"
191
+ variant="contained"
192
+ onClick={() => {
193
+ handleClose()
194
+ }}
195
+ >
187
196
  Cancel
188
197
  </Button>
189
198
  </DialogActions>
@@ -13,7 +13,7 @@ export default function TabPanel({
13
13
  }) {
14
14
  return (
15
15
  <div role="tabpanel" hidden={value !== index} {...other}>
16
- {value === index && <div>{children}</div>}
16
+ {value === index ? <div>{children}</div> : null}
17
17
  </div>
18
18
  )
19
19
  }
@@ -21,6 +21,10 @@ const useStyles = makeStyles()({
21
21
  minWidth: {
22
22
  minWidth: 300,
23
23
  },
24
+ centered: {
25
+ alignContent: 'center',
26
+ marginLeft: 20,
27
+ },
24
28
  })
25
29
 
26
30
  export default function TranscriptSelector({
@@ -70,7 +74,7 @@ export default function TranscriptSelector({
70
74
  )
71
75
  })}
72
76
  </TextField>
73
- <div style={{ alignContent: 'center', marginLeft: 20 }}>
77
+ <div className={classes.centered}>
74
78
  <Button
75
79
  variant="contained"
76
80
  color="primary"
@@ -83,7 +87,7 @@ export default function TranscriptSelector({
83
87
  </div>
84
88
  </div>
85
89
 
86
- {showSequence && (
90
+ {showSequence ? (
87
91
  <ReadOnlyTextField2
88
92
  value={
89
93
  proteinSequence
@@ -91,7 +95,7 @@ export default function TranscriptSelector({
91
95
  : 'Loading...'
92
96
  }
93
97
  />
94
- )}
98
+ ) : null}
95
99
  </>
96
100
  )
97
101
  }
@@ -8,27 +8,11 @@ import {
8
8
  retrieveMsaData,
9
9
  storeMsaData,
10
10
  } from './msaDataStore'
11
- import { gappedToUngappedPosition } from './structureConnection'
11
+ import { gappedToUngappedPosition, isProteinView } from './structureConnection'
12
12
  import { getUniprotIdFromAlphaFoldUrl } from './util'
13
13
 
14
14
  import type { JBrowsePluginMsaViewModel } from './model'
15
15
 
16
- interface ProteinView {
17
- type: 'ProteinView'
18
- id: string
19
- structures: {
20
- connectedViewId?: string
21
- uniprotId?: string
22
- structureSequences?: unknown[]
23
- hoverGenomeHighlights?: { start: number; end: number }[]
24
- }[]
25
- }
26
-
27
- function isProteinView(view: unknown): view is ProteinView {
28
- const v = view as Record<string, unknown>
29
- return v.type === 'ProteinView' && Array.isArray(v.structures)
30
- }
31
-
32
16
  export function loadStoredData(self: JBrowsePluginMsaViewModel) {
33
17
  const { dataStoreId, rows } = self
34
18
  if (dataStoreId && rows.length === 0) {
@@ -179,7 +163,7 @@ export function highlightConnectedStructures(self: JBrowsePluginMsaViewModel) {
179
163
  }
180
164
 
181
165
  for (const conn of connectedProteinViews) {
182
- const structure = conn.proteinView?.structures?.[conn.structureIdx]
166
+ const structure = conn.proteinView.structures[conn.structureIdx]
183
167
  if (!structure) {
184
168
  continue
185
169
  }
@@ -210,7 +194,7 @@ export function highlightConnectedStructures(self: JBrowsePluginMsaViewModel) {
210
194
  }
211
195
 
212
196
  export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
213
- const { views } = getSession(self)
197
+ const views = getSession(self).views as unknown[]
214
198
  const { connectedViewId, uniprotId, rows, connectedStructures } = self
215
199
 
216
200
  if (!uniprotId || rows.length === 0) {
@@ -221,14 +205,13 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
221
205
  if (!isProteinView(view)) {
222
206
  continue
223
207
  }
224
- const v = view
225
208
 
226
209
  for (
227
210
  let structureIdx = 0;
228
- structureIdx < v.structures.length;
211
+ structureIdx < view.structures.length;
229
212
  structureIdx++
230
213
  ) {
231
- const structure = v.structures[structureIdx]
214
+ const structure = view.structures[structureIdx]
232
215
  if (!structure) {
233
216
  continue
234
217
  }
@@ -242,7 +225,7 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
242
225
  }
243
226
 
244
227
  const alreadyConnected = connectedStructures.some(
245
- c => c.proteinViewId === v.id && c.structureIdx === structureIdx,
228
+ c => c.proteinViewId === view.id && c.structureIdx === structureIdx,
246
229
  )
247
230
  if (alreadyConnected) {
248
231
  continue
@@ -253,7 +236,7 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
253
236
  }
254
237
 
255
238
  try {
256
- self.connectToStructure(v.id, structureIdx)
239
+ self.connectToStructure(view.id, structureIdx)
257
240
  } catch (e) {
258
241
  console.error('Failed to auto-connect to ProteinView:', e)
259
242
  }
@@ -262,7 +245,7 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
262
245
  }
263
246
 
264
247
  export function observeProteinHighlights(self: JBrowsePluginMsaViewModel) {
265
- const { views } = getSession(self)
248
+ const views = getSession(self).views as unknown[]
266
249
  const { connectedViewId, transcriptToMsaMap, querySeqName } = self
267
250
 
268
251
  if (!connectedViewId || !transcriptToMsaMap) {
@@ -275,9 +258,8 @@ export function observeProteinHighlights(self: JBrowsePluginMsaViewModel) {
275
258
  if (!isProteinView(view)) {
276
259
  continue
277
260
  }
278
- const v = view
279
261
 
280
- for (const structure of v.structures) {
262
+ for (const structure of view.structures) {
281
263
  if (structure.connectedViewId !== connectedViewId) {
282
264
  continue
283
265
  }
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from 'react'
2
2
 
3
- import { Dialog } from '@jbrowse/core/ui'
3
+ import { Dialog, ErrorMessage } from '@jbrowse/core/ui'
4
4
  import { getSession } from '@jbrowse/core/util'
5
5
  import {
6
6
  Button,
@@ -13,9 +13,18 @@ import {
13
13
  Typography,
14
14
  } from '@mui/material'
15
15
  import { observer } from 'mobx-react'
16
+ import { makeStyles } from 'tss-react/mui'
17
+
18
+ import { isProteinView } from '../structureConnection'
16
19
 
17
20
  import type { JBrowsePluginMsaViewModel } from '../model'
18
21
 
22
+ const useStyles = makeStyles()(theme => ({
23
+ formControl: {
24
+ marginBottom: theme.spacing(2),
25
+ },
26
+ }))
27
+
19
28
  const ConnectStructureDialog = observer(function ConnectStructureDialog({
20
29
  model,
21
30
  handleClose,
@@ -23,23 +32,18 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
23
32
  model: JBrowsePluginMsaViewModel
24
33
  handleClose: () => void
25
34
  }) {
35
+ const { classes } = useStyles()
26
36
  const session = getSession(model)
27
37
  const [selectedViewId, setSelectedViewId] = useState('')
28
38
  const [selectedStructureIdx, setSelectedStructureIdx] = useState(0)
29
39
  const [selectedMsaRow, setSelectedMsaRow] = useState(model.querySeqName)
30
40
  const [error, setError] = useState<string>()
31
41
 
32
- // Find all ProteinViews in the session
33
-
34
- const proteinViews = session.views.filter(
35
- (v: any) => v.type === 'ProteinView',
36
- ) as any[]
42
+ const proteinViews = (session.views as unknown[]).filter(isProteinView)
37
43
 
38
- // Get structures for the selected view
39
44
  const selectedView = proteinViews.find(v => v.id === selectedViewId)
40
45
  const structures = selectedView?.structures ?? []
41
46
 
42
- // Get MSA row names
43
47
  const msaRowNames = model.rows.map(r => r[0])
44
48
 
45
49
  const handleConnect = () => {
@@ -75,7 +79,7 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
75
79
  </Typography>
76
80
  ) : (
77
81
  <>
78
- <FormControl fullWidth sx={{ mb: 2 }}>
82
+ <FormControl fullWidth className={classes.formControl}>
79
83
  <InputLabel>Protein View</InputLabel>
80
84
  <Select
81
85
  value={selectedViewId}
@@ -93,8 +97,8 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
93
97
  </Select>
94
98
  </FormControl>
95
99
 
96
- {structures.length > 1 && (
97
- <FormControl fullWidth sx={{ mb: 2 }}>
100
+ {structures.length > 1 ? (
101
+ <FormControl fullWidth className={classes.formControl}>
98
102
  <InputLabel>Structure</InputLabel>
99
103
  <Select
100
104
  value={selectedStructureIdx}
@@ -103,18 +107,16 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
103
107
  setSelectedStructureIdx(e.target.value)
104
108
  }}
105
109
  >
106
- {structures.map(
107
- (structure: { url?: string }, idx: number) => (
108
- <MenuItem key={idx} value={idx}>
109
- {structure.url ?? `Structure ${idx + 1}`}
110
- </MenuItem>
111
- ),
112
- )}
110
+ {structures.map((structure, idx) => (
111
+ <MenuItem key={idx} value={idx}>
112
+ {structure.url ?? `Structure ${idx + 1}`}
113
+ </MenuItem>
114
+ ))}
113
115
  </Select>
114
116
  </FormControl>
115
- )}
117
+ ) : null}
116
118
 
117
- <FormControl fullWidth sx={{ mb: 2 }}>
119
+ <FormControl fullWidth className={classes.formControl}>
118
120
  <InputLabel>MSA Row</InputLabel>
119
121
  <Select
120
122
  value={selectedMsaRow}
@@ -131,11 +133,7 @@ const ConnectStructureDialog = observer(function ConnectStructureDialog({
131
133
  </Select>
132
134
  </FormControl>
133
135
 
134
- {error && (
135
- <Typography color="error" sx={{ mt: 1 }}>
136
- {error}
137
- </Typography>
138
- )}
136
+ {error ? <ErrorMessage error={error} /> : null}
139
137
  </>
140
138
  )}
141
139
  </DialogContent>