@apollo-annotation/jbrowse-plugin-apollo 0.3.4 → 0.3.6
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.
- package/dist/index.esm.js +5466 -4490
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +5283 -4318
- package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.development.js +6806 -4088
- package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
- package/package.json +4 -4
- package/src/ApolloInternetAccount/addMenuItems.ts +5 -2
- package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
- package/src/ApolloInternetAccount/components/LoginButtons.tsx +1 -1
- package/src/ApolloInternetAccount/components/LoginIcons.tsx +1 -1
- package/src/ApolloInternetAccount/configSchema.ts +1 -1
- package/src/ApolloInternetAccount/model.ts +11 -10
- package/src/ApolloJobModel.ts +1 -1
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +8 -6
- package/src/ApolloRefNameAliasAdapter/index.ts +2 -2
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +17 -4
- package/src/ApolloSequenceAdapter/index.ts +1 -1
- package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +8 -7
- package/src/ApolloTextSearchAdapter/index.ts +1 -1
- package/src/BackendDrivers/BackendDriver.ts +7 -7
- package/src/BackendDrivers/CollaborationServerDriver.ts +14 -10
- package/src/BackendDrivers/DesktopFileDriver.ts +11 -10
- package/src/BackendDrivers/InMemoryFileDriver.ts +10 -6
- package/src/ChangeManager.ts +5 -5
- package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +92 -20
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +170 -27
- package/src/FeatureDetailsWidget/AttributeKey.tsx +50 -0
- package/src/FeatureDetailsWidget/AttributeKeySelector.tsx +104 -0
- package/src/FeatureDetailsWidget/Attributes.tsx +213 -320
- package/src/FeatureDetailsWidget/BasicInformation.tsx +8 -9
- package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +104 -0
- package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +22 -0
- package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +10 -8
- package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -1
- package/src/FeatureDetailsWidget/Sequence.tsx +18 -35
- package/src/FeatureDetailsWidget/StringTextField.tsx +1 -1
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +140 -95
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +600 -0
- package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +54 -0
- package/src/FeatureDetailsWidget/model.ts +8 -3
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +19 -12
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +19 -41
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +44 -22
- package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +6 -5
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -7
- package/src/LinearApolloDisplay/stateModel/base.ts +52 -10
- package/src/LinearApolloDisplay/stateModel/index.ts +4 -3
- package/src/LinearApolloDisplay/stateModel/layouts.ts +8 -34
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +13 -12
- package/src/LinearApolloDisplay/stateModel/rendering.ts +63 -31
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +221 -0
- package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +40 -0
- package/src/LinearApolloSixFrameDisplay/components/index.ts +2 -0
- package/src/LinearApolloSixFrameDisplay/configSchema.ts +7 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +821 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +63 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/index.ts +1 -0
- package/src/LinearApolloSixFrameDisplay/index.ts +2 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +261 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/index.ts +27 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +236 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +349 -0
- package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +199 -0
- package/src/LinearApolloSixFrameDisplay/types.ts +1 -0
- package/src/OntologyManager/OntologyStore/fulltext-stopwords.ts +10 -1
- package/src/OntologyManager/OntologyStore/fulltext.test.ts +1 -1
- package/src/OntologyManager/OntologyStore/fulltext.ts +8 -3
- package/src/OntologyManager/OntologyStore/index.test.ts +4 -1
- package/src/OntologyManager/OntologyStore/index.ts +19 -14
- package/src/OntologyManager/OntologyStore/indexeddb-schema.ts +6 -5
- package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +11 -5
- package/src/OntologyManager/index.ts +10 -6
- package/src/OntologyManager/util.ts +3 -2
- package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
- package/src/TabularEditor/HybridGrid/Feature.tsx +9 -8
- package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +1 -1
- package/src/TabularEditor/HybridGrid/HybridGrid.tsx +3 -2
- package/src/TabularEditor/HybridGrid/NumberCell.tsx +8 -1
- package/src/TabularEditor/HybridGrid/ToolBar.tsx +15 -13
- package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +9 -33
- package/src/TabularEditor/TabularEditorPane.tsx +1 -1
- package/src/TabularEditor/model.ts +2 -2
- package/src/TabularEditor/types.ts +5 -2
- package/src/components/AddAssembly.tsx +611 -291
- package/src/components/AddChildFeature.tsx +6 -5
- package/src/components/AddFeature.tsx +211 -38
- package/src/components/AddRefSeqAliases.tsx +14 -12
- package/src/components/CopyFeature.tsx +8 -7
- package/src/components/CreateApolloAnnotation.tsx +154 -46
- package/src/components/DeleteAssembly.tsx +9 -8
- package/src/components/DeleteFeature.tsx +5 -4
- package/src/components/Dialog.tsx +1 -1
- package/src/components/DownloadGFF3.tsx +11 -10
- package/src/components/FilterFeatures.tsx +6 -4
- package/src/components/ImportFeatures.tsx +7 -6
- package/src/components/LogOut.tsx +5 -4
- package/src/components/ManageChecks.tsx +9 -8
- package/src/components/ManageUsers.tsx +11 -10
- package/src/components/OntologyTermAutocomplete.tsx +5 -5
- package/src/components/OntologyTermMultiSelect.tsx +9 -6
- package/src/components/OpenLocalFile.tsx +4 -3
- package/src/components/ViewChangeLog.tsx +7 -6
- package/src/components/ViewCheckResults.tsx +8 -7
- package/src/components/index.ts +0 -1
- package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -0
- package/src/extensions/annotationFromJBrowseFeature.ts +14 -12
- package/src/extensions/annotationFromPileup.ts +6 -6
- package/src/index.ts +33 -50
- package/src/makeDisplayComponent.tsx +93 -41
- package/src/session/ClientDataStore.ts +21 -17
- package/src/session/session.ts +20 -26
- package/src/types.ts +4 -4
- package/src/util/annotationFeatureUtils.ts +53 -0
- package/src/util/index.ts +4 -3
- package/src/util/loadAssemblyIntoClient.ts +10 -3
- package/src/ApolloSixFrameRenderer/ApolloSixFrameRenderer.tsx +0 -13
- package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +0 -707
- package/src/ApolloSixFrameRenderer/configSchema.ts +0 -7
- package/src/ApolloSixFrameRenderer/index.ts +0 -3
- package/src/FeatureDetailsWidget/TranscriptBasic.tsx +0 -200
- package/src/SixFrameFeatureDisplay/components/TrackLines.tsx +0 -19
- package/src/SixFrameFeatureDisplay/components/index.ts +0 -1
- package/src/SixFrameFeatureDisplay/configSchema.ts +0 -21
- package/src/SixFrameFeatureDisplay/index.ts +0 -2
- package/src/SixFrameFeatureDisplay/stateModel.ts +0 -439
- package/src/components/ModifyFeatureAttribute.tsx +0 -460
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
3
|
+
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
4
4
|
import { defaultCodonTable, doesIntersect2, revcom } from '@jbrowse/core/util'
|
|
5
|
-
import { Theme } from '@mui/material'
|
|
5
|
+
import { type Theme } from '@mui/material'
|
|
6
6
|
import { autorun } from 'mobx'
|
|
7
|
-
import { Instance, addDisposer } from 'mobx-state-tree'
|
|
7
|
+
import { type Instance, addDisposer } from 'mobx-state-tree'
|
|
8
|
+
|
|
9
|
+
import { type ApolloSessionModel } from '../../session'
|
|
8
10
|
|
|
9
|
-
import { ApolloSessionModel } from '../../session'
|
|
10
11
|
import { layoutsModelFactory } from './layouts'
|
|
11
12
|
|
|
12
13
|
export function renderingModelIntermediateFactory(
|
|
@@ -145,16 +146,18 @@ function colorCode(letter: string, theme?: Theme) {
|
|
|
145
146
|
)
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
function codonColorCode(letter: string) {
|
|
149
|
+
function codonColorCode(letter: string, highContrast?: boolean) {
|
|
149
150
|
const colorMap: Record<string, string | undefined> = {
|
|
150
151
|
M: '#33ee33',
|
|
151
|
-
'*': '#f44336',
|
|
152
|
+
'*': highContrast ? '#000000' : '#f44336',
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
return colorMap[letter.toUpperCase()]
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
function reverseCodonSeq(seq: string): string {
|
|
159
|
+
// disable because sequence is all ascii
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-spread
|
|
158
161
|
return [...seq]
|
|
159
162
|
.map((c) => revcom(c))
|
|
160
163
|
.reverse()
|
|
@@ -186,6 +189,9 @@ function drawTranslation(
|
|
|
186
189
|
seq: string,
|
|
187
190
|
i: number,
|
|
188
191
|
reverse: boolean,
|
|
192
|
+
showStartCodons: boolean,
|
|
193
|
+
showStopCodons: boolean,
|
|
194
|
+
highContrast: boolean,
|
|
189
195
|
) {
|
|
190
196
|
let codonSeq: string = seq.slice(i, i + 3).toUpperCase()
|
|
191
197
|
if (reverse) {
|
|
@@ -196,8 +202,12 @@ function drawTranslation(
|
|
|
196
202
|
if (!codonLetter) {
|
|
197
203
|
return
|
|
198
204
|
}
|
|
199
|
-
const fillColor = codonColorCode(codonLetter)
|
|
200
|
-
if (
|
|
205
|
+
const fillColor = codonColorCode(codonLetter, highContrast)
|
|
206
|
+
if (
|
|
207
|
+
fillColor &&
|
|
208
|
+
((showStopCodons && codonLetter == '*') ||
|
|
209
|
+
(showStartCodons && codonLetter != '*'))
|
|
210
|
+
) {
|
|
201
211
|
seqTrackctx.fillStyle = fillColor
|
|
202
212
|
seqTrackctx.fillRect(trnslStartPx, trnslY, trnslWidthPx, sequenceRowHeight)
|
|
203
213
|
}
|
|
@@ -222,11 +232,13 @@ export function sequenceRenderingModelFactory(
|
|
|
222
232
|
addDisposer(
|
|
223
233
|
self,
|
|
224
234
|
autorun(
|
|
225
|
-
|
|
235
|
+
() => {
|
|
236
|
+
const { theme } = self
|
|
226
237
|
if (!self.lgv.initialized || self.regionCannotBeRendered()) {
|
|
227
238
|
return
|
|
228
239
|
}
|
|
229
|
-
|
|
240
|
+
const trnslWidthPx = 3 / self.lgv.bpPerPx
|
|
241
|
+
if (trnslWidthPx < 1) {
|
|
230
242
|
return
|
|
231
243
|
}
|
|
232
244
|
const seqTrackctx = self.seqTrackCanvas?.getContext('2d')
|
|
@@ -245,33 +257,48 @@ export function sequenceRenderingModelFactory(
|
|
|
245
257
|
? [3, 2, 1, 0, 0, -1, -2, -3]
|
|
246
258
|
: [3, 2, 1, -1, -2, -3]
|
|
247
259
|
let height = 0
|
|
248
|
-
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
260
|
+
if (theme) {
|
|
261
|
+
for (const frame of frames) {
|
|
262
|
+
let frameColor = theme.palette.framesCDS.at(frame)?.main
|
|
263
|
+
if (frameColor) {
|
|
264
|
+
let offsetPx = 0
|
|
265
|
+
if (self.highContrast) {
|
|
266
|
+
frameColor = 'white'
|
|
267
|
+
offsetPx = 1
|
|
268
|
+
// eslint-disable-next-line prefer-destructuring
|
|
269
|
+
seqTrackctx.fillStyle = theme.palette.grey[200]
|
|
270
|
+
seqTrackctx.fillRect(
|
|
271
|
+
0,
|
|
272
|
+
height,
|
|
273
|
+
self.lgv.dynamicBlocks.totalWidthPx,
|
|
274
|
+
self.sequenceRowHeight,
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
seqTrackctx.fillStyle = frameColor
|
|
278
|
+
seqTrackctx.fillRect(
|
|
279
|
+
0 + offsetPx,
|
|
280
|
+
height + offsetPx,
|
|
281
|
+
self.lgv.dynamicBlocks.totalWidthPx - 2 * offsetPx,
|
|
282
|
+
self.sequenceRowHeight - 2 * offsetPx,
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
height += self.sequenceRowHeight
|
|
258
286
|
}
|
|
259
|
-
height += self.sequenceRowHeight
|
|
260
287
|
}
|
|
261
288
|
|
|
262
289
|
for (const [idx, region] of self.regions.entries()) {
|
|
263
|
-
const
|
|
290
|
+
const { apolloDataStore } =
|
|
264
291
|
self.session as unknown as ApolloSessionModel
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const { seq } = await driver.getSequence(region)
|
|
271
|
-
|
|
292
|
+
const assembly = apolloDataStore.assemblies.get(
|
|
293
|
+
region.assemblyName,
|
|
294
|
+
)
|
|
295
|
+
const ref = assembly?.getByRefName(region.refName)
|
|
296
|
+
const seq = ref?.getSequence(region.start, region.end)
|
|
272
297
|
if (!seq) {
|
|
273
298
|
return
|
|
274
299
|
}
|
|
300
|
+
// disable because sequence is all ascii
|
|
301
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-spread
|
|
275
302
|
for (const [i, letter] of [...seq].entries()) {
|
|
276
303
|
const trnslXOffset =
|
|
277
304
|
(self.lgv.bpToPx({
|
|
@@ -279,7 +306,6 @@ export function sequenceRenderingModelFactory(
|
|
|
279
306
|
coord: region.start + i,
|
|
280
307
|
regionNumber: idx,
|
|
281
308
|
})?.offsetPx ?? 0) - self.lgv.offsetPx
|
|
282
|
-
const trnslWidthPx = 3 / self.lgv.bpPerPx
|
|
283
309
|
const trnslStartPx = self.lgv.displayedRegions[idx].reversed
|
|
284
310
|
? trnslXOffset - trnslWidthPx
|
|
285
311
|
: trnslXOffset
|
|
@@ -297,6 +323,9 @@ export function sequenceRenderingModelFactory(
|
|
|
297
323
|
seq,
|
|
298
324
|
i,
|
|
299
325
|
false,
|
|
326
|
+
self.showStartCodons,
|
|
327
|
+
self.showStopCodons,
|
|
328
|
+
self.highContrast,
|
|
300
329
|
)
|
|
301
330
|
}
|
|
302
331
|
}
|
|
@@ -371,6 +400,9 @@ export function sequenceRenderingModelFactory(
|
|
|
371
400
|
seq,
|
|
372
401
|
i,
|
|
373
402
|
true,
|
|
403
|
+
self.showStartCodons,
|
|
404
|
+
self.showStopCodons,
|
|
405
|
+
self.highContrast,
|
|
374
406
|
)
|
|
375
407
|
}
|
|
376
408
|
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
4
|
+
import { Menu, type MenuItem } from '@jbrowse/core/ui'
|
|
5
|
+
import {
|
|
6
|
+
type AbstractSessionModel,
|
|
7
|
+
doesIntersect2,
|
|
8
|
+
getContainingView,
|
|
9
|
+
} from '@jbrowse/core/util'
|
|
10
|
+
import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
11
|
+
import ErrorIcon from '@mui/icons-material/Error'
|
|
12
|
+
import { Alert, Avatar, Tooltip, useTheme } from '@mui/material'
|
|
13
|
+
import { observer } from 'mobx-react'
|
|
14
|
+
import React, { useEffect, useState } from 'react'
|
|
15
|
+
import { makeStyles } from 'tss-react/mui'
|
|
16
|
+
|
|
17
|
+
import { type LinearApolloSixFrameDisplay as LinearApolloSixFrameDisplayI } from '../stateModel'
|
|
18
|
+
|
|
19
|
+
import { TrackLines } from './TrackLines'
|
|
20
|
+
|
|
21
|
+
interface LinearApolloSixFrameDisplayProps {
|
|
22
|
+
model: LinearApolloSixFrameDisplayI
|
|
23
|
+
}
|
|
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
|
+
|
|
46
|
+
export const LinearApolloSixFrameDisplay = observer(
|
|
47
|
+
function LinearApolloSixFrameDisplay(
|
|
48
|
+
props: LinearApolloSixFrameDisplayProps,
|
|
49
|
+
) {
|
|
50
|
+
const theme = useTheme()
|
|
51
|
+
const { model } = props
|
|
52
|
+
const {
|
|
53
|
+
apolloRowHeight,
|
|
54
|
+
contextMenuItems: getContextMenuItems,
|
|
55
|
+
cursor,
|
|
56
|
+
featuresHeight,
|
|
57
|
+
isShown,
|
|
58
|
+
onMouseDown,
|
|
59
|
+
onMouseLeave,
|
|
60
|
+
onMouseMove,
|
|
61
|
+
onMouseUp,
|
|
62
|
+
regionCannotBeRendered,
|
|
63
|
+
session,
|
|
64
|
+
setCanvas,
|
|
65
|
+
setCollaboratorCanvas,
|
|
66
|
+
setOverlayCanvas,
|
|
67
|
+
setTheme,
|
|
68
|
+
} = model
|
|
69
|
+
const { classes } = useStyles()
|
|
70
|
+
const lgv = getContainingView(model) as unknown as LinearGenomeViewModel
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
setTheme(theme)
|
|
74
|
+
}, [theme, setTheme])
|
|
75
|
+
const [contextCoord, setContextCoord] = useState<Coord>()
|
|
76
|
+
const [contextMenuItems, setContextMenuItems] = useState<MenuItem[]>([])
|
|
77
|
+
const message = regionCannotBeRendered()
|
|
78
|
+
if (!isShown) {
|
|
79
|
+
return null
|
|
80
|
+
}
|
|
81
|
+
const { assemblyManager } = session as unknown as AbstractSessionModel
|
|
82
|
+
return (
|
|
83
|
+
<>
|
|
84
|
+
<div
|
|
85
|
+
className={classes.canvasContainer}
|
|
86
|
+
style={{
|
|
87
|
+
width: lgv.dynamicBlocks.totalWidthPx,
|
|
88
|
+
height: featuresHeight,
|
|
89
|
+
}}
|
|
90
|
+
onContextMenu={(event) => {
|
|
91
|
+
event.preventDefault()
|
|
92
|
+
if (contextMenuItems.length > 0) {
|
|
93
|
+
// There's already a context menu open, so close it
|
|
94
|
+
setContextMenuItems([])
|
|
95
|
+
} else {
|
|
96
|
+
const coord: [number, number] = [event.clientX, event.clientY]
|
|
97
|
+
setContextCoord(coord)
|
|
98
|
+
setContextMenuItems(getContextMenuItems(coord))
|
|
99
|
+
}
|
|
100
|
+
}}
|
|
101
|
+
>
|
|
102
|
+
{message ? (
|
|
103
|
+
<Alert severity="warning" classes={{ message: classes.ellipses }}>
|
|
104
|
+
<Tooltip title={message}>
|
|
105
|
+
<div>{message}</div>
|
|
106
|
+
</Tooltip>
|
|
107
|
+
</Alert>
|
|
108
|
+
) : (
|
|
109
|
+
// Promise.resolve() in these 3 callbacks is to avoid infinite rendering loop
|
|
110
|
+
// https://github.com/mobxjs/mobx/issues/3728#issuecomment-1715400931
|
|
111
|
+
<>
|
|
112
|
+
<TrackLines model={model} strand={1} />
|
|
113
|
+
<TrackLines model={model} strand={-1} />
|
|
114
|
+
<canvas
|
|
115
|
+
ref={async (node: HTMLCanvasElement) => {
|
|
116
|
+
await Promise.resolve()
|
|
117
|
+
setCollaboratorCanvas(node)
|
|
118
|
+
}}
|
|
119
|
+
width={lgv.dynamicBlocks.totalWidthPx}
|
|
120
|
+
height={featuresHeight}
|
|
121
|
+
className={classes.canvas}
|
|
122
|
+
data-testid="collaboratorCanvas"
|
|
123
|
+
/>
|
|
124
|
+
<canvas
|
|
125
|
+
ref={async (node: HTMLCanvasElement) => {
|
|
126
|
+
await Promise.resolve()
|
|
127
|
+
setCanvas(node)
|
|
128
|
+
}}
|
|
129
|
+
width={lgv.dynamicBlocks.totalWidthPx}
|
|
130
|
+
height={featuresHeight}
|
|
131
|
+
className={classes.canvas}
|
|
132
|
+
data-testid="canvas"
|
|
133
|
+
/>
|
|
134
|
+
<canvas
|
|
135
|
+
ref={async (node: HTMLCanvasElement) => {
|
|
136
|
+
await Promise.resolve()
|
|
137
|
+
setOverlayCanvas(node)
|
|
138
|
+
}}
|
|
139
|
+
width={lgv.dynamicBlocks.totalWidthPx}
|
|
140
|
+
height={featuresHeight}
|
|
141
|
+
onMouseMove={onMouseMove}
|
|
142
|
+
onMouseLeave={onMouseLeave}
|
|
143
|
+
onMouseDown={onMouseDown}
|
|
144
|
+
onMouseUp={onMouseUp}
|
|
145
|
+
className={classes.canvas}
|
|
146
|
+
style={{ cursor: cursor ?? 'default' }}
|
|
147
|
+
data-testid="overlayCanvas"
|
|
148
|
+
/>
|
|
149
|
+
{lgv.displayedRegions.flatMap((region, idx) => {
|
|
150
|
+
const assembly = assemblyManager.get(region.assemblyName)
|
|
151
|
+
return [...session.apolloDataStore.checkResults.values()]
|
|
152
|
+
.filter(
|
|
153
|
+
(checkResult) =>
|
|
154
|
+
assembly?.isValidRefName(checkResult.refSeq) &&
|
|
155
|
+
assembly.getCanonicalRefName(checkResult.refSeq) ===
|
|
156
|
+
region.refName &&
|
|
157
|
+
doesIntersect2(
|
|
158
|
+
region.start,
|
|
159
|
+
region.end,
|
|
160
|
+
checkResult.start,
|
|
161
|
+
checkResult.end,
|
|
162
|
+
),
|
|
163
|
+
)
|
|
164
|
+
.map((checkResult) => {
|
|
165
|
+
const left =
|
|
166
|
+
(lgv.bpToPx({
|
|
167
|
+
refName: region.refName,
|
|
168
|
+
coord: checkResult.start,
|
|
169
|
+
regionNumber: idx,
|
|
170
|
+
})?.offsetPx ?? 0) - lgv.offsetPx
|
|
171
|
+
const [feature] = checkResult.ids
|
|
172
|
+
if (!feature || !feature.parent?.looksLikeGene) {
|
|
173
|
+
return null
|
|
174
|
+
}
|
|
175
|
+
const top = 0
|
|
176
|
+
const height = apolloRowHeight
|
|
177
|
+
return (
|
|
178
|
+
<Tooltip
|
|
179
|
+
key={checkResult._id}
|
|
180
|
+
title={checkResult.message}
|
|
181
|
+
>
|
|
182
|
+
<Avatar
|
|
183
|
+
className={classes.avatar}
|
|
184
|
+
style={{ top, left, height, width: height }}
|
|
185
|
+
>
|
|
186
|
+
<ErrorIcon />
|
|
187
|
+
</Avatar>
|
|
188
|
+
</Tooltip>
|
|
189
|
+
)
|
|
190
|
+
})
|
|
191
|
+
})}
|
|
192
|
+
<Menu
|
|
193
|
+
open={contextMenuItems.length > 0}
|
|
194
|
+
onMenuItemClick={(_, callback) => {
|
|
195
|
+
callback()
|
|
196
|
+
setContextMenuItems([])
|
|
197
|
+
}}
|
|
198
|
+
onClose={() => {
|
|
199
|
+
setContextMenuItems([])
|
|
200
|
+
}}
|
|
201
|
+
TransitionProps={{
|
|
202
|
+
onExit: () => {
|
|
203
|
+
setContextMenuItems([])
|
|
204
|
+
},
|
|
205
|
+
}}
|
|
206
|
+
anchorReference="anchorPosition"
|
|
207
|
+
anchorPosition={
|
|
208
|
+
contextCoord
|
|
209
|
+
? { top: contextCoord[1], left: contextCoord[0] }
|
|
210
|
+
: undefined
|
|
211
|
+
}
|
|
212
|
+
style={{ zIndex: theme.zIndex.tooltip }}
|
|
213
|
+
menuItems={contextMenuItems}
|
|
214
|
+
/>
|
|
215
|
+
</>
|
|
216
|
+
)}
|
|
217
|
+
</div>
|
|
218
|
+
</>
|
|
219
|
+
)
|
|
220
|
+
},
|
|
221
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { observer } from 'mobx-react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import { type LinearApolloSixFrameDisplay } from '../stateModel'
|
|
5
|
+
|
|
6
|
+
export const TrackLines = observer(function TrackLines({
|
|
7
|
+
model,
|
|
8
|
+
strand,
|
|
9
|
+
}: {
|
|
10
|
+
model: LinearApolloSixFrameDisplay
|
|
11
|
+
strand: number
|
|
12
|
+
}) {
|
|
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
|
+
) : (
|
|
26
|
+
<div
|
|
27
|
+
style={{
|
|
28
|
+
position: 'absolute',
|
|
29
|
+
left: 0,
|
|
30
|
+
bottom:
|
|
31
|
+
(apolloRowHeight * (highestRow + 1) + lastRowTooltipBufferHeight) /
|
|
32
|
+
2 +
|
|
33
|
+
3,
|
|
34
|
+
width: '100%',
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<hr style={{ margin: 0, top: 0, color: 'black' }} />
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
})
|