@apollo-annotation/jbrowse-plugin-apollo 0.3.6 → 0.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 (84) hide show
  1. package/dist/index.esm.js +4603 -2045
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +4611 -2039
  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 +9387 -4016
  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 +15 -15
  12. package/src/ApolloInternetAccount/model.ts +48 -13
  13. package/src/BackendDrivers/CollaborationServerDriver.ts +23 -2
  14. package/src/ChangeManager.ts +42 -18
  15. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +64 -5
  16. package/src/FeatureDetailsWidget/Attributes.tsx +8 -3
  17. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +70 -81
  18. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +946 -190
  19. package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +4 -0
  20. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +61 -73
  21. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +55 -211
  22. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +562 -108
  23. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +78 -14
  24. package/src/LinearApolloDisplay/glyphs/Glyph.ts +15 -9
  25. package/src/LinearApolloDisplay/stateModel/base.ts +63 -43
  26. package/src/LinearApolloDisplay/stateModel/layouts.ts +3 -2
  27. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +79 -292
  28. package/src/LinearApolloDisplay/stateModel/rendering.ts +45 -344
  29. package/src/LinearApolloReferenceSequenceDisplay/components/LinearApolloReferenceSequenceDisplay.tsx +87 -0
  30. package/src/LinearApolloReferenceSequenceDisplay/components/index.ts +1 -0
  31. package/src/LinearApolloReferenceSequenceDisplay/configSchema.ts +7 -0
  32. package/src/LinearApolloReferenceSequenceDisplay/index.ts +3 -0
  33. package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +227 -0
  34. package/src/LinearApolloReferenceSequenceDisplay/stateModel/index.ts +25 -0
  35. package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +481 -0
  36. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +102 -40
  37. package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +12 -20
  38. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +382 -243
  39. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +12 -8
  40. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +83 -4
  41. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +23 -11
  42. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +118 -123
  43. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +53 -63
  44. package/src/OntologyManager/index.ts +4 -1
  45. package/src/TabularEditor/HybridGrid/Feature.tsx +20 -14
  46. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +7 -5
  47. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +108 -16
  48. package/src/components/AddAssembly.tsx +1 -1
  49. package/src/components/AddAssemblyAliases.tsx +114 -0
  50. package/src/components/AddChildFeature.tsx +7 -7
  51. package/src/components/AddFeature.tsx +20 -15
  52. package/src/components/AddRefSeqAliases.tsx +9 -9
  53. package/src/components/CopyFeature.tsx +4 -4
  54. package/src/components/CreateApolloAnnotation.tsx +335 -151
  55. package/src/components/DeleteAssembly.tsx +1 -1
  56. package/src/components/DeleteFeature.tsx +358 -11
  57. package/src/components/DownloadGFF3.tsx +20 -1
  58. package/src/components/EditZoomThresholdDialog.tsx +69 -0
  59. package/src/components/FilterFeatures.tsx +7 -7
  60. package/src/components/FilterTranscripts.tsx +86 -0
  61. package/src/components/ImportFeatures.tsx +1 -1
  62. package/src/components/ManageChecks.tsx +1 -1
  63. package/src/components/MergeExons.tsx +193 -0
  64. package/src/components/MergeTranscripts.tsx +182 -0
  65. package/src/components/OntologyTermMultiSelect.tsx +11 -11
  66. package/src/components/OpenLocalFile.tsx +11 -7
  67. package/src/components/SplitExon.tsx +134 -0
  68. package/src/components/ViewCheckResults.tsx +1 -1
  69. package/src/components/index.ts +4 -0
  70. package/src/config.ts +11 -0
  71. package/src/extensions/annotationFromJBrowseFeature.ts +2 -0
  72. package/src/extensions/annotationFromPileup.ts +99 -89
  73. package/src/index.ts +42 -105
  74. package/src/makeDisplayComponent.tsx +0 -1
  75. package/src/menus/index.ts +1 -0
  76. package/src/{ApolloInternetAccount/addMenuItems.ts → menus/topLevelMenu.ts} +60 -33
  77. package/src/menus/topLevelMenuAdmin.ts +154 -0
  78. package/src/session/session.ts +163 -104
  79. package/src/util/annotationFeatureUtils.ts +59 -0
  80. package/src/util/copyToClipboard.ts +21 -0
  81. package/src/util/displayUtils.ts +149 -0
  82. package/src/util/glyphUtils.ts +201 -0
  83. package/src/util/index.ts +2 -0
  84. package/src/util/mouseEventsUtils.ts +145 -0
@@ -1,19 +1,25 @@
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 { Alert, Avatar, Badge, Box, Tooltip, useTheme } from '@mui/material'
13
15
  import { observer } from 'mobx-react'
14
16
  import React, { useEffect, useState } from 'react'
15
- import { makeStyles } from 'tss-react/mui'
16
17
 
