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

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 (136) hide show
  1. package/dist/index.esm.js +6964 -4598
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +6610 -4261
  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 +11563 -7493
  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 +4 -4
  12. package/src/ApolloInternetAccount/addMenuItems.ts +23 -2
  13. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
  14. package/src/ApolloInternetAccount/components/LoginButtons.tsx +1 -1
  15. package/src/ApolloInternetAccount/components/LoginIcons.tsx +1 -1
  16. package/src/ApolloInternetAccount/configSchema.ts +1 -1
  17. package/src/ApolloInternetAccount/model.ts +11 -10
  18. package/src/ApolloJobModel.ts +1 -1
  19. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +8 -6
  20. package/src/ApolloRefNameAliasAdapter/index.ts +2 -2
  21. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +4 -4
  22. package/src/ApolloSequenceAdapter/index.ts +1 -1
  23. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +8 -7
  24. package/src/ApolloTextSearchAdapter/index.ts +1 -1
  25. package/src/BackendDrivers/BackendDriver.ts +7 -7
  26. package/src/BackendDrivers/CollaborationServerDriver.ts +14 -10
  27. package/src/BackendDrivers/DesktopFileDriver.ts +11 -10
  28. package/src/BackendDrivers/InMemoryFileDriver.ts +10 -6
  29. package/src/ChangeManager.ts +15 -11
  30. package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +8 -7
  31. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +35 -14
  32. package/src/FeatureDetailsWidget/AttributeKey.tsx +50 -0
  33. package/src/FeatureDetailsWidget/AttributeKeySelector.tsx +104 -0
  34. package/src/FeatureDetailsWidget/Attributes.tsx +215 -367
  35. package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -5
  36. package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +104 -0
  37. package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +22 -0
  38. package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +4 -4
  39. package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -1
  40. package/src/FeatureDetailsWidget/Sequence.tsx +2 -2
  41. package/src/FeatureDetailsWidget/StringTextField.tsx +1 -1
  42. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +15 -23
  43. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +950 -196
  44. package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +8 -4
  45. package/src/FeatureDetailsWidget/model.ts +8 -3
  46. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +7 -7
  47. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +59 -72
  48. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +253 -60
  49. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +52 -6
  50. package/src/LinearApolloDisplay/glyphs/Glyph.ts +16 -8
  51. package/src/LinearApolloDisplay/stateModel/base.ts +81 -10
  52. package/src/LinearApolloDisplay/stateModel/index.ts +4 -3
  53. package/src/LinearApolloDisplay/stateModel/layouts.ts +8 -39
  54. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +63 -46
  55. package/src/LinearApolloDisplay/stateModel/rendering.ts +60 -31
  56. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +226 -0
  57. package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +32 -0
  58. package/src/LinearApolloSixFrameDisplay/components/index.ts +2 -0
  59. package/src/LinearApolloSixFrameDisplay/configSchema.ts +7 -0
  60. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +940 -0
  61. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +63 -0
  62. package/src/LinearApolloSixFrameDisplay/glyphs/index.ts +1 -0
  63. package/src/LinearApolloSixFrameDisplay/index.ts +2 -0
  64. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +302 -0
  65. package/src/LinearApolloSixFrameDisplay/stateModel/index.ts +27 -0
  66. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +252 -0
  67. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +368 -0
  68. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +201 -0
  69. package/src/LinearApolloSixFrameDisplay/types.ts +1 -0
  70. package/src/OntologyManager/OntologyStore/fulltext.test.ts +1 -1
  71. package/src/OntologyManager/OntologyStore/fulltext.ts +8 -3
  72. package/src/OntologyManager/OntologyStore/index.test.ts +3 -1
  73. package/src/OntologyManager/OntologyStore/index.ts +19 -14
  74. package/src/OntologyManager/OntologyStore/indexeddb-schema.ts +6 -5
  75. package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +11 -5
  76. package/src/OntologyManager/index.ts +12 -7
  77. package/src/OntologyManager/util.ts +3 -2
  78. package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
  79. package/src/TabularEditor/HybridGrid/Feature.tsx +13 -7
  80. package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +1 -1
  81. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +3 -2
  82. package/src/TabularEditor/HybridGrid/ToolBar.tsx +1 -1
  83. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +114 -22
  84. package/src/TabularEditor/TabularEditorPane.tsx +1 -1
  85. package/src/TabularEditor/model.ts +2 -2
  86. package/src/TabularEditor/types.ts +5 -2
  87. package/src/components/AddAssembly.tsx +182 -179
  88. package/src/components/AddAssemblyAliases.tsx +114 -0
  89. package/src/components/AddChildFeature.tsx +8 -10
  90. package/src/components/AddFeature.tsx +216 -44
  91. package/src/components/AddRefSeqAliases.tsx +14 -12
  92. package/src/components/CopyFeature.tsx +10 -11
  93. package/src/components/CreateApolloAnnotation.tsx +342 -158
  94. package/src/components/DeleteAssembly.tsx +9 -8
  95. package/src/components/DeleteFeature.tsx +362 -14
  96. package/src/components/Dialog.tsx +1 -1
  97. package/src/components/DownloadGFF3.tsx +31 -11
  98. package/src/components/FilterFeatures.tsx +6 -4
  99. package/src/components/FilterTranscripts.tsx +86 -0
  100. package/src/components/ImportFeatures.tsx +7 -6
  101. package/src/components/LogOut.tsx +5 -4
  102. package/src/components/ManageChecks.tsx +9 -8
  103. package/src/components/ManageUsers.tsx +11 -10
  104. package/src/components/MergeExons.tsx +193 -0
  105. package/src/components/MergeTranscripts.tsx +185 -0
  106. package/src/components/OntologyTermAutocomplete.tsx +5 -5
  107. package/src/components/OntologyTermMultiSelect.tsx +6 -6
  108. package/src/components/OpenLocalFile.tsx +4 -3
  109. package/src/components/SplitExon.tsx +134 -0
  110. package/src/components/ViewChangeLog.tsx +7 -6
  111. package/src/components/ViewCheckResults.tsx +8 -7
  112. package/src/components/index.ts +3 -0
  113. package/src/config.ts +5 -0
  114. package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -0
  115. package/src/extensions/annotationFromJBrowseFeature.ts +13 -10
  116. package/src/extensions/annotationFromPileup.ts +104 -94
  117. package/src/index.ts +33 -50
  118. package/src/makeDisplayComponent.tsx +90 -37
  119. package/src/session/ClientDataStore.ts +21 -17
  120. package/src/session/session.ts +46 -39
  121. package/src/types.ts +4 -4
  122. package/src/util/annotationFeatureUtils.ts +66 -1
  123. package/src/util/copyToClipboard.ts +21 -0
  124. package/src/util/glyphUtils.ts +49 -0
  125. package/src/util/index.ts +5 -3
  126. package/src/util/loadAssemblyIntoClient.ts +10 -3
  127. package/src/util/mouseEventsUtils.ts +113 -0
  128. package/src/ApolloSixFrameRenderer/ApolloSixFrameRenderer.tsx +0 -13
  129. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +0 -707
  130. package/src/ApolloSixFrameRenderer/configSchema.ts +0 -7
  131. package/src/ApolloSixFrameRenderer/index.ts +0 -3
  132. package/src/SixFrameFeatureDisplay/components/TrackLines.tsx +0 -19
  133. package/src/SixFrameFeatureDisplay/components/index.ts +0 -1
  134. package/src/SixFrameFeatureDisplay/configSchema.ts +0 -21
  135. package/src/SixFrameFeatureDisplay/index.ts +0 -2
  136. package/src/SixFrameFeatureDisplay/stateModel.ts +0 -443
