@apollo-annotation/jbrowse-plugin-apollo 0.3.7 → 0.3.9

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 (86) hide show
  1. package/dist/index.esm.js +11212 -10483
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +11251 -10509
  4. package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
  5. package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
  6. package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
  7. package/dist/jbrowse-plugin-apollo.umd.development.js +7726 -9014
  8. package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
  9. package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
  10. package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
  11. package/package.json +18 -18
  12. package/src/ApolloInternetAccount/model.ts +123 -70
  13. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +4 -4
  14. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +9 -7
  15. package/src/BackendDrivers/CollaborationServerDriver.ts +72 -20
  16. package/src/BackendDrivers/DesktopFileDriver.ts +2 -2
  17. package/src/ChangeManager.ts +36 -14
  18. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +64 -5
  19. package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -4
  20. package/src/FeatureDetailsWidget/NumberTextField.tsx +5 -2
  21. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +70 -73
  22. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +72 -234
  23. package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +92 -0
  24. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +23 -131
  25. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +50 -194
  26. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +279 -217
  27. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +53 -34
  28. package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -9
  29. package/src/LinearApolloDisplay/glyphs/util.ts +19 -0
  30. package/src/LinearApolloDisplay/stateModel/base.ts +34 -43
  31. package/src/LinearApolloDisplay/stateModel/layouts.ts +3 -2
  32. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +32 -261
  33. package/src/LinearApolloDisplay/stateModel/rendering.ts +43 -343
  34. package/src/LinearApolloReferenceSequenceDisplay/components/LinearApolloReferenceSequenceDisplay.tsx +87 -0
  35. package/src/LinearApolloReferenceSequenceDisplay/components/index.ts +1 -0
  36. package/src/LinearApolloReferenceSequenceDisplay/configSchema.ts +7 -0
  37. package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +181 -0
  38. package/src/LinearApolloReferenceSequenceDisplay/drawSequenceTrack.ts +218 -0
  39. package/src/LinearApolloReferenceSequenceDisplay/index.ts +3 -0
  40. package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +227 -0
  41. package/src/LinearApolloReferenceSequenceDisplay/stateModel/index.ts +25 -0
  42. package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +157 -0
  43. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +101 -38
  44. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +334 -262
  45. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +12 -8
  46. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +42 -4
  47. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +4 -8
  48. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +73 -97
  49. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +49 -61
  50. package/src/TabularEditor/HybridGrid/Feature.tsx +16 -14
  51. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +7 -5
  52. package/src/components/AddAssembly.tsx +34 -38
  53. package/src/components/AddAssemblyAliases.tsx +1 -1
  54. package/src/components/AddChildFeature.tsx +5 -2
  55. package/src/components/AddFeature.tsx +30 -21
  56. package/src/components/AddRefSeqAliases.tsx +64 -50
  57. package/src/components/CopyFeature.tsx +4 -2
  58. package/src/components/CreateApolloAnnotation.tsx +22 -9
  59. package/src/components/DeleteAssembly.tsx +3 -10
  60. package/src/components/DownloadGFF3.tsx +2 -2
  61. package/src/components/EditZoomThresholdDialog.tsx +69 -0
  62. package/src/components/FilterFeatures.tsx +7 -7
  63. package/src/components/FilterTranscripts.tsx +6 -6
  64. package/src/components/ImportFeatures.tsx +1 -1
  65. package/src/components/ManageChecks.tsx +3 -10
  66. package/src/components/ManageUsers.tsx +23 -22
  67. package/src/components/MergeTranscripts.tsx +12 -15
  68. package/src/components/OntologyTermAutocomplete.tsx +1 -8
  69. package/src/components/OntologyTermMultiSelect.tsx +11 -11
  70. package/src/components/OpenLocalFile.tsx +11 -7
  71. package/src/components/ViewChangeLog.tsx +25 -50
  72. package/src/components/ViewCheckResults.tsx +2 -8
  73. package/src/components/index.ts +1 -0
  74. package/src/config.ts +6 -0
  75. package/src/index.ts +53 -115
  76. package/src/makeDisplayComponent.tsx +9 -14
  77. package/src/menus/index.ts +1 -0
  78. package/src/{ApolloInternetAccount/addMenuItems.ts → menus/topLevelMenu.ts} +56 -47
  79. package/src/menus/topLevelMenuAdmin.ts +154 -0
  80. package/src/session/ClientDataStore.ts +32 -14
  81. package/src/session/session.ts +159 -121
  82. package/src/util/annotationFeatureUtils.ts +15 -21
  83. package/src/util/displayUtils.ts +149 -0
  84. package/src/util/glyphUtils.ts +329 -0
  85. package/src/util/loadAssemblyIntoClient.ts +3 -2
  86. package/src/util/mouseEventsUtils.ts +32 -0
