@apollo-annotation/jbrowse-plugin-apollo 0.3.5 → 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 +5474 -4937
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +4609 -4089
- 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 +3634 -3500
- 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 +4 -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 +8 -7
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +35 -14
- package/src/FeatureDetailsWidget/AttributeKey.tsx +50 -0
- package/src/FeatureDetailsWidget/AttributeKeySelector.tsx +104 -0
- package/src/FeatureDetailsWidget/Attributes.tsx +210 -367
- package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -5
- package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +104 -0
- package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +22 -0
- package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +4 -4
- package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -1
- package/src/FeatureDetailsWidget/Sequence.tsx +2 -2
- package/src/FeatureDetailsWidget/StringTextField.tsx +1 -1
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +3 -3
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +21 -21
- package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +4 -4
- package/src/FeatureDetailsWidget/model.ts +8 -3
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +6 -6
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +13 -14
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +9 -9
- 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 -39
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +13 -12
- package/src/LinearApolloDisplay/stateModel/rendering.ts +59 -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.test.ts +1 -1
- package/src/OntologyManager/OntologyStore/fulltext.ts +8 -3
- package/src/OntologyManager/OntologyStore/index.test.ts +3 -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 +8 -6
- package/src/OntologyManager/util.ts +3 -2
- package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
- package/src/TabularEditor/HybridGrid/Feature.tsx +9 -7
- package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +1 -1
- package/src/TabularEditor/HybridGrid/HybridGrid.tsx +3 -2
- package/src/TabularEditor/HybridGrid/ToolBar.tsx +1 -1
- package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +6 -6
- 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 +182 -179
- 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 +9 -8
- 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 +6 -6
- package/src/components/OpenLocalFile.tsx +4 -3
- package/src/components/ViewChangeLog.tsx +7 -6
- package/src/components/ViewCheckResults.tsx +8 -7
- package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -0
- package/src/extensions/annotationFromJBrowseFeature.ts +11 -10
- package/src/extensions/annotationFromPileup.ts +6 -6
- package/src/index.ts +33 -50
- package/src/makeDisplayComponent.tsx +90 -37
- 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 +1 -1
- package/src/util/index.ts +3 -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/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 -443
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import { AnnotationFeature } from '@apollo-annotation/mst'
|
|
1
|
+
import { type AnnotationFeature } from '@apollo-annotation/mst'
|
|
2
2
|
import {
|
|
3
3
|
LocationEndChange,
|
|
4
4
|
LocationStartChange,
|
|
5
5
|
} from '@apollo-annotation/shared'
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import { MenuItem } from '@jbrowse/core/ui'
|
|
9
|
-
import type
|
|
10
|
-
import {
|
|
6
|
+
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
7
|
+
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
8
|
+
import { type MenuItem } from '@jbrowse/core/ui'
|
|
9
|
+
import { type Frame, getFrame } from '@jbrowse/core/util'
|
|
10
|
+
import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
11
|
+
import { type Theme } from '@mui/material'
|
|
11
12
|
import { autorun } from 'mobx'
|
|
12
|
-
import { Instance, addDisposer } from 'mobx-state-tree'
|
|
13
|
-
import type
|
|
13
|
+
import { type Instance, addDisposer } from 'mobx-state-tree'
|
|
14
|
+
import { type CSSProperties } from 'react'
|
|
15
|
+
|
|
16
|
+
import { type Coord } from '../components'
|
|
17
|
+
import { type Glyph } from '../glyphs/Glyph'
|
|
18
|
+
import { type CanvasMouseEvent } from '../types'
|
|
14
19
|
|
|
15
|
-
import { Coord } from '../components'
|
|
16
|
-
import { Glyph } from '../glyphs/Glyph'
|
|
17
|
-
import { CanvasMouseEvent } from '../types'
|
|
18
20
|
import { renderingModelFactory } from './rendering'
|
|
19
|
-
import { Frame, getFrame } from '@jbrowse/core/util'
|
|
20
21
|
|
|
21
22
|
export interface FeatureAndGlyphUnderMouse {
|
|
22
23
|
feature: AnnotationFeature
|
|
@@ -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,10 +146,10 @@ 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()]
|
|
@@ -188,6 +189,9 @@ function drawTranslation(
|
|
|
188
189
|
seq: string,
|
|
189
190
|
i: number,
|
|
190
191
|
reverse: boolean,
|
|
192
|
+
showStartCodons: boolean,
|
|
193
|
+
showStopCodons: boolean,
|
|
194
|
+
highContrast: boolean,
|
|
191
195
|
) {
|
|
192
196
|
let codonSeq: string = seq.slice(i, i + 3).toUpperCase()
|
|
193
197
|
if (reverse) {
|
|
@@ -198,8 +202,12 @@ function drawTranslation(
|
|
|
198
202
|
if (!codonLetter) {
|
|
199
203
|
return
|
|
200
204
|
}
|
|
201
|
-
const fillColor = codonColorCode(codonLetter)
|
|
202
|
-
if (
|
|
205
|
+
const fillColor = codonColorCode(codonLetter, highContrast)
|
|
206
|
+
if (
|
|
207
|
+
fillColor &&
|
|
208
|
+
((showStopCodons && codonLetter == '*') ||
|
|
209
|
+
(showStartCodons && codonLetter != '*'))
|
|
210
|
+
) {
|
|
203
211
|
seqTrackctx.fillStyle = fillColor
|
|
204
212
|
seqTrackctx.fillRect(trnslStartPx, trnslY, trnslWidthPx, sequenceRowHeight)
|
|
205
213
|
}
|
|
@@ -224,11 +232,13 @@ export function sequenceRenderingModelFactory(
|
|
|
224
232
|
addDisposer(
|
|
225
233
|
self,
|
|
226
234
|
autorun(
|
|
227
|
-
|
|
235
|
+
() => {
|
|
236
|
+
const { theme } = self
|
|
228
237
|
if (!self.lgv.initialized || self.regionCannotBeRendered()) {
|
|
229
238
|
return
|
|
230
239
|
}
|
|
231
|
-
|
|
240
|
+
const trnslWidthPx = 3 / self.lgv.bpPerPx
|
|
241
|
+
if (trnslWidthPx < 1) {
|
|
232
242
|
return
|
|
233
243
|
}
|
|
234
244
|
const seqTrackctx = self.seqTrackCanvas?.getContext('2d')
|
|
@@ -247,30 +257,43 @@ export function sequenceRenderingModelFactory(
|
|
|
247
257
|
? [3, 2, 1, 0, 0, -1, -2, -3]
|
|
248
258
|
: [3, 2, 1, -1, -2, -3]
|
|
249
259
|
let height = 0
|
|
250
|
-
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
|
260
286
|
}
|
|
261
|
-
height += self.sequenceRowHeight
|
|
262
287
|
}
|
|
263
288
|
|
|
264
289
|
for (const [idx, region] of self.regions.entries()) {
|
|
265
|
-
const
|
|
290
|
+
const { apolloDataStore } =
|
|
266
291
|
self.session as unknown as ApolloSessionModel
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const { seq } = await driver.getSequence(region)
|
|
273
|
-
|
|
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)
|
|
274
297
|
if (!seq) {
|
|
275
298
|
return
|
|
276
299
|
}
|
|
@@ -283,7 +306,6 @@ export function sequenceRenderingModelFactory(
|
|
|
283
306
|
coord: region.start + i,
|
|
284
307
|
regionNumber: idx,
|
|
285
308
|
})?.offsetPx ?? 0) - self.lgv.offsetPx
|
|
286
|
-
const trnslWidthPx = 3 / self.lgv.bpPerPx
|
|
287
309
|
const trnslStartPx = self.lgv.displayedRegions[idx].reversed
|
|
288
310
|
? trnslXOffset - trnslWidthPx
|
|
289
311
|
: trnslXOffset
|
|
@@ -301,6 +323,9 @@ export function sequenceRenderingModelFactory(
|
|
|
301
323
|
seq,
|
|
302
324
|
i,
|
|
303
325
|
false,
|
|
326
|
+
self.showStartCodons,
|
|
327
|
+
self.showStopCodons,
|
|
328
|
+
self.highContrast,
|
|
304
329
|
)
|
|
305
330
|
}
|
|
306
331
|
}
|
|
@@ -375,6 +400,9 @@ export function sequenceRenderingModelFactory(
|
|
|
375
400
|
seq,
|
|
376
401
|
i,
|
|
377
402
|
true,
|
|
403
|
+
self.showStartCodons,
|
|
404
|
+
self.showStopCodons,
|
|
405
|
+
self.highContrast,
|
|
378
406
|
)
|
|
379
407
|
}
|
|
380
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
|
+
})
|