18
+ import {
19
+ type Coord,
20
+ clusterResultByMessage,
21
+ useStyles,
22
+ } from '../../util/displayUtils'
17
23
  import { type LinearApolloSixFrameDisplay as LinearApolloSixFrameDisplayI } from '../stateModel'
18
24
 
19
25
  import { TrackLines } from './TrackLines'
@@ -21,31 +27,11 @@ import { TrackLines } from './TrackLines'
21
27
  interface LinearApolloSixFrameDisplayProps {
22
28
  model: LinearApolloSixFrameDisplayI
23
29
  }
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
30
 
46
31
  export const LinearApolloSixFrameDisplay = observer(
47
32
  function LinearApolloSixFrameDisplay(
48
33
  props: LinearApolloSixFrameDisplayProps,
34
+ apolloDragging,
49
35
  ) {
50
36
  const theme = useTheme()
51
37
  const { model } = props
@@ -54,6 +40,8 @@ export const LinearApolloSixFrameDisplay = observer(
54
40
  contextMenuItems: getContextMenuItems,
55
41
  cursor,
56
42
  featuresHeight,
43
+ featureLabelSpacer,
44
+ geneTrackRowNums,
57
45
  isShown,
58
46
  onMouseDown,
59
47
  onMouseLeave,
@@ -65,6 +53,7 @@ export const LinearApolloSixFrameDisplay = observer(
65
53
  setCollaboratorCanvas,
66
54
  setOverlayCanvas,
67
55
  setTheme,
56
+ showCheckResults,
68
57
  } = model
69
58
  const { classes } = useStyles()
70
59
  const lgv = getContainingView(model) as unknown as LinearGenomeViewModel
@@ -95,12 +84,16 @@ export const LinearApolloSixFrameDisplay = observer(
95
84
  } else {
96
85
  const coord: [number, number] = [event.clientX, event.clientY]
97
86
  setContextCoord(coord)
98
- setContextMenuItems(getContextMenuItems(coord))
87
+ setContextMenuItems(getContextMenuItems(event))
99
88
  }
100
89
  }}
101
90
  >
102
91
  {message ? (
103
- <Alert severity="warning" classes={{ message: classes.ellipses }}>
92
+ <Alert
93
+ severity="warning"
94
+ classes={{ message: classes.ellipses }}
95
+ slotProps={{ root: { className: classes.center } }}
96
+ >
104
97
  <Tooltip title={message}>
105
98
  <div>{message}</div>
106
99
  </Tooltip>
@@ -109,8 +102,13 @@ export const LinearApolloSixFrameDisplay = observer(
109
102
  // Promise.resolve() in these 3 callbacks is to avoid infinite rendering loop
110
103
  // https://github.com/mobxjs/mobx/issues/3728#issuecomment-1715400931
111
104
  <>
112
- <TrackLines model={model} strand={1} />
113
- <TrackLines model={model} strand={-1} />
105
+ <TrackLines model={model} idx={0} />
106
+ <TrackLines
107
+ model={model}
108
+ hrStyle={{ margin: 0, top: 0, color: 'grey', opacity: 0.4 }}
109
+ idx={1}
110
+ />
111
+ <TrackLines model={model} idx={2} />
114
112
  <canvas
115
113
  ref={async (node: HTMLCanvasElement) => {
116
114
  await Promise.resolve()
@@ -147,9 +145,12 @@ export const LinearApolloSixFrameDisplay = observer(
147
145
  data-testid="overlayCanvas"
148
146
  />
149
147
  {lgv.displayedRegions.flatMap((region, idx) => {
148
+ const widthBp = lgv.bpPerPx * apolloRowHeight
150
149
  const assembly = assemblyManager.get(region.assemblyName)
151
- return [...session.apolloDataStore.checkResults.values()]
152
- .filter(
150
+ if (showCheckResults) {
151
+ const filteredCheckResults = [
152
+ ...session.apolloDataStore.checkResults.values(),
153
+ ].filter(
153
154
  (checkResult) =>
154
155
  assembly?.isValidRefName(checkResult.refSeq) &&
155
156
  assembly.getCanonicalRefName(checkResult.refSeq) ===
@@ -161,33 +162,92 @@ export const LinearApolloSixFrameDisplay = observer(
161
162
  checkResult.end,
162
163
  ),
163
164
  )
164
- .map((checkResult) => {
165
+ const checkResults = clusterResultByMessage<CheckResultI>(
166
+ filteredCheckResults,
167
+ widthBp,
168
+ true,
169
+ )
170
+ return checkResults.map((checkResult) => {
165
171
  const left =
166
172
  (lgv.bpToPx({
167
173
  refName: region.refName,
168
174
  coord: checkResult.start,
169
175
  regionNumber: idx,
170
176
  })?.offsetPx ?? 0) - lgv.offsetPx
171
- const [feature] = checkResult.ids
177
+ const [feature] = checkResult.featureIds
172
178
  if (!feature || !feature.parent?.looksLikeGene) {
173
179
  return null
174
180
  }
175
- const top = 0
181
+
182
+ let row
183
+ for (const loc of feature.cdsLocations) {
184
+ for (const cds of loc) {
185
+ let rowNum: number = getFrame(
186
+ cds.min,
187
+ cds.max,
188
+ feature.strand ?? 1,
189
+ cds.phase,
190
+ )
191
+ rowNum = featureLabelSpacer(
192
+ rowNum < 0 ? -1 * rowNum + 5 : rowNum,
193
+ )
194
+ if (
195
+ checkResult.start >= cds.min &&
196
+ checkResult.start <= cds.max
197
+ ) {
198
+ row = rowNum - 1
199
+ break
200
+ }
201
+ }
202
+ }
203
+ if (row === undefined) {
204
+ const rowNum =
205
+ feature.strand == 1
206
+ ? geneTrackRowNums[0]
207
+ : geneTrackRowNums[1]
208
+ row = rowNum - 1
209
+ }
210
+
211
+ const top = row * apolloRowHeight
176
212
  const height = apolloRowHeight
177
213
  return (
178
214
  <Tooltip
179
215
  key={checkResult._id}
180
216
  title={checkResult.message}
181
217
  >
182
- <Avatar
183
- className={classes.avatar}
184
- style={{ top, left, height, width: height }}
218
+ <Box
219
+ className={classes.box}
220
+ style={{
221
+ top,
222
+ left,
223
+ height,
224
+ width: height,
225
+ pointerEvents: apolloDragging ? 'none' : 'auto',
226
+ }}
185
227
  >
186
- <ErrorIcon />
187
- </Avatar>
228
+ <Badge
229
+ className={classes.badge}
230
+ badgeContent={checkResult.count}
231
+ color="primary"
232
+ overlap="circular"
233
+ anchorOrigin={{
234
+ vertical: 'bottom',
235
+ horizontal: 'right',
236
+ }}
237
+ invisible={checkResult.count <= 1}
238
+ >
239
+ <Avatar className={classes.avatar}>
240
+ <ErrorIcon
241
+ data-testid={`ErrorIcon-${checkResult.start}`}
242
+ />
243
+ </Avatar>
244
+ </Badge>
245
+ </Box>
188
246
  </Tooltip>
189
247
  )
190
248
  })
249
+ }
250
+ return null
191
251
  })}
192
252
  <Menu
193
253
  open={contextMenuItems.length > 0}
@@ -198,9 +258,11 @@ export const LinearApolloSixFrameDisplay = observer(
198
258
  onClose={() => {
199
259
  setContextMenuItems([])
200
260
  }}
201
- TransitionProps={{
202
- onExit: () => {
203
- setContextMenuItems([])
261
+ slotProps={{
262
+ transition: {
263
+ onExit: () => {
264
+ setContextMenuItems([])
265
+ },
204
266
  },
205
267
  }}
206
268
  anchorReference="anchorPosition"
@@ -5,36 +5,28 @@ import { type LinearApolloSixFrameDisplay } from '../stateModel'
5
5
 
6
6
  export const TrackLines = observer(function TrackLines({
7
7
  model,
8
- strand,
8
+ hrStyle = { margin: 0, top: 0, color: 'black' },
9
+ idx = 0,
9
10
  }: {
10
11
  model: LinearApolloSixFrameDisplay
11
- strand: number
12
+ hrStyle?: React.CSSProperties
13
+ idx: number
12
14
  }) {
13
- const { apolloRowHeight, highestRow, lastRowTooltipBufferHeight } = model
14
- return strand == 1 ? (
15
- <div
16
- style={{
17
- position: 'absolute',
18
- left: 0,
19
- top: (apolloRowHeight * (highestRow + 1)) / 2 - 2,
20
- width: '100%',
21
- }}
22
- >
23
- <hr style={{ margin: 0, top: 0, color: 'black' }} />
24
- </div>
25
- ) : (
15
+ const { apolloRowHeight, highestRow, showFeatureLabels } = model
16
+ const featureLabelSpacer = showFeatureLabels ? 2 : 1
17
+
18
+ return (
26
19
  <div
27
20
  style={{
28
21
  position: 'absolute',
29
22
  left: 0,
30
- bottom:
31
- (apolloRowHeight * (highestRow + 1) + lastRowTooltipBufferHeight) /
32
- 2 +
33
- 3,
23
+ top:
24
+ (apolloRowHeight * featureLabelSpacer * (highestRow + 1)) / 2 +
25
+ idx * featureLabelSpacer * apolloRowHeight,
34
26
  width: '100%',
35
27
  }}
36
28
  >
37
- <hr style={{ margin: 0, top: 0, color: 'black' }} />
29
+ <hr style={hrStyle} />
38
30
  </div>
39
31
  )
40
32
  })