@@ -0,0 +1,157 @@
1
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
2
+ import type PluginManager from '@jbrowse/core/PluginManager'
3
+ import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
4
+ import { type Theme, createTheme } from '@mui/material'
5
+ import { autorun } from 'mobx'
6
+ import { type Instance, addDisposer } from 'mobx-state-tree'
7
+
8
+ import { drawSequenceOverlay } from '../drawSequenceOverlay'
9
+ import { drawSequenceTrack } from '../drawSequenceTrack'
10
+
11
+ import { baseModelFactory } from './base'
12
+
13
+ export function renderingModelFactory(
14
+ pluginManager: PluginManager,
15
+ configSchema: AnyConfigurationSchemaType,
16
+ ) {
17
+ const BaseLinearApolloReferenceSequenceDisplay = baseModelFactory(
18
+ pluginManager,
19
+ configSchema,
20
+ )
21
+
22
+ return BaseLinearApolloReferenceSequenceDisplay.named(
23
+ 'LinearApolloReferenceSequenceDisplayRendering',
24
+ )
25
+ .volatile(() => ({
26
+ seqTrackCanvas: null as HTMLCanvasElement | null,
27
+ seqTrackOverlayCanvas: null as HTMLCanvasElement | null,
28
+ theme: createTheme(),
29
+ }))
30
+ .actions((self) => ({
31
+ setSeqTrackCanvas(canvas: HTMLCanvasElement | null) {
32
+ self.seqTrackCanvas = canvas
33
+ },
34
+ setSeqTrackOverlayCanvas(canvas: HTMLCanvasElement | null) {
35
+ self.seqTrackOverlayCanvas = canvas
36
+ },
37
+ setTheme(theme: Theme) {
38
+ self.theme = theme
39
+ },
40
+ afterAttach() {
41
+ addDisposer(
42
+ self,
43
+ autorun(
44
+ () => {
45
+ const {
46
+ lgv,
47
+ seqTrackCanvas,
48
+ theme,
49
+ highContrast,
50
+ showStartCodons,
51
+ showStopCodons,
52
+ sequenceRowHeight,
53
+ session,
54
+ } = self
55
+ if (
56
+ !lgv.initialized ||
57
+ self.regionCannotBeRendered() ||
58
+ !seqTrackCanvas
59
+ ) {
60
+ return
61
+ }
62
+
63
+ const trnslWidthPx = 3 / lgv.bpPerPx
64
+ if (trnslWidthPx < 1) {
65
+ return
66
+ }
67
+
68
+ const { bpPerPx, offsetPx, dynamicBlocks } = lgv
69
+ // we have to be really explicit about passing in individual
70
+ // variables here and not just e.g. "lgv" so that the autorun
71
+ // tracks the variables correctly
72
+ drawSequenceTrack(
73
+ seqTrackCanvas,
74
+ theme,
75
+ bpPerPx,
76
+ offsetPx,
77
+ dynamicBlocks,
78
+ highContrast,
79
+ showStartCodons,
80
+ showStopCodons,
81
+ sequenceRowHeight,
82
+ session,
83
+ )
84
+ },
85
+ { name: 'LinearApolloReferenceSequenceDisplayRenderSequence' },
86
+ ),
87
+ )
88
+ addDisposer(
89
+ self,
90
+ autorun(
91
+ () => {
92
+ const { seqTrackOverlayCanvas } = self
93
+ if (
94
+ !self.lgv.initialized ||
95
+ self.regionCannotBeRendered() ||
96
+ !seqTrackOverlayCanvas
97
+ ) {
98
+ return
99
+ }
100
+ const seqTrackOverlayctx = seqTrackOverlayCanvas.getContext('2d')
101
+ if (!seqTrackOverlayctx) {
102
+ return
103
+ }
104
+
105
+ seqTrackOverlayctx.clearRect(
106
+ 0,
107
+ 0,
108
+ self.lgv.dynamicBlocks.totalWidthPx,
109
+ self.height,
110
+ )
111
+
112
+ const {
113
+ hoveredFeature,
114
+ selectedFeature,
115
+ lgv,
116
+ sequenceRowHeight,
117
+ session,
118
+ theme,
119
+ } = self
120
+
121
+ if (!(hoveredFeature || selectedFeature)) {
122
+ return
123
+ }
124
+ const { bpPerPx, dynamicBlocks, offsetPx } = lgv
125
+ // we have to be really explicit about passing in individual
126
+ // variables here and not just e.g. "lgv" so that the autorun
127
+ // tracks the variables correctly
128
+ drawSequenceOverlay(
129
+ seqTrackOverlayCanvas,
130
+ seqTrackOverlayctx,
131
+ hoveredFeature,
132
+ selectedFeature,
133
+ sequenceRowHeight,
134
+ theme,
135
+ session,
136
+ bpPerPx,
137
+ offsetPx,
138
+ dynamicBlocks,
139
+ )
140
+ },
141
+ {
142
+ name: 'LinearApolloReferenceSequenceDisplayRenderSequenceHighlight',
143
+ },
144
+ ),
145
+ )
146
+ },
147
+ }))
148
+ }
149
+
150
+ export type LinearApolloReferenceSequenceDisplayRenderingModel = ReturnType<
151
+ typeof renderingModelFactory
152
+ >
153
+ // eslint disable because of
154
+ // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
155
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
156
+ export interface LinearApolloReferenceSequenceDisplayRendering
157
+ extends Instance<LinearApolloReferenceSequenceDisplayRenderingModel> {}
@@ -1,19 +1,26 @@
1
1
  /* eslint-disable @typescript-eslint/unbound-method */
