@apollo-annotation/jbrowse-plugin-apollo 0.3.12 → 1.0.0
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/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.d.ts +1 -1
- package/dist/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.d.ts.map +1 -1
- package/dist/BackendDrivers/BackendDriver.d.ts +29 -4
- package/dist/BackendDrivers/BackendDriver.d.ts.map +1 -1
- package/dist/BackendDrivers/CollaborationServerDriver.d.ts +3 -1
- package/dist/BackendDrivers/CollaborationServerDriver.d.ts.map +1 -1
- package/dist/BackendDrivers/LocalDriver/LocalDriver.d.ts +22 -0
- package/dist/BackendDrivers/LocalDriver/LocalDriver.d.ts.map +1 -0
- package/dist/BackendDrivers/LocalDriver/db.d.ts +4 -0
- package/dist/BackendDrivers/LocalDriver/db.d.ts.map +1 -0
- package/dist/BackendDrivers/index.d.ts +1 -2
- package/dist/BackendDrivers/index.d.ts.map +1 -1
- package/dist/ChangeManager.d.ts +3 -3
- package/dist/ChangeManager.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.d.ts +0 -6
- package/dist/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/TranscriptWidgetEditLocation.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/model.d.ts +0 -2
- package/dist/FeatureDetailsWidget/model.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/components/CheckResultWarnings.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/components/LinearApolloDisplay.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/components/OverlayCanvas.d.ts +7 -0
- package/dist/LinearApolloDisplay/components/OverlayCanvas.d.ts.map +1 -0
- package/dist/LinearApolloDisplay/components/Tooltip.d.ts +10 -0
- package/dist/LinearApolloDisplay/components/Tooltip.d.ts.map +1 -0
- package/dist/LinearApolloDisplay/glyphs/BoxGlyph.d.ts +0 -1
- package/dist/LinearApolloDisplay/glyphs/BoxGlyph.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/glyphs/CDSGlyph.d.ts +3 -0
- package/dist/LinearApolloDisplay/glyphs/CDSGlyph.d.ts.map +1 -0
- package/dist/LinearApolloDisplay/glyphs/ExonGlyph.d.ts +3 -0
- package/dist/LinearApolloDisplay/glyphs/ExonGlyph.d.ts.map +1 -0
- package/dist/LinearApolloDisplay/glyphs/GeneGlyph.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/glyphs/GenericChildGlyph.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/glyphs/Glyph.d.ts +26 -20
- package/dist/LinearApolloDisplay/glyphs/Glyph.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/glyphs/TranscriptGlyph.d.ts +3 -0
- package/dist/LinearApolloDisplay/glyphs/TranscriptGlyph.d.ts.map +1 -0
- package/dist/LinearApolloDisplay/glyphs/util.d.ts +13 -0
- package/dist/LinearApolloDisplay/glyphs/util.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/base.d.ts +17 -0
- package/dist/LinearApolloDisplay/stateModel/base.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/index.d.ts +35 -17
- package/dist/LinearApolloDisplay/stateModel/index.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/layouts.d.ts +29 -7
- package/dist/LinearApolloDisplay/stateModel/layouts.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/mouseEvents.d.ts +69 -23
- package/dist/LinearApolloDisplay/stateModel/mouseEvents.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/rendering.d.ts +26 -9
- package/dist/LinearApolloDisplay/stateModel/rendering.d.ts.map +1 -1
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/base.d.ts +6 -0
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/base.d.ts.map +1 -1
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/index.d.ts +6 -0
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/index.d.ts.map +1 -1
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/rendering.d.ts +6 -0
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/rendering.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/glyphs/Glyph.d.ts +1 -1
- package/dist/LinearApolloSixFrameDisplay/glyphs/Glyph.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/layouts.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/rendering.d.ts.map +1 -1
- package/dist/OntologyManager/OntologyStore/fulltext.d.ts +1 -1
- package/dist/OntologyManager/OntologyStore/fulltext.d.ts.map +1 -1
- package/dist/OntologyManager/OntologyStore/index.d.ts +2 -2
- package/dist/OntologyManager/OntologyStore/index.d.ts.map +1 -1
- package/dist/OntologyManager/OntologyStore/indexeddb-storage.d.ts +1 -1
- package/dist/OntologyManager/OntologyStore/indexeddb-storage.d.ts.map +1 -1
- package/dist/OntologyManager/OntologyStore/types.d.ts +18 -0
- package/dist/OntologyManager/OntologyStore/types.d.ts.map +1 -0
- package/dist/TabularEditor/HybridGrid/featureContextMenuItems.d.ts.map +1 -1
- package/dist/components/AddChildFeature.d.ts.map +1 -1
- package/dist/components/ColorFeature.d.ts +13 -0
- package/dist/components/ColorFeature.d.ts.map +1 -0
- package/dist/components/CreateApolloAnnotation.d.ts.map +1 -1
- package/dist/components/DownloadGFF3.d.ts +4 -1
- package/dist/components/DownloadGFF3.d.ts.map +1 -1
- package/dist/components/DuplicateTranscript.d.ts.map +1 -1
- package/dist/components/ViewChangeLog.d.ts +2 -1
- package/dist/components/ViewChangeLog.d.ts.map +1 -1
- package/dist/components/ViewCheckResults.d.ts +2 -1
- package/dist/components/ViewCheckResults.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/extensions/annotationFromJBrowseFeature.d.ts.map +1 -1
- package/dist/extensions/annotationFromPileup.d.ts.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +6325 -5997
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +5869 -5541
- 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 +16782 -25897
- 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/dist/makeDisplayComponent.d.ts.map +1 -1
- package/dist/menus/Icons.d.ts +3 -0
- package/dist/menus/Icons.d.ts.map +1 -0
- package/dist/menus/topLevelMenu.d.ts.map +1 -1
- package/dist/session/changeHandlers.d.ts +9 -0
- package/dist/session/changeHandlers.d.ts.map +1 -0
- package/dist/util/annotationFeatureUtils.d.ts +2 -1
- package/dist/util/annotationFeatureUtils.d.ts.map +1 -1
- package/dist/util/glyphUtils.d.ts +3 -3
- package/dist/util/glyphUtils.d.ts.map +1 -1
- package/dist/util/index.d.ts +0 -1
- package/dist/util/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/ApolloInternetAccount/model.ts +68 -4
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +6 -3
- package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +1 -1
- package/src/BackendDrivers/BackendDriver.ts +36 -3
- package/src/BackendDrivers/CollaborationServerDriver.ts +78 -23
- package/src/BackendDrivers/LocalDriver/LocalDriver.ts +367 -0
- package/src/BackendDrivers/LocalDriver/db.ts +37 -0
- package/src/BackendDrivers/index.ts +1 -2
- package/src/ChangeManager.ts +27 -25
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +1 -1
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +69 -53
- package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +1 -5
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +95 -115
- package/src/LinearApolloDisplay/components/OverlayCanvas.tsx +76 -0
- package/src/LinearApolloDisplay/components/Tooltip.tsx +42 -0
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +60 -302
- package/src/LinearApolloDisplay/glyphs/CDSGlyph.ts +145 -0
- package/src/LinearApolloDisplay/glyphs/ExonGlyph.ts +212 -0
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +65 -999
- package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +71 -181
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +42 -66
- package/src/LinearApolloDisplay/glyphs/TranscriptGlyph.ts +291 -0
- package/src/LinearApolloDisplay/glyphs/util.ts +87 -0
- package/src/LinearApolloDisplay/stateModel/base.ts +83 -0
- package/src/LinearApolloDisplay/stateModel/layouts.ts +198 -138
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +252 -158
- package/src/LinearApolloDisplay/stateModel/rendering.ts +103 -21
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +3 -3
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +20 -2
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +7 -2
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +8 -13
- package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +1 -1
- package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +4 -3
- package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +1 -1
- package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +2 -1
- package/src/OntologyManager/OntologyStore/__snapshots__/index.test.ts.snap +18262 -8519
- package/src/OntologyManager/OntologyStore/fulltext.ts +1 -2
- package/src/OntologyManager/OntologyStore/index.test.ts +5 -2
- package/src/OntologyManager/OntologyStore/index.ts +7 -8
- package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +2 -2
- package/src/OntologyManager/OntologyStore/types.ts +27 -0
- package/src/OntologyManager/index.ts +15 -26
- package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +4 -5
- package/src/components/AddChildFeature.tsx +15 -8
- package/src/components/ColorFeature.tsx +167 -0
- package/src/components/CreateApolloAnnotation.tsx +35 -9
- package/src/components/DownloadGFF3.tsx +92 -121
- package/src/components/DuplicateTranscript.tsx +10 -0
- package/src/components/ViewChangeLog.tsx +123 -83
- package/src/components/ViewCheckResults.tsx +15 -73
- package/src/components/index.ts +1 -1
- package/src/config.ts +37 -19
- package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -1
- package/src/extensions/annotationFromJBrowseFeature.ts +91 -63
- package/src/extensions/annotationFromPileup.ts +40 -40
- package/src/index.ts +45 -1
- package/src/makeDisplayComponent.tsx +10 -3
- package/src/menus/Icons.tsx +49 -0
- package/src/menus/topLevelMenu.ts +24 -96
- package/src/session/ClientDataStore.ts +16 -17
- package/src/session/changeHandlers.ts +261 -0
- package/src/session/session.ts +77 -46
- package/src/util/annotationFeatureUtils.ts +29 -1
- package/src/util/glyphUtils.ts +74 -31
- package/src/util/index.ts +0 -1
- package/dist/BackendDrivers/DesktopFileDriver.d.ts +0 -160
- package/dist/BackendDrivers/DesktopFileDriver.d.ts.map +0 -1
- package/dist/BackendDrivers/InMemoryFileDriver.d.ts +0 -162
- package/dist/BackendDrivers/InMemoryFileDriver.d.ts.map +0 -1
- package/dist/LinearApolloDisplay/glyphs/index.d.ts +0 -4
- package/dist/LinearApolloDisplay/glyphs/index.d.ts.map +0 -1
- package/dist/components/OpenLocalFile.d.ts +0 -15
- package/dist/components/OpenLocalFile.d.ts.map +0 -1
- package/dist/util/loadAssemblyIntoClient.d.ts +0 -5
- package/dist/util/loadAssemblyIntoClient.d.ts.map +0 -1
- package/src/BackendDrivers/DesktopFileDriver.ts +0 -184
- package/src/BackendDrivers/InMemoryFileDriver.ts +0 -107
- package/src/LinearApolloDisplay/glyphs/index.ts +0 -3
- package/src/components/OpenLocalFile.tsx +0 -189
- package/src/util/loadAssemblyIntoClient.ts +0 -94
|
@@ -1,55 +1,36 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
2
2
|
/* eslint-disable @typescript-eslint/use-unknown-in-catch-callback-variable */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
5
|
-
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
6
3
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
7
|
-
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
8
5
|
import {
|
|
9
6
|
Button,
|
|
10
7
|
DialogActions,
|
|
11
8
|
DialogContent,
|
|
12
9
|
DialogContentText,
|
|
13
|
-
MenuItem,
|
|
14
|
-
Select,
|
|
15
|
-
type SelectChangeEvent,
|
|
16
10
|
} from '@mui/material'
|
|
17
|
-
import {
|
|
18
|
-
DataGrid,
|
|
19
|
-
type GridColDef,
|
|
20
|
-
type GridRowsProp,
|
|
21
|
-
GridToolbar,
|
|
22
|
-
} from '@mui/x-data-grid'
|
|
11
|
+
import { DataGrid, type GridColDef, type GridRowsProp } from '@mui/x-data-grid'
|
|
23
12
|
import React, { useEffect, useState } from 'react'
|
|
24
13
|
|
|
25
|
-
import type { ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
|
|
26
14
|
import type { ApolloSessionModel } from '../session'
|
|
27
|
-
import type { ApolloRootModel } from '../types'
|
|
28
|
-
import { createFetchErrorMessage } from '../util'
|
|
29
15
|
|
|
30
16
|
import { Dialog } from './Dialog'
|
|
31
17
|
|
|
32
18
|
interface ViewCheckResultsProps {
|
|
33
19
|
session: ApolloSessionModel
|
|
34
20
|
handleClose(): void
|
|
21
|
+
assembly: string
|
|
35
22
|
}
|
|
36
23
|
|
|
37
24
|
export function ViewCheckResults({
|
|
38
25
|
handleClose,
|
|
39
26
|
session,
|
|
27
|
+
assembly: assemblyName,
|
|
40
28
|
}: ViewCheckResultsProps) {
|
|
41
|
-
const { internetAccounts } = getRoot<ApolloRootModel>(session)
|
|
42
|
-
const { collaborationServerDriver } = session.apolloDataStore
|
|
43
|
-
const apolloInternetAccount = internetAccounts.find(
|
|
44
|
-
(ia) => ia.type === 'ApolloInternetAccount',
|
|
45
|
-
) as ApolloInternetAccountModel | undefined
|
|
46
|
-
if (!apolloInternetAccount) {
|
|
47
|
-
throw new Error('No Apollo internet account found')
|
|
48
|
-
}
|
|
49
|
-
const { baseURL } = apolloInternetAccount
|
|
50
29
|
const [errorMessage, setErrorMessage] = useState<string>()
|
|
51
30
|
const [displayGridData, setDisplayGridData] = useState<GridRowsProp[]>([])
|
|
52
31
|
|
|
32
|
+
const { apolloDataStore } = session
|
|
33
|
+
|
|
53
34
|
const gridColumns: GridColDef[] = [
|
|
54
35
|
{ field: '_id', headerName: 'id', width: 50 },
|
|
55
36
|
{
|
|
@@ -62,48 +43,21 @@ export function ViewCheckResults({
|
|
|
62
43
|
{ field: 'message', headerName: 'Message', flex: 1 },
|
|
63
44
|
]
|
|
64
45
|
|
|
65
|
-
const assemblies = collaborationServerDriver.getAssemblies()
|
|
66
|
-
const [selectedAssembly, setSelectedAssembly] = useState(assemblies.at(0))
|
|
67
|
-
|
|
68
46
|
useEffect(() => {
|
|
69
47
|
async function getGridData() {
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
48
|
+
const backendDriver = apolloDataStore.getBackendDriver(assemblyName)
|
|
49
|
+
if (!backendDriver) {
|
|
50
|
+
setErrorMessage(`No driver found for assembly "${assemblyName}"`)
|
|
72
51
|
return
|
|
73
52
|
}
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const uri = url.toString()
|
|
78
|
-
const apolloFetch = apolloInternetAccount?.getFetcher({
|
|
79
|
-
locationType: 'UriLocation',
|
|
80
|
-
uri,
|
|
81
|
-
})
|
|
82
|
-
if (apolloFetch) {
|
|
83
|
-
const response = await apolloFetch(uri, {
|
|
84
|
-
headers: new Headers({ 'Content-Type': 'application/json' }),
|
|
85
|
-
})
|
|
86
|
-
if (!response.ok) {
|
|
87
|
-
const newErrorMessage = await createFetchErrorMessage(
|
|
88
|
-
response,
|
|
89
|
-
'Error when retrieving checks',
|
|
90
|
-
)
|
|
91
|
-
setErrorMessage(newErrorMessage)
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
const data = await response.json()
|
|
95
|
-
setDisplayGridData(data)
|
|
96
|
-
}
|
|
53
|
+
const data = await backendDriver.getCheckResults(assemblyName)
|
|
54
|
+
// @ts-expect-error not sure how to type this
|
|
55
|
+
setDisplayGridData(data)
|
|
97
56
|
}
|
|
98
57
|
getGridData().catch((error) => {
|
|
99
58
|
setErrorMessage(String(error))
|
|
100
59
|
})
|
|
101
|
-
}, [
|
|
102
|
-
|
|
103
|
-
function handleChangeAssembly(e: SelectChangeEvent) {
|
|
104
|
-
const newAssembly = assemblies.find((asm) => asm.name === e.target.value)
|
|
105
|
-
setSelectedAssembly(newAssembly)
|
|
106
|
-
}
|
|
60
|
+
}, [apolloDataStore, assemblyName])
|
|
107
61
|
|
|
108
62
|
return (
|
|
109
63
|
<Dialog
|
|
@@ -113,26 +67,14 @@ export function ViewCheckResults({
|
|
|
113
67
|
handleClose={handleClose}
|
|
114
68
|
data-testid="view-check-results"
|
|
115
69
|
>
|
|
116
|
-
<Select
|
|
117
|
-
style={{ width: 200, marginLeft: 40 }}
|
|
118
|
-
value={selectedAssembly?.name ?? ''}
|
|
119
|
-
onChange={handleChangeAssembly}
|
|
120
|
-
disabled={assemblies.length === 0}
|
|
121
|
-
>
|
|
122
|
-
{assemblies.map((option) => (
|
|
123
|
-
<MenuItem key={option.name} value={option.name}>
|
|
124
|
-
{option.displayName}
|
|
125
|
-
</MenuItem>
|
|
126
|
-
))}
|
|
127
|
-
</Select>
|
|
128
|
-
|
|
129
70
|
<DialogContent>
|
|
71
|
+
<DialogContentText>Check results for {assemblyName}</DialogContentText>
|
|
130
72
|
<DataGrid
|
|
131
73
|
pagination
|
|
132
74
|
rows={displayGridData}
|
|
133
75
|
columns={gridColumns}
|
|
134
76
|
getRowId={(row) => row._id}
|
|
135
|
-
|
|
77
|
+
showToolbar
|
|
136
78
|
initialState={{
|
|
137
79
|
sorting: { sortModel: [{ field: 'name', sort: 'asc' }] },
|
|
138
80
|
columns: { columnVisibilityModel: { name: true } },
|
package/src/components/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './AddAssembly'
|
|
|
2
2
|
export * from './AddAssemblyAliases'
|
|
3
3
|
export * from './AddChildFeature'
|
|
4
4
|
export * from './AddFeature'
|
|
5
|
+
export * from './ColorFeature'
|
|
5
6
|
export * from './CopyFeature'
|
|
6
7
|
export * from './DeleteAssembly'
|
|
7
8
|
export * from './DeleteFeature'
|
|
@@ -12,7 +13,6 @@ export * from './ManageChecks'
|
|
|
12
13
|
export * from './ManageUsers'
|
|
13
14
|
export * from './MergeExons'
|
|
14
15
|
export * from './MergeTranscripts'
|
|
15
|
-
export * from './OpenLocalFile'
|
|
16
16
|
export * from './ViewChangeLog'
|
|
17
17
|
export * from './AddRefSeqAliases'
|
|
18
18
|
export * from './ViewCheckResults'
|
package/src/config.ts
CHANGED
|
@@ -3,24 +3,42 @@ import { types } from '@jbrowse/mobx-state-tree'
|
|
|
3
3
|
|
|
4
4
|
import { OntologyRecordConfiguration } from './OntologyManager'
|
|
5
5
|
|
|
6
|
-
const ApolloPluginConfigurationSchema
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
6
|
+
const ApolloPluginConfigurationSchema: ReturnType<typeof ConfigurationSchema> =
|
|
7
|
+
ConfigurationSchema(
|
|
8
|
+
'ApolloPlugin',
|
|
9
|
+
{
|
|
10
|
+
ontologies: types.array(OntologyRecordConfiguration),
|
|
11
|
+
featureTypeOntologyName: {
|
|
12
|
+
description: 'Name of the feature type ontology',
|
|
13
|
+
type: 'string',
|
|
14
|
+
defaultValue: 'Sequence Ontology',
|
|
15
|
+
},
|
|
16
|
+
hasRole: {
|
|
17
|
+
description: 'Flag used internally by jbrowse-plugin-apollo',
|
|
18
|
+
type: 'boolean',
|
|
19
|
+
defaultValue: false,
|
|
20
|
+
},
|
|
21
|
+
skippedAttributesOnCopy: {
|
|
22
|
+
description: 'Feature attribute keys to skip when copying features',
|
|
23
|
+
type: 'stringArray',
|
|
24
|
+
defaultValue: [],
|
|
25
|
+
},
|
|
26
|
+
geneBackgroundColor: {
|
|
27
|
+
description: 'Color for feature background',
|
|
28
|
+
type: 'string',
|
|
29
|
+
defaultValue: 'jexl:geneBackgroundColor(featureType)',
|
|
30
|
+
contextVariable: ['featureType'],
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
+
actions: (self: any) => ({
|
|
36
|
+
addOntology(ontologySnapshot: { name: string }) {
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
38
|
+
self.ontologies.push(ontologySnapshot)
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
)
|
|
25
43
|
|
|
26
44
|
export default ApolloPluginConfigurationSchema
|
|
@@ -110,7 +110,7 @@ describe('Convert JBrowse feature to annotation feature', () => {
|
|
|
110
110
|
expect(xcds?.type).toStrictEqual('CDS')
|
|
111
111
|
expect(xcds?.min).toStrictEqual(15)
|
|
112
112
|
expect(xcds?.max).toStrictEqual(27)
|
|
113
|
-
expect(xcds?.attributes?.
|
|
113
|
+
expect(xcds?.attributes?.gff_name?.at(0)).toStrictEqual('XYZ')
|
|
114
114
|
expect(xcds?.attributes?.gff_score?.at(0)).toStrictEqual('0')
|
|
115
115
|
expect(xcds?.attributes?.gff_source?.at(0)).toStrictEqual('mySource')
|
|
116
116
|
} else {
|
|
@@ -6,19 +6,16 @@
|
|
|
6
6
|
import type { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
7
7
|
import { gff3ToAnnotationFeature } from '@apollo-annotation/shared'
|
|
8
8
|
import type { GFF3Feature } from '@gmod/gff'
|
|
9
|
-
import type { Assembly } from '@jbrowse/core/assemblyManager/assembly'
|
|
10
9
|
import type { PluggableElementType } from '@jbrowse/core/pluggableElementTypes'
|
|
11
10
|
import type DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType'
|
|
12
|
-
import {
|
|
13
|
-
type AbstractSessionModel,
|
|
14
|
-
getContainingView,
|
|
15
|
-
getSession,
|
|
16
|
-
} from '@jbrowse/core/util'
|
|
11
|
+
import { getContainingView, getSession } from '@jbrowse/core/util'
|
|
17
12
|
import type { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
18
13
|
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
19
|
-
import AddIcon from '@mui/icons-material/Add'
|
|
20
14
|
|
|
15
|
+
import { CollaborationServerDriver } from '../BackendDrivers'
|
|
21
16
|
import { CreateApolloAnnotation } from '../components/CreateApolloAnnotation'
|
|
17
|
+
import { Apollo as ApolloIcon } from '../menus/Icons'
|
|
18
|
+
import type { ApolloSessionModel } from '../session'
|
|
22
19
|
|
|
23
20
|
function simpleFeatureToGFF3Feature(
|
|
24
21
|
feature: Feature,
|
|
@@ -60,29 +57,67 @@ export function jbrowseFeatureToAnnotationFeature(
|
|
|
60
57
|
return gff3ToAnnotationFeature(simpleFeatureToGFF3Feature(feature, refSeqId))
|
|
61
58
|
}
|
|
62
59
|
|
|
60
|
+
const fieldsToSkip = new Set([
|
|
61
|
+
'start',
|
|
62
|
+
'end',
|
|
63
|
+
'type',
|
|
64
|
+
'strand',
|
|
65
|
+
'refName',
|
|
66
|
+
'subfeatures',
|
|
67
|
+
'derived_features',
|
|
68
|
+
'phase',
|
|
69
|
+
'source',
|
|
70
|
+
'score',
|
|
71
|
+
'parent',
|
|
72
|
+
// From https://github.com/GMOD/jbrowse-components/blob/ab3126374367f43d01038d6d2e86d8db03c4d8d8/packages/core/src/BaseFeatureWidget/BaseFeatureDetail/Attributes.tsx#L12-L24
|
|
73
|
+
'__jbrowsefmt',
|
|
74
|
+
'length',
|
|
75
|
+
'position',
|
|
76
|
+
'uniqueId',
|
|
77
|
+
'exonFrames',
|
|
78
|
+
'parentId',
|
|
79
|
+
'thickStart',
|
|
80
|
+
'thickEnd',
|
|
81
|
+
'_lineHash',
|
|
82
|
+
])
|
|
83
|
+
|
|
84
|
+
const fieldsToRename: Record<string, string | undefined> = {
|
|
85
|
+
id: 'gff_id',
|
|
86
|
+
name: 'gff_name',
|
|
87
|
+
alias: 'gff_alias',
|
|
88
|
+
target: 'gff_target',
|
|
89
|
+
gap: 'gff_gap',
|
|
90
|
+
derives_from: 'gff_derives_from',
|
|
91
|
+
note: 'gff_note',
|
|
92
|
+
dbxref: 'gff_dbxref',
|
|
93
|
+
ontology_term: 'gff_ontology_term',
|
|
94
|
+
is_circular: 'gff_is_circular',
|
|
95
|
+
}
|
|
96
|
+
|
|
63
97
|
function convertFeatureAttributes(feature: Feature): Record<string, string[]> {
|
|
64
98
|
const attributes: Record<string, string[]> = {}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
'type',
|
|
69
|
-
'strand',
|
|
70
|
-
'refName',
|
|
71
|
-
'subfeatures',
|
|
72
|
-
'derived_features',
|
|
73
|
-
'phase',
|
|
74
|
-
'source',
|
|
75
|
-
'score',
|
|
76
|
-
])
|
|
77
|
-
for (const [key, value] of Object.entries(feature.toJSON())) {
|
|
78
|
-
if (defaultFields.has(key)) {
|
|
99
|
+
|
|
100
|
+
for (const [originalKey, value] of Object.entries(feature.toJSON())) {
|
|
101
|
+
if (fieldsToSkip.has(originalKey)) {
|
|
79
102
|
continue
|
|
80
103
|
}
|
|
104
|
+
const renamedKey = fieldsToRename[originalKey]
|
|
105
|
+
const key = renamedKey ?? originalKey
|
|
81
106
|
attributes[key] = Array.isArray(value) ? value.map(String) : [String(value)]
|
|
82
107
|
}
|
|
83
108
|
return attributes
|
|
84
109
|
}
|
|
85
110
|
|
|
111
|
+
function getTopLevelSimpleFeature(feature: Feature) {
|
|
112
|
+
let topLevel = feature
|
|
113
|
+
let parent = feature.get('parent')
|
|
114
|
+
while (parent) {
|
|
115
|
+
topLevel = parent
|
|
116
|
+
parent = parent.get('parent')
|
|
117
|
+
}
|
|
118
|
+
return topLevel
|
|
119
|
+
}
|
|
120
|
+
|
|
86
121
|
export function annotationFromJBrowseFeature(
|
|
87
122
|
pluggableElement: PluggableElementType,
|
|
88
123
|
) {
|
|
@@ -108,29 +143,6 @@ export function annotationFromJBrowseFeature(
|
|
|
108
143
|
}
|
|
109
144
|
return assembly
|
|
110
145
|
},
|
|
111
|
-
getRefSeqId(assembly: Assembly) {
|
|
112
|
-
const firstRegion = self.getFirstRegion()
|
|
113
|
-
const { refName } = firstRegion
|
|
114
|
-
const { refNameAliases } = assembly
|
|
115
|
-
if (!refNameAliases) {
|
|
116
|
-
throw new Error(`Could not find aliases for ${assembly.name}`)
|
|
117
|
-
}
|
|
118
|
-
const newRefNames = [...Object.entries(refNameAliases)]
|
|
119
|
-
.filter(([id, refName]) => id !== refName)
|
|
120
|
-
.map(([id, refName]) => ({
|
|
121
|
-
_id: id,
|
|
122
|
-
name: refName,
|
|
123
|
-
}))
|
|
124
|
-
const refSeqId = newRefNames.find((item) => item.name === refName)?._id
|
|
125
|
-
if (!refSeqId) {
|
|
126
|
-
throw new Error(`Could not find refSeqId named ${refName}`)
|
|
127
|
-
}
|
|
128
|
-
return refSeqId
|
|
129
|
-
},
|
|
130
|
-
getAnnotationFeature(assembly: Assembly, feature: Feature) {
|
|
131
|
-
const refSeqId = self.getRefSeqId(assembly)
|
|
132
|
-
return jbrowseFeatureToAnnotationFeature(feature, refSeqId)
|
|
133
|
-
},
|
|
134
146
|
}))
|
|
135
147
|
.views((self) => {
|
|
136
148
|
const superContextMenuItems = self.contextMenuItems
|
|
@@ -144,30 +156,46 @@ export function annotationFromJBrowseFeature(
|
|
|
144
156
|
if (!feature) {
|
|
145
157
|
return superContextMenuItems()
|
|
146
158
|
}
|
|
159
|
+
const topLevelFeature = getTopLevelSimpleFeature(feature)
|
|
147
160
|
return [
|
|
148
161
|
...superContextMenuItems(),
|
|
149
162
|
{
|
|
150
163
|
label: 'Create Apollo annotation',
|
|
151
|
-
icon:
|
|
152
|
-
onClick: () => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
icon: ApolloIcon,
|
|
165
|
+
onClick: async () => {
|
|
166
|
+
const backendDriver = (
|
|
167
|
+
session as unknown as ApolloSessionModel
|
|
168
|
+
).apolloDataStore.getBackendDriver(region.assemblyName)
|
|
169
|
+
let refSeqId = region.refName
|
|
170
|
+
if (backendDriver instanceof CollaborationServerDriver) {
|
|
171
|
+
const backendRefSeqId = await backendDriver.getRefSeqId(
|
|
172
|
+
region.assemblyName,
|
|
173
|
+
region.refName,
|
|
174
|
+
)
|
|
175
|
+
if (!backendRefSeqId) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`Could not find refSeq for "${region.refName}"`,
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
refSeqId = backendRefSeqId
|
|
181
|
+
}
|
|
182
|
+
const annotationFeature = jbrowseFeatureToAnnotationFeature(
|
|
183
|
+
topLevelFeature,
|
|
184
|
+
refSeqId,
|
|
170
185
|
)
|
|
186
|
+
session.queueDialog((doneCallback) => [
|
|
187
|
+
CreateApolloAnnotation,
|
|
188
|
+
{
|
|
189
|
+
session,
|
|
190
|
+
handleClose: () => {
|
|
191
|
+
doneCallback()
|
|
192
|
+
},
|
|
193
|
+
annotationFeature,
|
|
194
|
+
assembly,
|
|
195
|
+
refSeqId,
|
|
196
|
+
region,
|
|
197
|
+
},
|
|
198
|
+
])
|
|
171
199
|
},
|
|
172
200
|
},
|
|
173
201
|
]
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
6
6
|
import type { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
7
|
-
import type { Assembly } from '@jbrowse/core/assemblyManager/assembly'
|
|
8
7
|
import type {
|
|
9
8
|
DisplayType,
|
|
10
9
|
PluggableElementType,
|
|
@@ -14,11 +13,14 @@ import {
|
|
|
14
13
|
getContainingView,
|
|
15
14
|
getSession,
|
|
16
15
|
} from '@jbrowse/core/util'
|
|
16
|
+
import type { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
17
17
|
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
18
|
-
import AddIcon from '@mui/icons-material/Add'
|
|
19
18
|
import ObjectID from 'bson-objectid'
|
|
20
19
|
|
|
20
|
+
import { CollaborationServerDriver } from '../BackendDrivers'
|
|
21
21
|
import { CreateApolloAnnotation } from '../components/CreateApolloAnnotation'
|
|
22
|
+
import { Apollo as ApolloIcon } from '../menus/Icons'
|
|
23
|
+
import type { ApolloSessionModel } from '../session'
|
|
22
24
|
|
|
23
25
|
function parseCigar(cigar: string): [string, number][] {
|
|
24
26
|
const regex = /(\d+)([MIDNSHPX=])/g
|
|
@@ -44,7 +46,7 @@ export function annotationFromPileup(pluggableElement: PluggableElementType) {
|
|
|
44
46
|
return lgv.dynamicBlocks.contentBlocks[0]
|
|
45
47
|
},
|
|
46
48
|
getAssembly() {
|
|
47
|
-
const firstRegion =
|
|
49
|
+
const firstRegion = this.getFirstRegion()
|
|
48
50
|
const session = getSession(self)
|
|
49
51
|
const { assemblyManager } = session
|
|
50
52
|
const { assemblyName } = firstRegion
|
|
@@ -54,35 +56,13 @@ export function annotationFromPileup(pluggableElement: PluggableElementType) {
|
|
|
54
56
|
}
|
|
55
57
|
return assembly
|
|
56
58
|
},
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
throw new Error(`Could not find aliases for ${assembly.name}`)
|
|
63
|
-
}
|
|
64
|
-
const newRefNames = [...Object.entries(refNameAliases)]
|
|
65
|
-
.filter(([id, refName]) => id !== refName)
|
|
66
|
-
.map(([id, refName]) => ({
|
|
67
|
-
_id: id,
|
|
68
|
-
name: refName,
|
|
69
|
-
}))
|
|
70
|
-
const refSeqId = newRefNames.find((item) => item.name === refName)?._id
|
|
71
|
-
if (!refSeqId) {
|
|
72
|
-
throw new Error(`Could not find refSeqId named ${refName}`)
|
|
73
|
-
}
|
|
74
|
-
return refSeqId
|
|
75
|
-
},
|
|
76
|
-
getAnnotationFeature() {
|
|
77
|
-
const feature = self.contextMenuFeature
|
|
78
|
-
const assembly = self.getAssembly()
|
|
79
|
-
const refSeqId = self.getRefSeqId(assembly)
|
|
80
|
-
const start: number = feature.get('start')
|
|
81
|
-
const end: number = feature.get('end')
|
|
82
|
-
const strand = feature.get('strand')
|
|
83
|
-
const name = feature.get('name')
|
|
59
|
+
getAnnotationFeature(jbrowseFeature: Feature, refSeqId: string) {
|
|
60
|
+
const start: number = jbrowseFeature.get('start')
|
|
61
|
+
const end: number = jbrowseFeature.get('end')
|
|
62
|
+
const strand = jbrowseFeature.get('strand') as 1 | -1 | undefined
|
|
63
|
+
const name = jbrowseFeature.get('name') as string | undefined
|
|
84
64
|
|
|
85
|
-
const cigarData
|
|
65
|
+
const cigarData = jbrowseFeature.get('CIGAR') as string
|
|
86
66
|
const ops = parseCigar(cigarData)
|
|
87
67
|
let position = start
|
|
88
68
|
let currentExonStart: number | undefined
|
|
@@ -151,9 +131,10 @@ export function annotationFromPileup(pluggableElement: PluggableElementType) {
|
|
|
151
131
|
max: end,
|
|
152
132
|
type: 'mRNA',
|
|
153
133
|
strand,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
134
|
+
}
|
|
135
|
+
if (name) {
|
|
136
|
+
newFeature.attributes = {}
|
|
137
|
+
newFeature.attributes.gff_name = [name]
|
|
157
138
|
}
|
|
158
139
|
if (exons.length === 0) {
|
|
159
140
|
return newFeature
|
|
@@ -183,16 +164,32 @@ export function annotationFromPileup(pluggableElement: PluggableElementType) {
|
|
|
183
164
|
const session = getSession(self)
|
|
184
165
|
const assembly = self.getAssembly()
|
|
185
166
|
const region = self.getFirstRegion()
|
|
186
|
-
const
|
|
187
|
-
if (!
|
|
167
|
+
const jbrowseFeature = self.contextMenuFeature
|
|
168
|
+
if (!jbrowseFeature) {
|
|
188
169
|
return superContextMenuItems()
|
|
189
170
|
}
|
|
190
171
|
return [
|
|
191
172
|
...superContextMenuItems(),
|
|
192
173
|
{
|
|
193
174
|
label: 'Create Apollo annotation',
|
|
194
|
-
icon:
|
|
195
|
-
onClick: () => {
|
|
175
|
+
icon: ApolloIcon,
|
|
176
|
+
onClick: async () => {
|
|
177
|
+
const backendDriver = (
|
|
178
|
+
session as unknown as ApolloSessionModel
|
|
179
|
+
).apolloDataStore.getBackendDriver(region.assemblyName)
|
|
180
|
+
let refSeqId = region.refName
|
|
181
|
+
if (backendDriver instanceof CollaborationServerDriver) {
|
|
182
|
+
const backendRefSeqId = await backendDriver.getRefSeqId(
|
|
183
|
+
region.assemblyName,
|
|
184
|
+
region.refName,
|
|
185
|
+
)
|
|
186
|
+
if (!backendRefSeqId) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`Could not find refSeq for "${region.refName}"`,
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
refSeqId = backendRefSeqId
|
|
192
|
+
}
|
|
196
193
|
;(session as unknown as AbstractSessionModel).queueDialog(
|
|
197
194
|
(doneCallback) => [
|
|
198
195
|
CreateApolloAnnotation,
|
|
@@ -201,9 +198,12 @@ export function annotationFromPileup(pluggableElement: PluggableElementType) {
|
|
|
201
198
|
handleClose: () => {
|
|
202
199
|
doneCallback()
|
|
203
200
|
},
|
|
204
|
-
annotationFeature: self.getAnnotationFeature(
|
|
201
|
+
annotationFeature: self.getAnnotationFeature(
|
|
202
|
+
jbrowseFeature,
|
|
203
|
+
refSeqId,
|
|
204
|
+
),
|
|
205
205
|
assembly,
|
|
206
|
-
refSeqId
|
|
206
|
+
refSeqId,
|
|
207
207
|
region,
|
|
208
208
|
},
|
|
209
209
|
],
|
package/src/index.ts
CHANGED
|
@@ -91,6 +91,12 @@ interface ApolloMessageData {
|
|
|
91
91
|
assembly: string
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
interface JBrowseTrackConfig {
|
|
95
|
+
trackId: string
|
|
96
|
+
type: string
|
|
97
|
+
displays?: { type: string; displayId: string }[]
|
|
98
|
+
}
|
|
99
|
+
|
|
94
100
|
function isApolloMessageData(data?: unknown): data is ApolloMessageData {
|
|
95
101
|
return (
|
|
96
102
|
typeof data === 'object' &&
|
|
@@ -118,7 +124,8 @@ validationRegistry.registerValidation(new ParentChildValidation())
|
|
|
118
124
|
export default class ApolloPlugin extends Plugin {
|
|
119
125
|
name = 'ApolloPlugin'
|
|
120
126
|
version = version
|
|
121
|
-
configurationSchema =
|
|
127
|
+
configurationSchema: ReturnType<typeof ConfigurationSchema> =
|
|
128
|
+
ApolloPluginConfigurationSchema
|
|
122
129
|
|
|
123
130
|
install(pluginManager: PluginManager) {
|
|
124
131
|
installApolloSequenceAdapter(pluginManager)
|
|
@@ -288,6 +295,43 @@ export default class ApolloPlugin extends Plugin {
|
|
|
288
295
|
annotationFromJBrowseFeature,
|
|
289
296
|
)
|
|
290
297
|
|
|
298
|
+
pluginManager.addToExtensionPoint(
|
|
299
|
+
'Core-preProcessTrackConfig',
|
|
300
|
+
(snap: JBrowseTrackConfig): JBrowseTrackConfig => {
|
|
301
|
+
if (snap.type !== 'ReferenceSequenceTrack') {
|
|
302
|
+
return snap
|
|
303
|
+
}
|
|
304
|
+
const displays = snap.displays ?? []
|
|
305
|
+
const apolloDisplayIdx = displays.findIndex(
|
|
306
|
+
(d) => d.type === 'LinearApolloReferenceSequenceDisplay',
|
|
307
|
+
)
|
|
308
|
+
if (apolloDisplayIdx === 0) {
|
|
309
|
+
return snap
|
|
310
|
+
}
|
|
311
|
+
if (apolloDisplayIdx === -1) {
|
|
312
|
+
return {
|
|
313
|
+
...snap,
|
|
314
|
+
displays: [
|
|
315
|
+
{
|
|
316
|
+
type: 'LinearApolloReferenceSequenceDisplay',
|
|
317
|
+
displayId: `${snap.trackId}-LinearApolloReferenceSequenceDisplay`,
|
|
318
|
+
},
|
|
319
|
+
...displays,
|
|
320
|
+
],
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const reorderedDisplays = displays.toSpliced(apolloDisplayIdx, 1)
|
|
324
|
+
reorderedDisplays.unshift({
|
|
325
|
+
type: 'LinearApolloReferenceSequenceDisplay',
|
|
326
|
+
displayId: `${snap.trackId}-LinearApolloReferenceSequenceDisplay`,
|
|
327
|
+
})
|
|
328
|
+
return {
|
|
329
|
+
...snap,
|
|
330
|
+
displays: reorderedDisplays,
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
)
|
|
334
|
+
|
|
291
335
|
pluginManager.addToExtensionPoint(
|
|
292
336
|
'LinearGenomeView-searchResultSelected',
|
|
293
337
|
(_: any, props: Record<string, unknown>) => {
|
|
@@ -65,9 +65,16 @@ function scrollSelectedFeatureIntoView(
|
|
|
65
65
|
) {
|
|
66
66
|
const { apolloRowHeight, selectedFeature } = model
|
|
67
67
|
if (scrollContainerRef.current && selectedFeature) {
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
const
|
|
68
|
+
let row: number | undefined
|
|
69
|
+
if ('getFeatureLayoutPosition' in model) {
|
|
70
|
+
const position = model.getFeatureLayoutPosition(selectedFeature)
|
|
71
|
+
if (position) {
|
|
72
|
+
row = position.layoutRow + position.featureRow
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
row = model.getRowForFeature(selectedFeature)
|
|
76
|
+
}
|
|
77
|
+
if (row !== undefined) {
|
|
71
78
|
const top = row * apolloRowHeight
|
|
72
79
|
scrollContainerRef.current.scroll({ top, behavior: 'smooth' })
|
|
73
80
|
}
|