@@ -1,707 +0,0 @@
1
- /* eslint-disable react-hooks/exhaustive-deps */
2
- /* eslint-disable @typescript-eslint/unbound-method */
3
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
- /* eslint-disable @typescript-eslint/no-unsafe-call */
5
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
6
- /* eslint-disable @typescript-eslint/no-unnecessary-condition */
7
- /* eslint-disable @typescript-eslint/no-misused-promises */
8
- import { AnnotationFeature } from '@apollo-annotation/mst'
9
- import {
10
- LocationEndChange,
11
- LocationStartChange,
12
- } from '@apollo-annotation/shared'
13
- import { getConf } from '@jbrowse/core/configuration'
14
- import { AbstractSessionModel, Region, getSession } from '@jbrowse/core/util'
15
- import { Menu, MenuItem } from '@mui/material'
16
- import { autorun, toJS } from 'mobx'
17
- import { observer } from 'mobx-react'
18
- import { getRoot, getSnapshot } from 'mobx-state-tree'
19
- import React, { useEffect, useMemo, useRef, useState } from 'react'
20
-
21
- import { ApolloInternetAccountModel } from '../../ApolloInternetAccount/model'
22
- import { AddChildFeature } from '../../components/AddChildFeature'
23
- import { CopyFeature } from '../../components/CopyFeature'
24
- import { DeleteFeature } from '../../components/DeleteFeature'
25
- import { Collaborator } from '../../session'
26
- import { SixFrameFeatureDisplay } from '../../SixFrameFeatureDisplay/stateModel'
27
- import { ApolloRootModel } from '../../types'
28
-
29
- interface ApolloRenderingProps {
30
- assemblyName: string
31
- regions: Region[]
32
- bpPerPx: number
33
- displayModel: SixFrameFeatureDisplay
34
- blockKey: string
35
- }
36
-
37
- function draw(
38
- ctx: CanvasRenderingContext2D,
39
- xOffset: number,
40
- yOffset: number,
41
- width: number,
42
- bpPerPx: number,
43
- rowHeight: number,
44
- ) {
45
- const widthPx = width / bpPerPx
46
- ctx.fillStyle = 'black'
47
- ctx.fillRect(xOffset, yOffset, widthPx, rowHeight)
48
- if (widthPx > 2) {
49
- ctx.clearRect(xOffset + 1, yOffset + 1, widthPx - 2, rowHeight - 2)
50
- ctx.fillStyle = 'rgba(255,255,255,0.75)'
51
- ctx.fillRect(xOffset + 1, yOffset + 1, widthPx - 2, rowHeight - 2)
52
- // ctx.fillStyle = 'black'
53
- // ctx.fillText(
54
- // 'CDS',
55
- // xOffset + startPx + 1,
56
- // yOffset + 11,
57
- // widthPx - 2,
58
- // )
59
- }
60
- }
61
-
62
- type Coord = [number, number]
63
-
64
- /**
65
- * Use the golden ratio to generate distinct colors for a given integer
66
- * See https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
67
- * @param number -
68
- * @returns HSL string
69
- */
70
- function selectColor(number: number) {
71
- const goldenAngle = 180 * (3 - Math.sqrt(5))
72
- const hue = number * goldenAngle + 60
73
- return `hsl(${hue},100%,50%)`
74
- }
75
-
76
- function ApolloRendering(props: ApolloRenderingProps) {
77
- const [contextCoord, setContextCoord] = useState<Coord>()
78
- const [contextMenuFeature, setContextMenuFeature] =
79
- useState<AnnotationFeature>()
80
-
81
- const canvasRef = useRef<HTMLCanvasElement>(null)
82
- const overlayCanvasRef = useRef<HTMLCanvasElement>(null)
83
- const codonCanvasRef = useRef<HTMLCanvasElement>(null)
84
- const [isAdmin, setIsAdmin] = useState<boolean>(false)
85
- const [isReadOnly, setIsReadOnly] = useState<boolean>(true)
86
- // const [overEdge, setOverEdge] = useState<'start' | 'end'>()
87
- const [dragging, setDragging] = useState<{
88
- edge: 'start' | 'end'
89
- feature: AnnotationFeature
90
- row: number
91
- bp: number
92
- px: number
93
- }>()
94
- const [movedDuringLastMouseDown, setMovedDuringLastMouseDown] =
95
- useState(false)
96
- const [collaborators, setCollaborators] = useState<Collaborator[]>([])
97
-
98
- const { bpPerPx, displayModel, regions } = props
99
- const { session } = displayModel
100
- const { collaborators: collabs } = session
101
-
102
- // bridging mobx observability and React useEffect observability
103
-
104
- useEffect(
105
- () =>
106
- autorun(() => {
107
- setCollaborators(toJS(collabs))
108
- }),
109
- [],
110
- )
111
-
112
- const [region] = regions
113
- const totalWidth = (region.end - region.start) / bpPerPx
114
- const {
115
- apolloFeatureUnderMouse,
116
- apolloRowHeight: height,
117
- apolloRowUnderMouse,
118
- changeManager,
119
- codonLayout,
120
- featureLayout,
121
- features,
122
- featuresHeight: totalHeight,
123
- getAssemblyId,
124
- selectedFeature,
125
- setApolloFeatureUnderMouse,
126
- setApolloRowUnderMouse,
127
- setSelectedFeature,
128
- showIntronLines: showLines,
129
- showStartCodons: showStarts,
130
- showStopCodons: showStops,
131
- } = displayModel
132
- // use this to convince useEffect that the features really did change
133
- const featureSnap = [...features.values()].map((a) =>
134
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
135
- // @ts-expect-error
136
- [...a.values()].map((f) => getSnapshot(f)),
137
- )
138
-
139
- const apolloInternetAccount = useMemo(() => {
140
- const { internetAccounts } = getRoot<ApolloRootModel>(session)
141
- const { assemblyName } = region
142
- const { assemblyManager } = getSession(displayModel)
143
- const assembly = assemblyManager.get(assemblyName)
144
- if (!assembly) {
145
- throw new Error(`No assembly found with name ${assemblyName}`)
146
- }
147
- const { internetAccountConfigId } = getConf(assembly, [
148
- 'sequence',
149
- 'metadata',
150
- ]) as { internetAccountConfigId: string }
151
- const matchingAccount = internetAccounts.find(
152
- (ia) => getConf(ia, 'internetAccountId') === internetAccountConfigId,
153
- ) as ApolloInternetAccountModel | undefined
154
- if (!matchingAccount) {
155
- throw new Error(
156
- `No InternetAccount found with config id ${internetAccountConfigId}`,
157
- )
158
- }
159
- return matchingAccount
160
- }, [displayModel, region, session])
161
-
162
- const { role } = apolloInternetAccount
163
-
164
- useEffect(() => {
165
- if (role?.includes('admin')) {
166
- setIsAdmin(true)
167
- }
168
- if (role?.includes('admin') ?? role?.includes('user')) {
169
- setIsReadOnly(false)
170
- }
171
- }, [role])
172
-
173
- useEffect(() => {
174
- // if (!isAlive(region)) {
175
- // return
176
- // }
177
- const canvas = canvasRef.current
178
- if (!canvas) {
179
- return
180
- }
181
- const ctx = canvas.getContext('2d')
182
- if (!ctx) {
183
- return
184
- }
185
- const transcript: Record<string, [number, number][]> = {}
186
- ctx.clearRect(0, 0, totalWidth, totalHeight)
187
- for (const [row, featureInfos] of featureLayout) {
188
- for (const [parentID, feature] of featureInfos) {
189
- const start = region.reversed
190
- ? region.end - feature.max
191
- : feature.min - region.start - 1
192
- const end = feature.max - region.start - 1
193
- const startPx = start / bpPerPx
194
- const endPx = end / bpPerPx
195
- const width = end - start
196
- draw(ctx, startPx, row * height, width, bpPerPx, height)
197
- const lineY = row * height + height / 2
198
- if (!transcript[parentID]) {
199
- transcript[parentID] = []
200
- }
201
- if (
202
- !transcript[parentID].some(
203
- (el) => el[0] === startPx && el[1] === lineY,
204
- )
205
- ) {
206
- transcript[parentID].push([startPx, lineY])
207
- }
208
- if (
209
- !transcript[parentID].some((el) => el[0] === endPx && el[1] === lineY)
210
- ) {
211
- transcript[parentID].push([endPx, lineY])
212
- }
213
- }
214
- }
215
- if (showLines) {
216
- let offset = -Math.floor(Object.keys(transcript).length / 2)
217
- for (const pid in transcript) {
218
- ctx.strokeStyle = selectColor(offset)
219
- const sortedCoords = transcript[pid].sort((a, b) => {
220
- return a[0] - b[0]
221
- })
222
- let [prevCoords] = sortedCoords
223
- for (const [index, coords] of sortedCoords.entries()) {
224
- if (index === 0) {
225
- continue
226
- }
227
- if (index % 2 === 0) {
228
- /** Mid-point for intron line "hat" */
229
- const midPoint: [number, number] = [
230
- (coords[0] - prevCoords[0]) / 2 + prevCoords[0],
231
- Math.max(
232
- 1, // Avoid render ceiling
233
- Math.min(prevCoords[1], coords[1]) - height / 2 + offset * 2,
234
- ),
235
- ]
236
- ctx.beginPath()
237
- ctx.moveTo(prevCoords[0], prevCoords[1] + offset * 2)
238
- ctx.lineTo(...midPoint)
239
- ctx.stroke()
240
- ctx.moveTo(...midPoint)
241
- ctx.lineTo(coords[0], coords[1] + offset * 2)
242
- ctx.stroke()
243
- }
244
- prevCoords = coords
245
- }
246
- offset += 1
247
- }
248
- }
249
- }, [
250
- showLines,
251
- region,
252
- bpPerPx,
253
- region.start,
254
- region.end,
255
- region.reversed,
256
- totalWidth,
257
- featureLayout,
258
- totalHeight,
259
- features,
260
- height,
261
- featureSnap,
262
- ])
263
- useEffect(() => {
264
- // if (!isAlive(region)) {
265
- // return
266
- // }
267
- const canvas = codonCanvasRef.current
268
- if (!canvas) {
269
- return
270
- }
271
- const ctx = canvas.getContext('2d')
272
- if (!ctx) {
273
- return
274
- }
275
-
276
- ctx.clearRect(0, 0, totalWidth, totalHeight)
277
- for (const [row, { starts, stops }] of codonLayout) {
278
- const scale = bpPerPx
279
- for (const start of starts) {
280
- const x = start / scale
281
- if (region.start / scale <= x && x <= region.end / scale) {
282
- ctx.fillStyle = 'rgba(255,0,255,1)'
283
- if (showStarts) {
284
- ctx.fillRect(
285
- Math.round(x - 0.5 - region.start / scale),
286
- row * height,
287
- 1,
288
- height,
289
- )
290
- } else {
291
- ctx.clearRect(
292
- Math.round(x - 0.5 - region.start / scale),
293
- row * height,
294
- 1,
295
- height,
296
- )
297
- }
298
- }
299
- }
300
- for (const start of stops) {
301
- const x = start / scale
302
- if (region.start / scale <= x && x <= region.end / scale) {
303
- ctx.fillStyle = 'black'
304
- if (showStops) {
305
- ctx.fillRect(
306
- Math.round(x - 0.5 - region.start / scale),
307
- row * height,
308
- 1,
309
- height,
310
- )
311
- } else {
312
- ctx.clearRect(
313
- Math.round(x - 0.5 - region.start / scale),
314
- row * height,
315
- 1,
316
- height,
317
- )
318
- }
319
- }
320
- }
321
- }
322
- }, [
323
- showStarts,
324
- showStops,
325
- codonLayout,
326
- totalWidth,
327
- totalHeight,
328
- bpPerPx,
329
- height,
330
- region,
331
- region.start,
332
- region.end,
333
- ])
334
-
335
- useEffect(() => {
336
- // if (!isAlive(region)) {
337
- // return
338
- // }
339
- const canvas = overlayCanvasRef.current
340
- if (!canvas) {
341
- return
342
- }
343
- const ctx = canvas.getContext('2d')
344
- if (!ctx) {
345
- return
346
- }
347
- ctx.clearRect(0, 0, totalWidth, totalHeight)
348
- // if (dragging) {
349
- // const { feature, row, edge, px } = dragging
350
- // const featureEdge = region.reversed
351
- // ? region.end - feature[edge]
352
- // : feature[edge] - region.start
353
- // const featureEdgePx = featureEdge / bpPerPx
354
- // const startPx = Math.min(px, featureEdgePx)
355
- // const widthPx = Math.abs(px - featureEdgePx)
356
- // ctx.strokeStyle = 'red'
357
- // ctx.setLineDash([6])
358
- // ctx.strokeRect(startPx, row * height, widthPx, height * feature.rowCount)
359
- // ctx.fillStyle = 'rgba(255,0,0,.2)'
360
- // ctx.fillRect(startPx, row * height, widthPx, height * feature.rowCount)
361
- // }
362
- // const feature = dragging?.feature || apolloFeatureUnderMouse
363
- // const row = dragging?.row || apolloRowUnderMouse
364
- // if (feature && row !== undefined) {
365
- // const start = region.reversed
366
- // ? region.end - feature.end
367
- // : feature.start - region.start - 1
368
- // const width = feature.length
369
- // const startPx = start / bpPerPx
370
- // const widthPx = width / bpPerPx
371
- // ctx.fillStyle = 'rgba(0,0,0,0.2)'
372
- // ctx.fillRect(startPx, row * height, widthPx, height * feature.rowCount)
373
- // }
374
- for (const collaborator of collaborators) {
375
- const { locations } = collaborator
376
- if (locations.length === 0) {
377
- return
378
- }
379
- for (const location of locations) {
380
- const { end, start } = location
381
- const locationStart = region.reversed
382
- ? region.end - start
383
- : start - region.start
384
- const locationStartPx = locationStart / bpPerPx
385
- const locationWidthPx = (end - start) / bpPerPx
386
- ctx.fillStyle = 'rgba(0,255,0,.2)'
387
- ctx.fillRect(locationStartPx, 1, locationWidthPx, 100)
388
- ctx.fillStyle = 'black'
389
- ctx.fillText(
390
- collaborator.name,
391
- locationStartPx + 1,
392
- 11,
393
- locationWidthPx - 2,
394
- )
395
- }
396
- }
397
- }, [
398
- apolloFeatureUnderMouse,
399
- apolloRowUnderMouse,
400
- bpPerPx,
401
- totalHeight,
402
- totalWidth,
403
- region,
404
- region.start,
405
- region.end,
406
- region.reversed,
407
- dragging,
408
- height,
409
- collaborators,
410
- ])
411
-
412
- // function onMouseMove(event: React.MouseEvent<HTMLCanvasElement, MouseEvent>) {
413
- // // if (!isAlive(region)) {
414
- // // return
415
- // // }
416
- // const { clientX, clientY, buttons } = event
417
- // if (!movedDuringLastMouseDown && buttons === 1) {
418
- // setMovedDuringLastMouseDown(true)
419
- // }
420
- // const { left, top } = canvasRef.current?.getBoundingClientRect() || {
421
- // left: 0,
422
- // top: 0,
423
- // }
424
- // // get pixel coordinates within the whole canvas
425
- // let x = clientX - left
426
- // x = region.reversed ? totalWidth - x : x
427
- // const y = clientY - top
428
-
429
- // if (dragging) {
430
- // const { edge, feature, row } = dragging
431
- // let px = region.reversed ? totalWidth - x : x
432
- // let bp = region.start + x * bpPerPx
433
- // if (edge === 'start' && bp > feature.end - 1) {
434
- // bp = feature.end - 1
435
- // px = (region.reversed ? region.end - bp : bp - region.start) / bpPerPx
436
- // } else if (edge === 'end' && bp < feature.start + 1) {
437
- // bp = feature.start + 1
438
- // px = (region.reversed ? region.end - bp : bp - region.start) / bpPerPx
439
- // }
440
- // setDragging({
441
- // edge,
442
- // feature,
443
- // row,
444
- // px,
445
- // bp,
446
- // })
447
- // return
448
- // }
449
-
450
- // const row = Math.floor(y / height)
451
- // if (row === undefined) {
452
- // setApolloFeatureUnderMouse(undefined)
453
- // setApolloRowUnderMouse(undefined)
454
- // return
455
- // }
456
- // const layoutRow = featureLayout.get(row)
457
- // if (!layoutRow) {
458
- // setApolloFeatureUnderMouse(undefined)
459
- // setApolloRowUnderMouse(undefined)
460
- // return
461
- // }
462
- // const bp = region.start + bpPerPx * x
463
- // // eslint-disable-next-line @typescript-eslint/no-unused-vars
464
- // const [parentID, feat] =
465
- // layoutRow.find((f) => bp >= f[1].min && bp <= f[1].max) || []
466
- // let feature: AnnotationFeature | undefined = feat
467
- // if (feature) {
468
- // const topRow = row
469
- // const startPx = (feature.start - region.start) / bpPerPx
470
- // const thisX = x - startPx
471
- // feature = feature.getFeatureFromLayout(
472
- // thisX,
473
- // y - topRow * height,
474
- // bpPerPx,
475
- // height,
476
- // ) as AnnotationFeature
477
- // }
478
- // if (feature) {
479
- // // TODO: check reversed
480
- // // TODO: ensure feature is in interbase
481
- // const startPx = (feature.start - region.start) / bpPerPx
482
- // const endPx = (feature.end - region.start) / bpPerPx
483
- // if (endPx - startPx < 8) {
484
- // setOverEdge(undefined)
485
- // } else if (Math.abs(startPx - x) < 4) {
486
- // setOverEdge('start')
487
- // } else if (Math.abs(endPx - x) < 4) {
488
- // setOverEdge('end')
489
- // } else {
490
- // setOverEdge(undefined)
491
- // }
492
- // }
493
- // setApolloFeatureUnderMouse(feature)
494
- // setApolloRowUnderMouse(row)
495
- // }
496
- function onMouseLeave() {
497
- setApolloFeatureUnderMouse()
498
- setApolloRowUnderMouse()
499
- }
500
- // function onMouseDown(event: React.MouseEvent) {
501
- // if (apolloFeatureUnderMouse && overEdge) {
502
- // const { clientX } = event
503
- // const { left } = canvasRef.current?.getBoundingClientRect() || {
504
- // left: 0,
505
- // top: 0,
506
- // }
507
- // const px = clientX - left
508
- // event.stopPropagation()
509
- // setDragging({
510
- // edge: overEdge,
511
- // feature: apolloFeatureUnderMouse,
512
- // row: apolloRowUnderMouse || 0,
513
- // px,
514
- // bp: apolloFeatureUnderMouse[overEdge],
515
- // })
516
- // }
517
- // }
518
- async function onMouseUp() {
519
- if (!movedDuringLastMouseDown) {
520
- if (apolloFeatureUnderMouse) {
521
- setSelectedFeature(apolloFeatureUnderMouse)
522
- }
523
- } else if (dragging) {
524
- const assembly = getAssemblyId(region.assemblyName)
525
- const { bp, edge, feature } = dragging
526
- let change: LocationEndChange | LocationStartChange
527
- if (edge === 'end') {
528
- const featureId = feature._id
529
- const oldEnd = feature.max
530
- const newEnd = Math.round(bp)
531
- change = new LocationEndChange({
532
- typeName: 'LocationEndChange',
533
- changedIds: [featureId],
534
- featureId,
535
- oldEnd,
536
- newEnd,
537
- assembly,
538
- })
539
- } else {
540
- const featureId = feature._id
541
- const oldStart = feature.min
542
- const newStart = Math.round(bp)
543
- change = new LocationStartChange({
544
- typeName: 'LocationStartChange',
545
- changedIds: [featureId],
546
- featureId,
547
- oldStart,
548
- newStart,
549
- assembly,
550
- })
551
- }
552
- await changeManager.submit(change)
553
- }
554
-
555
- setDragging(undefined)
556
- setMovedDuringLastMouseDown(false)
557
- }
558
- function onContextMenu(event: React.MouseEvent) {
559
- event.preventDefault()
560
- setContextMenuFeature(apolloFeatureUnderMouse)
561
- setContextCoord([event.pageX, event.pageY])
562
- }
563
-
564
- return (
565
- <div
566
- style={{ position: 'relative', width: totalWidth, height: totalHeight }}
567
- >
568
- <Menu
569
- open={Boolean(contextMenuFeature)}
570
- anchorReference="anchorPosition"
571
- anchorPosition={
572
- contextCoord
573
- ? { left: contextCoord[0], top: contextCoord[1] }
574
- : undefined
575
- }
576
- data-testid="base_linear_display_context_menu"
577
- onClose={() => {
578
- setContextMenuFeature(undefined)
579
- }}
580
- >
581
- <MenuItem
582
- disabled={isReadOnly}
583
- key={1}
584
- value={1}
585
- onClick={() => {
586
- if (!contextMenuFeature) {
587
- return
588
- }
589
- const currentAssemblyId = getAssemblyId(region.assemblyName)
590
- ;(session as unknown as AbstractSessionModel).queueDialog(
591
- (doneCallback) => [
592
- AddChildFeature,
593
- {
594
- session,
595
- handleClose: () => {
596
- doneCallback()
597
-
598
- setContextMenuFeature(undefined)
599
- },
600
- changeManager,
601
- sourceFeature: contextMenuFeature,
602
- sourceAssemblyId: currentAssemblyId,
603
- internetAccount: apolloInternetAccount,
604
- },
605
- ],
606
- )
607
- }}
608
- >
609
- Add child feature
610
- </MenuItem>
611
- <MenuItem
612
- disabled={isReadOnly}
613
- key={2}
614
- value={2}
615
- onClick={() => {
616
- if (!contextMenuFeature) {
617
- return
618
- }
619
- const currentAssemblyId = getAssemblyId(region.assemblyName)
620
- ;(session as unknown as AbstractSessionModel).queueDialog(
621
- (doneCallback) => [
622
- CopyFeature,
623
- {
624
- session,
625
- handleClose: () => {
626
- doneCallback()
627
-
628
- setContextMenuFeature(undefined)
629
- },
630
- changeManager,
631
- sourceFeature: contextMenuFeature,
632
- sourceAssemblyId: currentAssemblyId,
633
- },
634
- ],
635
- )
636
- }}
637
- >
638
- Copy features and annotations
639
- </MenuItem>
640
- <MenuItem
641
- disabled={!isAdmin}
642
- key={3}
643
- value={3}
644
- onClick={() => {
645
- if (!contextMenuFeature) {
646
- return
647
- }
648
- const currentAssemblyId = getAssemblyId(region.assemblyName)
649
- ;(session as unknown as AbstractSessionModel).queueDialog(
650
- (doneCallback) => [
651
- DeleteFeature,
652
- {
653
- session,
654
- handleClose: () => {
655
- doneCallback()
656
-
657
- setContextMenuFeature(undefined)
658
- },
659
- changeManager,
660
- sourceFeature: contextMenuFeature,
661
- sourceAssemblyId: currentAssemblyId,
662
- selectedFeature,
663
- setSelectedFeature,
664
- },
665
- ],
666
- )
667
- }}
668
- >
669
- Delete feature
670
- </MenuItem>
671
- </Menu>
672
- <canvas
673
- ref={canvasRef}
674
- width={totalWidth}
675
- height={totalHeight}
676
- style={{ position: 'absolute', left: 0, top: 0 }}
677
- />
678
- <canvas
679
- ref={overlayCanvasRef}
680
- width={totalWidth}
681
- height={totalHeight}
682
- // onMouseMove={onMouseMove}
683
- onMouseLeave={onMouseLeave}
684
- // onMouseDown={onMouseDown}
685
- onMouseUp={onMouseUp}
686
- onContextMenu={onContextMenu}
687
- style={{
688
- position: 'absolute',
689
- left: 0,
690
- top: 0,
691
- // cursor:
692
- // dragging || (apolloFeatureUnderMouse && overEdge)
693
- // ? 'col-resize'
694
- // : 'default',
695
- }}
696
- />
697
- <canvas
698
- ref={codonCanvasRef}
699
- width={totalWidth}
700
- height={height * 6}
701
- style={{ position: 'absolute', left: 0, top: 0 }}
702
- />
703
- </div>
704
- )
705
- }
706
-
707
- export default observer(ApolloRendering)
@@ -1,7 +0,0 @@
1
- import { ConfigurationSchema } from '@jbrowse/core/configuration'
2
-
3
- export default ConfigurationSchema(
4
- 'ApolloSixFrameRenderer',
5
- {},
6
- { explicitlyTyped: true },
7
- )