2
2
  /* eslint-disable @typescript-eslint/no-misused-promises */
3
3
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
4
+ import { type CheckResultI } from '@apollo-annotation/mst'
4
5
  import { Menu, type MenuItem } from '@jbrowse/core/ui'
5
6
  import {
6
7
  type AbstractSessionModel,
7
8
  doesIntersect2,
8
9
  getContainingView,
10
+ getFrame,
9
11
  } from '@jbrowse/core/util'
10
12
  import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
11
13
  import ErrorIcon from '@mui/icons-material/Error'
12
- import { Alert, Avatar, Tooltip, useTheme } from '@mui/material'
14
+ import LockIcon from '@mui/icons-material/Lock'
15
+ import { Alert, Avatar, Badge, Box, Tooltip, useTheme } from '@mui/material'
13
16
  import { observer } from 'mobx-react'
14
17
  import React, { useEffect, useState } from 'react'
15
- import { makeStyles } from 'tss-react/mui'
16
18
 
19
+ import {
20
+ type Coord,
21
+ clusterResultByMessage,
22
+ useStyles,
23
+ } from '../../util/displayUtils'
17
24
  import { type LinearApolloSixFrameDisplay as LinearApolloSixFrameDisplayI } from '../stateModel'
18
25
 
19
26
  import { TrackLines } from './TrackLines'
@@ -21,31 +28,11 @@ import { TrackLines } from './TrackLines'
21
28
  interface LinearApolloSixFrameDisplayProps {
22
29
  model: LinearApolloSixFrameDisplayI
23
30
  }
24
- export type Coord = [number, number]
25
-
26
- const useStyles = makeStyles()((theme) => ({
27
- canvasContainer: {
28
- position: 'relative',
29
- left: 0,
30
- },
31
- canvas: {
32
- position: 'absolute',
33
- left: 0,
34
- },
35
- ellipses: {
36
- textOverflow: 'ellipsis',
37
- overflow: 'hidden',
38
- },
39
- avatar: {
40
- position: 'absolute',
41
- color: theme.palette.warning.light,
42
- backgroundColor: theme.palette.warning.contrastText,
43
- },
44
- }))
45
31
 
46
32
  export const LinearApolloSixFrameDisplay = observer(
47
33
  function LinearApolloSixFrameDisplay(
48
34
  props: LinearApolloSixFrameDisplayProps,
35
+ apolloDragging,
49
36
  ) {
50
37
  const theme = useTheme()
51
38
  const { model } = props
@@ -54,6 +41,8 @@ export const LinearApolloSixFrameDisplay = observer(
54
41
  contextMenuItems: getContextMenuItems,
55
42
  cursor,
56
43
  featuresHeight,
44
+ featureLabelSpacer,
45
+ geneTrackRowNums,
57
46
  isShown,
58
47
  onMouseDown,
59
48
  onMouseLeave,
@@ -65,6 +54,7 @@ export const LinearApolloSixFrameDisplay = observer(
65
54
  setCollaboratorCanvas,
66
55
  setOverlayCanvas,
67
56
  setTheme,
57
+ showCheckResults,
68
58
  } = model
69
59
  const { classes } = useStyles()
70
60
  const lgv = getContainingView(model) as unknown as LinearGenomeViewModel
@@ -95,12 +85,21 @@ export const LinearApolloSixFrameDisplay = observer(
95
85
  } else {
96
86
  const coord: [number, number] = [event.clientX, event.clientY]
97
87
  setContextCoord(coord)
98
- setContextMenuItems(getContextMenuItems(coord))
88
+ setContextMenuItems(getContextMenuItems(event))
99
89
  }
100
90
  }}
101
91
  >
92
+ {session.isLocked ? (
93
+ <div className={classes.locked} data-testid="lock-icon">
94
+ <LockIcon />
95
+ </div>
96
+ ) : null}
102
97
  {message ? (
103
- <Alert severity="warning" classes={{ message: classes.ellipses }}>
98
+ <Alert
99
+ severity="warning"
100
+ classes={{ message: classes.ellipses }}
101
+ slotProps={{ root: { className: classes.center } }}
102
+ >
104
103
  <Tooltip title={message}>
105
104
  <div>{message}</div>
106
105
  </Tooltip>
@@ -152,9 +151,12 @@ export const LinearApolloSixFrameDisplay = observer(
152
151
  data-testid="overlayCanvas"
153
152
  />
154
153
  {lgv.displayedRegions.flatMap((region, idx) => {
154
+ const widthBp = lgv.bpPerPx * apolloRowHeight
155
155
  const assembly = assemblyManager.get(region.assemblyName)
156
- return [...session.apolloDataStore.checkResults.values()]
157
- .filter(
156
+ if (showCheckResults) {
157
+ const filteredCheckResults = [
158
+ ...session.apolloDataStore.checkResults.values(),
159
+ ].filter(
158
160
  (checkResult) =>
159
161
  assembly?.isValidRefName(checkResult.refSeq) &&
160
162
  assembly.getCanonicalRefName(checkResult.refSeq) ===
@@ -166,33 +168,92 @@ export const LinearApolloSixFrameDisplay = observer(
166
168
  checkResult.end,
167
169
  ),
168
170
  )
169
- .map((checkResult) => {
171
+ const checkResults = clusterResultByMessage<CheckResultI>(
172
+ filteredCheckResults,
173
+ widthBp,
174
+ true,
175
+ )
176
+ return checkResults.map((checkResult) => {
170
177
  const left =
171
178
  (lgv.bpToPx({
172
179
  refName: region.refName,
173
180
  coord: checkResult.start,
174
181
  regionNumber: idx,
175
182
  })?.offsetPx ?? 0) - lgv.offsetPx
176
- const [feature] = checkResult.ids
183
+ const [feature] = checkResult.featureIds
177
184
  if (!feature || !feature.parent?.looksLikeGene) {
178
185
  return null
179
186
  }
180
- const top = 0
187
+
188
+ let row
189
+ for (const loc of feature.cdsLocations) {
190
+ for (const cds of loc) {
191
+ let rowNum: number = getFrame(
192
+ cds.min,
193
+ cds.max,
194
+ feature.strand ?? 1,
195
+ cds.phase,
196
+ )
197
+ rowNum = featureLabelSpacer(
198
+ rowNum < 0 ? -1 * rowNum + 5 : rowNum,
199
+ )
200
+ if (
201
+ checkResult.start >= cds.min &&
202
+ checkResult.start <= cds.max
203
+ ) {
204
+ row = rowNum - 1
205
+ break
206
+ }
207
+ }
208
+ }
209
+ if (row === undefined) {
210
+ const rowNum =
211
+ feature.strand == 1
212
+ ? geneTrackRowNums[0]
213
+ : geneTrackRowNums[1]
214
+ row = rowNum - 1
215
+ }
216
+
217
+ const top = row * apolloRowHeight
181
218
  const height = apolloRowHeight
182
219
  return (
183
220
  <Tooltip
184
221
  key={checkResult._id}
185
222
  title={checkResult.message}
186
223
  >
187
- <Avatar
188
- className={classes.avatar}
189
- style={{ top, left, height, width: height }}
224
+ <Box
225
+ className={classes.box}
226
+ style={{
227
+ top,
228
+ left,
229
+ height,
230
+ width: height,
231
+ pointerEvents: apolloDragging ? 'none' : 'auto',
232
+ }}
190
233
  >
191
- <ErrorIcon />
192
- </Avatar>
234
+ <Badge
235
+ className={classes.badge}
236
+ badgeContent={checkResult.count}
237
+ color="primary"
238
+ overlap="circular"
239
+ anchorOrigin={{
240
+ vertical: 'bottom',
241
+ horizontal: 'right',
242
+ }}
243
+ invisible={checkResult.count <= 1}
244
+ >
245
+ <Avatar className={classes.avatar}>
246
+ <ErrorIcon
247
+ data-testid={`ErrorIcon-${checkResult.start}`}
248
+ />
249
+ </Avatar>
250
+ </Badge>
251
+ </Box>
193
252
  </Tooltip>
194
253
  )
195
254
  })
255
+ }
256
+ return null
196
257
  })}
197
258
  <Menu
198
259
  open={contextMenuItems.length > 0}
@@ -203,9 +264,11 @@ export const LinearApolloSixFrameDisplay = observer(
203
264
  onClose={() => {
204
265
  setContextMenuItems([])
205
266
  }}
206
- TransitionProps={{
207
- onExit: () => {
208
- setContextMenuItems([])
267
+ slotProps={{
268
+ transition: {
269
+ onExit: () => {
270
+ setContextMenuItems([])
271
+ },
209
272
  },
210
273
  }}
211
274
  anchorReference="anchorPosition"