@apollo-annotation/jbrowse-plugin-apollo 0.3.8 → 0.3.9
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 +10932 -10932
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +10845 -10846
- 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 +18619 -21342
- 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 +7 -7
- package/src/ApolloInternetAccount/model.ts +81 -63
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +4 -4
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +9 -7
- package/src/BackendDrivers/CollaborationServerDriver.ts +49 -18
- package/src/BackendDrivers/DesktopFileDriver.ts +2 -2
- package/src/ChangeManager.ts +3 -1
- package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -4
- package/src/FeatureDetailsWidget/NumberTextField.tsx +5 -2
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +39 -203
- package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +92 -0
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +6 -102
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +31 -230
- package/src/LinearApolloDisplay/glyphs/util.ts +19 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +181 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceTrack.ts +218 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +62 -386
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +6 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +122 -70
- package/src/components/AddAssembly.tsx +33 -37
- package/src/components/AddFeature.tsx +21 -18
- package/src/components/AddRefSeqAliases.tsx +56 -42
- package/src/components/CopyFeature.tsx +1 -1
- package/src/components/CreateApolloAnnotation.tsx +22 -10
- package/src/components/DeleteAssembly.tsx +2 -9
- package/src/components/DownloadGFF3.tsx +2 -2
- package/src/components/ManageChecks.tsx +2 -9
- package/src/components/ManageUsers.tsx +23 -22
- package/src/components/OntologyTermAutocomplete.tsx +1 -8
- package/src/components/ViewChangeLog.tsx +25 -50
- package/src/components/ViewCheckResults.tsx +1 -7
- package/src/config.ts +3 -3
- package/src/index.ts +17 -16
- package/src/makeDisplayComponent.tsx +9 -13
- package/src/session/ClientDataStore.ts +32 -14
- package/src/session/session.ts +19 -27
- package/src/util/glyphUtils.ts +178 -1
- package/src/util/loadAssemblyIntoClient.ts +3 -2
|
@@ -193,11 +193,8 @@ export function CreateApolloAnnotation({
|
|
|
193
193
|
continue
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
// Destination feature should be of type gene
|
|
197
|
-
if (
|
|
198
|
-
featureTypeOntology?.isTypeOf(f.type, 'gene') &&
|
|
199
|
-
f.strand === annotationFeature.strand
|
|
200
|
-
) {
|
|
196
|
+
// Destination feature should be of type gene
|
|
197
|
+
if (featureTypeOntology?.isTypeOf(f.type, 'gene')) {
|
|
201
198
|
const featureSnapshot = getSnapshot(f)
|
|
202
199
|
filteredFeatures.push(featureSnapshot)
|
|
203
200
|
}
|
|
@@ -373,7 +370,7 @@ export function CreateApolloAnnotation({
|
|
|
373
370
|
})
|
|
374
371
|
}
|
|
375
372
|
|
|
376
|
-
await submitChange(change)
|
|
373
|
+
await submitChange(change, annotationFeature._id)
|
|
377
374
|
}
|
|
378
375
|
|
|
379
376
|
const copyTranscriptsToDestinationGene = async (
|
|
@@ -384,6 +381,15 @@ export function CreateApolloAnnotation({
|
|
|
384
381
|
}
|
|
385
382
|
for (const transcriptId of Object.keys(transcripts)) {
|
|
386
383
|
const transcript = transcripts[transcriptId]
|
|
384
|
+
transcript.strand = selectedDestinationFeature.strand
|
|
385
|
+
|
|
386
|
+
// update strand of transcript children if they exist
|
|
387
|
+
if (transcript.children) {
|
|
388
|
+
for (const childId of Object.keys(transcript.children)) {
|
|
389
|
+
transcript.children[childId].strand =
|
|
390
|
+
selectedDestinationFeature.strand
|
|
391
|
+
}
|
|
392
|
+
}
|
|
387
393
|
const change = new AddFeatureChange({
|
|
388
394
|
parentFeatureId: selectedDestinationFeature._id,
|
|
389
395
|
changedIds: [selectedDestinationFeature._id],
|
|
@@ -391,7 +397,8 @@ export function CreateApolloAnnotation({
|
|
|
391
397
|
assembly: assembly.name,
|
|
392
398
|
addedFeature: transcript,
|
|
393
399
|
})
|
|
394
|
-
|
|
400
|
+
// selects the last added transcript
|
|
401
|
+
await submitChange(change, transcriptId)
|
|
395
402
|
}
|
|
396
403
|
}
|
|
397
404
|
|
|
@@ -419,8 +426,7 @@ export function CreateApolloAnnotation({
|
|
|
419
426
|
},
|
|
420
427
|
},
|
|
421
428
|
})
|
|
422
|
-
await submitChange(change)
|
|
423
|
-
apolloSessionModel.apolloSetSelectedFeature(newGeneId)
|
|
429
|
+
await submitChange(change, newGeneId)
|
|
424
430
|
}
|
|
425
431
|
|
|
426
432
|
const extendSelectedDestinationFeatureLocation = async (
|
|
@@ -462,8 +468,14 @@ export function CreateApolloAnnotation({
|
|
|
462
468
|
|
|
463
469
|
const submitChange = async (
|
|
464
470
|
change: AddFeatureChange | LocationStartChange | LocationEndChange,
|
|
471
|
+
selectedFeatureId?: string,
|
|
465
472
|
) => {
|
|
466
|
-
await apolloSessionModel.apolloDataStore.changeManager
|
|
473
|
+
await apolloSessionModel.apolloDataStore.changeManager
|
|
474
|
+
.submit(change)
|
|
475
|
+
.then(() => {
|
|
476
|
+
// Selects the newly added/modified feature
|
|
477
|
+
apolloSessionModel.apolloSetSelectedFeature(selectedFeatureId)
|
|
478
|
+
})
|
|
467
479
|
}
|
|
468
480
|
|
|
469
481
|
const handleCreateNewGeneChange = (
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
3
3
|
import { DeleteAssemblyChange } from '@apollo-annotation/shared'
|
|
4
|
-
import { type Assembly } from '@jbrowse/core/assemblyManager/assembly'
|
|
5
4
|
import {
|
|
6
5
|
Button,
|
|
7
6
|
Checkbox,
|
|
@@ -15,7 +14,7 @@ import {
|
|
|
15
14
|
type SelectChangeEvent,
|
|
16
15
|
} from '@mui/material'
|
|
17
16
|
import { getRoot } from 'mobx-state-tree'
|
|
18
|
-
import React, {
|
|
17
|
+
import React, { useState } from 'react'
|
|
19
18
|
|
|
20
19
|
import { type ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
|
|
21
20
|
import {
|
|
@@ -40,7 +39,6 @@ export function DeleteAssembly({
|
|
|
40
39
|
session,
|
|
41
40
|
}: DeleteAssemblyProps) {
|
|
42
41
|
const { internetAccounts } = getRoot<ApolloRootModel>(session)
|
|
43
|
-
const [selectedAssembly, setSelectedAssembly] = useState<Assembly>()
|
|
44
42
|
const [errorMessage, setErrorMessage] = useState('')
|
|
45
43
|
const [confirmDelete, setconfirmDelete] = useState(false)
|
|
46
44
|
const [submitted, setSubmitted] = useState(false)
|
|
@@ -63,12 +61,7 @@ export function DeleteAssembly({
|
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
const assemblies = collaborationServerDriver.getAssemblies()
|
|
66
|
-
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
if (assemblies.length > 0 && selectedAssembly === undefined) {
|
|
69
|
-
setSelectedAssembly(assemblies[0])
|
|
70
|
-
}
|
|
71
|
-
}, [assemblies, selectedAssembly])
|
|
64
|
+
const [selectedAssembly, setSelectedAssembly] = useState(assemblies.at(0))
|
|
72
65
|
|
|
73
66
|
function handleChangeInternetAccount(e: SelectChangeEvent) {
|
|
74
67
|
setSubmitted(false)
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
6
6
|
import { type ApolloAssembly } from '@apollo-annotation/mst'
|
|
7
7
|
import { annotationFeatureToGFF3 } from '@apollo-annotation/shared'
|
|
8
|
-
import
|
|
8
|
+
import { type GFF3Item, formatSync } from '@gmod/gff'
|
|
9
9
|
import { type Assembly } from '@jbrowse/core/assemblyManager/assembly'
|
|
10
10
|
import { getConf } from '@jbrowse/core/configuration'
|
|
11
11
|
import {
|
|
@@ -169,7 +169,7 @@ export function DownloadGFF3({ handleClose, session }: DownloadGFF3Props) {
|
|
|
169
169
|
const { refName, seq } = sequenceFeature
|
|
170
170
|
gff3Items.push({ id: refName, description: '', sequence: seq })
|
|
171
171
|
}
|
|
172
|
-
const gff3 =
|
|
172
|
+
const gff3 = formatSync(gff3Items)
|
|
173
173
|
const gff3Blob = new Blob([gff3], { type: 'text/plain;charset=utf-8' })
|
|
174
174
|
saveAs(
|
|
175
175
|
gff3Blob,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/use-unknown-in-catch-callback-variable */
|
|
2
2
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
4
|
-
import { type Assembly } from '@jbrowse/core/assemblyManager/assembly'
|
|
5
4
|
import { type AbstractSessionModel } from '@jbrowse/core/util'
|
|
6
5
|
import {
|
|
7
6
|
Button,
|
|
@@ -52,7 +51,6 @@ interface CheckDocument {
|
|
|
52
51
|
|
|
53
52
|
export function ManageChecks({ handleClose, session }: ManageChecksProps) {
|
|
54
53
|
const { internetAccounts } = getRoot<ApolloRootModel>(session)
|
|
55
|
-
const [selectedAssembly, setSelectedAssembly] = useState<Assembly>()
|
|
56
54
|
const [errorMessage, setErrorMessage] = useState('')
|
|
57
55
|
const [submitted, setSubmitted] = useState(false)
|
|
58
56
|
const apolloInternetAccounts = internetAccounts.filter(
|
|
@@ -76,6 +74,7 @@ export function ManageChecks({ handleClose, session }: ManageChecksProps) {
|
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
const assemblies = collaborationServerDriver.getAssemblies()
|
|
77
|
+
const [selectedAssembly, setSelectedAssembly] = useState(assemblies.at(0))
|
|
79
78
|
|
|
80
79
|
useEffect(() => {
|
|
81
80
|
async function getChecks() {
|
|
@@ -99,19 +98,13 @@ export function ManageChecks({ handleClose, session }: ManageChecksProps) {
|
|
|
99
98
|
})
|
|
100
99
|
}, [selectedInternetAccount])
|
|
101
100
|
|
|
102
|
-
useEffect(() => {
|
|
103
|
-
if (assemblies.length > 0 && selectedAssembly === undefined) {
|
|
104
|
-
setSelectedAssembly(assemblies[0])
|
|
105
|
-
}
|
|
106
|
-
}, [assemblies, selectedAssembly])
|
|
107
|
-
|
|
108
101
|
useEffect(() => {
|
|
109
102
|
async function getChecks() {
|
|
110
103
|
if (!selectedAssembly) {
|
|
111
104
|
return
|
|
112
105
|
}
|
|
113
106
|
const { baseURL, getFetcher } = selectedInternetAccount
|
|
114
|
-
const uri = new URL(
|
|
107
|
+
const uri = new URL(`assemblies/${selectedAssembly.name}`, baseURL).href
|
|
115
108
|
const apolloFetch = getFetcher({ locationType: 'UriLocation', uri })
|
|
116
109
|
const response = await apolloFetch(uri, { method: 'GET' })
|
|
117
110
|
if (!response.ok) {
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
GridToolbar,
|
|
29
29
|
} from '@mui/x-data-grid'
|
|
30
30
|
import { getRoot } from 'mobx-state-tree'
|
|
31
|
-
import React, {
|
|
31
|
+
import React, { useEffect, useState } from 'react'
|
|
32
32
|
|
|
33
33
|
import { type ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
|
|
34
34
|
import { type ChangeManager } from '../ChangeManager'
|
|
@@ -72,33 +72,34 @@ export function ManageUsers({
|
|
|
72
72
|
)
|
|
73
73
|
const [users, setUsers] = useState<UserResponse[]>([])
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
async function getUsers() {
|
|
77
|
+
const { baseURL } = selectedInternetAccount
|
|
78
|
+
const uri = new URL('users', baseURL).href
|
|
79
|
+
const apolloFetch = selectedInternetAccount.getFetcher({
|
|
80
|
+
locationType: 'UriLocation',
|
|
81
|
+
uri,
|
|
82
|
+
})
|
|
83
|
+
if (apolloFetch) {
|
|
84
|
+
const response = await apolloFetch(uri, { method: 'GET' })
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
const newErrorMessage = await createFetchErrorMessage(
|
|
87
|
+
response,
|
|
88
|
+
'Error when getting user data from db',
|
|
89
|
+
)
|
|
90
|
+
setErrorMessage(newErrorMessage)
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
const data = (await response.json()) as UserResponse[]
|
|
94
|
+
setUsers(
|
|
95
|
+
data.map((u) => (u.role === undefined ? { ...u, role: '' } : u)),
|
|
88
96
|
)
|
|
89
|
-
setErrorMessage(newErrorMessage)
|
|
90
|
-
return
|
|
91
97
|
}
|
|
92
|
-
const data = (await response.json()) as UserResponse[]
|
|
93
|
-
setUsers(data.map((u) => (u.role === undefined ? { ...u, role: '' } : u)))
|
|
94
98
|
}
|
|
95
|
-
}, [selectedInternetAccount])
|
|
96
|
-
|
|
97
|
-
useEffect(() => {
|
|
98
99
|
getUsers().catch((error) => {
|
|
99
100
|
setErrorMessage(String(error))
|
|
100
101
|
})
|
|
101
|
-
}, [
|
|
102
|
+
}, [selectedInternetAccount])
|
|
102
103
|
|
|
103
104
|
async function deleteUser(id: GridRowId) {
|
|
104
105
|
const change = new DeleteUserChange({
|
|
@@ -73,21 +73,14 @@ export function OntologyTermAutocomplete({
|
|
|
73
73
|
[filterTermsProp, includeDeprecated],
|
|
74
74
|
)
|
|
75
75
|
|
|
76
|
-
// effect for clearing choices when not open
|
|
77
|
-
useEffect(() => {
|
|
78
|
-
if (!open) {
|
|
79
|
-
setTermChoices(undefined)
|
|
80
|
-
}
|
|
81
|
-
}, [open])
|
|
82
|
-
|
|
83
76
|
// effect for matching the current value with an ontology term
|
|
84
77
|
useEffect(() => {
|
|
85
78
|
const controller = new AbortController()
|
|
86
79
|
const { signal } = controller
|
|
87
80
|
if (needToLoadCurrentTerm) {
|
|
88
|
-
setCurrentOntologyTermInvalid('')
|
|
89
81
|
getCurrentTerm(ontologyStore, valueString, filterTerms, signal).then(
|
|
90
82
|
(term) => {
|
|
83
|
+
setCurrentOntologyTermInvalid('')
|
|
91
84
|
if (!signal.aborted) {
|
|
92
85
|
setCurrentOntologyTerm(term)
|
|
93
86
|
}
|
|
@@ -26,6 +26,10 @@ import React, { useEffect, useState } from 'react'
|
|
|
26
26
|
import { makeStyles } from 'tss-react/mui'
|
|
27
27
|
|
|
28
28
|
import { type ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
|
|
29
|
+
import {
|
|
30
|
+
type ApolloInternetAccount,
|
|
31
|
+
type CollaborationServerDriver,
|
|
32
|
+
} from '../BackendDrivers'
|
|
29
33
|
import { type ApolloSessionModel } from '../session'
|
|
30
34
|
import { type ApolloRootModel } from '../types'
|
|
31
35
|
import { createFetchErrorMessage } from '../util'
|
|
@@ -37,11 +41,6 @@ interface ViewChangeLogProps {
|
|
|
37
41
|
handleClose(): void
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
interface AssemblyDocument {
|
|
41
|
-
_id: string
|
|
42
|
-
name: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
44
|
const useStyles = makeStyles()((theme) => ({
|
|
46
45
|
changeTextarea: {
|
|
47
46
|
fontFamily: 'monospace',
|
|
@@ -63,12 +62,18 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
|
|
|
63
62
|
const { baseURL } = apolloInternetAccount
|
|
64
63
|
const { classes } = useStyles()
|
|
65
64
|
const [errorMessage, setErrorMessage] = useState<string>()
|
|
66
|
-
const [assemblyCollection, setAssemblyCollection] = useState<
|
|
67
|
-
AssemblyDocument[]
|
|
68
|
-
>([])
|
|
69
|
-
const [assemblyId, setAssemblyId] = useState<string>('')
|
|
70
65
|
const [displayGridData, setDisplayGridData] = useState<GridRowsProp[]>([])
|
|
71
66
|
|
|
67
|
+
const { collaborationServerDriver } = session.apolloDataStore as {
|
|
68
|
+
collaborationServerDriver: CollaborationServerDriver
|
|
69
|
+
getInternetAccount(
|
|
70
|
+
assemblyName?: string,
|
|
71
|
+
internetAccountId?: string,
|
|
72
|
+
): ApolloInternetAccount
|
|
73
|
+
}
|
|
74
|
+
const assemblies = collaborationServerDriver.getAssemblies()
|
|
75
|
+
const [selectedAssembly, setSelectedAssembly] = useState(assemblies.at(0))
|
|
76
|
+
|
|
72
77
|
const gridColumns: GridColDef[] = [
|
|
73
78
|
{ field: 'sequence' },
|
|
74
79
|
{
|
|
@@ -90,7 +95,6 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
|
|
|
90
95
|
readOnly
|
|
91
96
|
/>
|
|
92
97
|
),
|
|
93
|
-
valueFormatter: ({ value }) => JSON.stringify(value),
|
|
94
98
|
},
|
|
95
99
|
{ field: 'user', headerName: 'User', width: 140 },
|
|
96
100
|
{
|
|
@@ -102,47 +106,17 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
|
|
|
102
106
|
},
|
|
103
107
|
]
|
|
104
108
|
|
|
105
|
-
useEffect(() => {
|
|
106
|
-
async function getAssemblies() {
|
|
107
|
-
const uri = new URL('assemblies', baseURL).href
|
|
108
|
-
const apolloFetch = apolloInternetAccount?.getFetcher({
|
|
109
|
-
locationType: 'UriLocation',
|
|
110
|
-
uri,
|
|
111
|
-
})
|
|
112
|
-
if (apolloFetch) {
|
|
113
|
-
const response = await apolloFetch(uri, { method: 'GET' })
|
|
114
|
-
if (!response.ok) {
|
|
115
|
-
const newErrorMessage = await createFetchErrorMessage(
|
|
116
|
-
response,
|
|
117
|
-
'Error when retrieving assemblies from server',
|
|
118
|
-
)
|
|
119
|
-
setErrorMessage(newErrorMessage)
|
|
120
|
-
return
|
|
121
|
-
}
|
|
122
|
-
const data = (await response.json()) as AssemblyDocument[]
|
|
123
|
-
setAssemblyCollection(data)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
getAssemblies().catch((error) => {
|
|
127
|
-
setErrorMessage(String(error))
|
|
128
|
-
})
|
|
129
|
-
}, [apolloInternetAccount, baseURL])
|
|
130
|
-
|
|
131
|
-
useEffect(() => {
|
|
132
|
-
if (!assemblyId && assemblyCollection.length > 0) {
|
|
133
|
-
setAssemblyId(assemblyCollection[0]._id)
|
|
134
|
-
}
|
|
135
|
-
}, [assemblyId, assemblyCollection])
|
|
136
|
-
|
|
137
109
|
useEffect(() => {
|
|
138
110
|
async function getGridData() {
|
|
139
|
-
if (!
|
|
111
|
+
if (!selectedAssembly) {
|
|
140
112
|
return
|
|
141
113
|
}
|
|
142
114
|
|
|
143
115
|
// Get changes
|
|
144
116
|
const url = new URL('changes', baseURL)
|
|
145
|
-
const searchParams = new URLSearchParams({
|
|
117
|
+
const searchParams = new URLSearchParams({
|
|
118
|
+
assembly: selectedAssembly.name,
|
|
119
|
+
})
|
|
146
120
|
url.search = searchParams.toString()
|
|
147
121
|
const uri = url.toString()
|
|
148
122
|
const apolloFetch = apolloInternetAccount?.getFetcher({
|
|
@@ -168,10 +142,11 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
|
|
|
168
142
|
getGridData().catch((error) => {
|
|
169
143
|
setErrorMessage(String(error))
|
|
170
144
|
})
|
|
171
|
-
}, [
|
|
145
|
+
}, [apolloInternetAccount, baseURL, selectedAssembly])
|
|
172
146
|
|
|
173
147
|
function handleChangeAssembly(e: SelectChangeEvent) {
|
|
174
|
-
|
|
148
|
+
const newAssembly = assemblies.find((asm) => asm.name === e.target.value)
|
|
149
|
+
setSelectedAssembly(newAssembly)
|
|
175
150
|
}
|
|
176
151
|
|
|
177
152
|
return (
|
|
@@ -184,12 +159,12 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
|
|
|
184
159
|
>
|
|
185
160
|
<Select
|
|
186
161
|
style={{ width: 200, marginLeft: 40 }}
|
|
187
|
-
value={
|
|
162
|
+
value={selectedAssembly?.name ?? ''}
|
|
188
163
|
onChange={handleChangeAssembly}
|
|
189
164
|
>
|
|
190
|
-
{
|
|
191
|
-
<MenuItem key={option.
|
|
192
|
-
{option.name}
|
|
165
|
+
{assemblies.map((option) => (
|
|
166
|
+
<MenuItem key={option.name} value={option.name}>
|
|
167
|
+
{option.displayName || option.name}
|
|
193
168
|
</MenuItem>
|
|
194
169
|
))}
|
|
195
170
|
</Select>
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
6
6
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
7
|
-
import { type Assembly } from '@jbrowse/core/assemblyManager/assembly'
|
|
8
7
|
import {
|
|
9
8
|
Button,
|
|
10
9
|
DialogActions,
|
|
@@ -49,7 +48,6 @@ export function ViewCheckResults({
|
|
|
49
48
|
}
|
|
50
49
|
const { baseURL } = apolloInternetAccount
|
|
51
50
|
const [errorMessage, setErrorMessage] = useState<string>()
|
|
52
|
-
const [selectedAssembly, setSelectedAssembly] = useState<Assembly>()
|
|
53
51
|
const [displayGridData, setDisplayGridData] = useState<GridRowsProp[]>([])
|
|
54
52
|
|
|
55
53
|
const gridColumns: GridColDef[] = [
|
|
@@ -65,11 +63,7 @@ export function ViewCheckResults({
|
|
|
65
63
|
]
|
|
66
64
|
|
|
67
65
|
const assemblies = collaborationServerDriver.getAssemblies()
|
|
68
|
-
|
|
69
|
-
if (!selectedAssembly && assemblies.length > 0) {
|
|
70
|
-
setSelectedAssembly(assemblies[0])
|
|
71
|
-
}
|
|
72
|
-
}, [assemblies, selectedAssembly])
|
|
66
|
+
const [selectedAssembly, setSelectedAssembly] = useState(assemblies.at(0))
|
|
73
67
|
|
|
74
68
|
useEffect(() => {
|
|
75
69
|
async function getGridData() {
|
package/src/config.ts
CHANGED
|
@@ -15,10 +15,10 @@ const ApolloPluginConfigurationSchema = ConfigurationSchema('ApolloPlugin', {
|
|
|
15
15
|
type: 'boolean',
|
|
16
16
|
defaultValue: false,
|
|
17
17
|
},
|
|
18
|
-
|
|
19
|
-
description: 'Color ',
|
|
18
|
+
geneBackgroundColor: {
|
|
19
|
+
description: 'Color for feature background',
|
|
20
20
|
type: 'string',
|
|
21
|
-
defaultValue: 'jexl:
|
|
21
|
+
defaultValue: 'jexl:geneBackgroundColor(featureType)',
|
|
22
22
|
contextVariable: ['featureType'],
|
|
23
23
|
},
|
|
24
24
|
})
|
package/src/index.ts
CHANGED
|
@@ -42,7 +42,6 @@ import {
|
|
|
42
42
|
import { installApolloRefNameAliasAdapter } from './ApolloRefNameAliasAdapter'
|
|
43
43
|
import { installApolloSequenceAdapter } from './ApolloSequenceAdapter'
|
|
44
44
|
import { installApolloTextSearchAdapter } from './ApolloTextSearchAdapter'
|
|
45
|
-
import { type BackendDriver } from './BackendDrivers'
|
|
46
45
|
import {
|
|
47
46
|
ApolloFeatureDetailsWidget,
|
|
48
47
|
ApolloFeatureDetailsWidgetModel,
|
|
@@ -309,9 +308,10 @@ export default class ApolloPlugin extends Plugin {
|
|
|
309
308
|
if (!dataStore) {
|
|
310
309
|
break
|
|
311
310
|
}
|
|
312
|
-
const backendDriver = dataStore.getBackendDriver(
|
|
313
|
-
|
|
314
|
-
|
|
311
|
+
const backendDriver = dataStore.getBackendDriver(assemblyName)
|
|
312
|
+
if (!backendDriver) {
|
|
313
|
+
break
|
|
314
|
+
}
|
|
315
315
|
const { seq: sequence } =
|
|
316
316
|
await backendDriver.getSequence(region)
|
|
317
317
|
handle.workers[0].postMessage({
|
|
@@ -331,9 +331,10 @@ export default class ApolloPlugin extends Plugin {
|
|
|
331
331
|
if (!dataStore) {
|
|
332
332
|
break
|
|
333
333
|
}
|
|
334
|
-
const backendDriver = dataStore.getBackendDriver(
|
|
335
|
-
|
|
336
|
-
|
|
334
|
+
const backendDriver = dataStore.getBackendDriver(assembly)
|
|
335
|
+
if (!backendDriver) {
|
|
336
|
+
break
|
|
337
|
+
}
|
|
337
338
|
const regions = await backendDriver.getRegions(assembly)
|
|
338
339
|
handle.workers[0].postMessage({
|
|
339
340
|
apollo,
|
|
@@ -352,9 +353,10 @@ export default class ApolloPlugin extends Plugin {
|
|
|
352
353
|
if (!dataStore) {
|
|
353
354
|
break
|
|
354
355
|
}
|
|
355
|
-
const backendDriver = dataStore.getBackendDriver(
|
|
356
|
-
|
|
357
|
-
|
|
356
|
+
const backendDriver = dataStore.getBackendDriver(assembly)
|
|
357
|
+
if (!backendDriver) {
|
|
358
|
+
break
|
|
359
|
+
}
|
|
358
360
|
const refNameAliases =
|
|
359
361
|
await backendDriver.getRefNameAliases(assembly)
|
|
360
362
|
handle.workers[0].postMessage({
|
|
@@ -378,18 +380,17 @@ export default class ApolloPlugin extends Plugin {
|
|
|
378
380
|
configure(pluginManager: PluginManager) {
|
|
379
381
|
if (isAbstractMenuManager(pluginManager.rootModel)) {
|
|
380
382
|
pluginManager.jexl.addFunction(
|
|
381
|
-
'
|
|
382
|
-
(featureType:
|
|
383
|
-
if (featureType === '
|
|
383
|
+
'geneBackgroundColor',
|
|
384
|
+
(featureType: string) => {
|
|
385
|
+
if (featureType === 'pseudogene') {
|
|
384
386
|
return alpha('rgb(148, 203, 236)', 0.6)
|
|
385
387
|
}
|
|
386
|
-
if (featureType === '
|
|
388
|
+
if (featureType === 'ncRNA_gene') {
|
|
387
389
|
return alpha('rgb(194, 106, 119)', 0.6)
|
|
388
390
|
}
|
|
389
|
-
|
|
391
|
+
return
|
|
390
392
|
},
|
|
391
393
|
)
|
|
392
|
-
|
|
393
394
|
addTopLevelMenus(pluginManager.rootModel)
|
|
394
395
|
}
|
|
395
396
|
}
|
|
@@ -87,25 +87,21 @@ const ResizeHandle = ({
|
|
|
87
87
|
},
|
|
88
88
|
[onResize],
|
|
89
89
|
)
|
|
90
|
-
|
|
91
|
-
(event: MouseEvent) => {
|
|
92
|
-
event.stopPropagation()
|
|
93
|
-
event.preventDefault()
|
|
94
|
-
globalThis.removeEventListener('mousemove', mouseMove)
|
|
95
|
-
globalThis.removeEventListener('mouseup', cancelDrag)
|
|
96
|
-
globalThis.removeEventListener('mouseleave', cancelDrag)
|
|
97
|
-
},
|
|
98
|
-
[mouseMove],
|
|
99
|
-
)
|
|
90
|
+
|
|
100
91
|
return (
|
|
101
92
|
// TODO: a11y
|
|
102
93
|
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
103
94
|
<div
|
|
104
95
|
onMouseDown={(event: React.MouseEvent) => {
|
|
105
96
|
event.stopPropagation()
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
97
|
+
const controller = new AbortController()
|
|
98
|
+
const { signal } = controller
|
|
99
|
+
function abortDrag() {
|
|
100
|
+
controller.abort()
|
|
101
|
+
}
|
|
102
|
+
globalThis.addEventListener('mousemove', mouseMove, { signal })
|
|
103
|
+
globalThis.addEventListener('mouseup', abortDrag, { signal })
|
|
104
|
+
globalThis.addEventListener('mouseleave', abortDrag, { signal })
|
|
109
105
|
}}
|
|
110
106
|
onClick={(e) => {
|
|
111
107
|
e.stopPropagation()
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
|
|
34
34
|
import {
|
|
35
35
|
type ApolloInternetAccount,
|
|
36
|
+
type BackendDriver,
|
|
36
37
|
CollaborationServerDriver,
|
|
37
38
|
DesktopFileDriver,
|
|
38
39
|
InMemoryFileDriver,
|
|
@@ -86,18 +87,38 @@ export function clientDataStoreFactory(
|
|
|
86
87
|
}
|
|
87
88
|
return self.assemblies.put(assemblySnapshot)
|
|
88
89
|
},
|
|
90
|
+
}))
|
|
91
|
+
.actions((self) => ({
|
|
89
92
|
addFeature(assemblyId: string, feature: AnnotationFeatureSnapshot) {
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
const session = getSession(self)
|
|
94
|
+
const { assemblyManager } = session
|
|
95
|
+
let apolloAssembly = self.assemblies.get(assemblyId)
|
|
96
|
+
if (!apolloAssembly) {
|
|
97
|
+
// maybe it's a valid assembly that we haven't loaded yet
|
|
98
|
+
const assembly = assemblyManager.get(assemblyId)
|
|
99
|
+
if (!assembly) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Could not find assembly "${assemblyId}" to add feature "${feature._id}"`,
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
apolloAssembly = self.addAssembly(assemblyId)
|
|
95
105
|
}
|
|
96
|
-
|
|
106
|
+
let ref = apolloAssembly.refSeqs.get(feature.refSeq)
|
|
97
107
|
if (!ref) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
)
|
|
108
|
+
// maybe it's a valid refName that we haven't loaded yet
|
|
109
|
+
const assembly = assemblyManager.get(assemblyId)
|
|
110
|
+
if (!assembly) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Could not find assembly "${assemblyId}" to add feature "${feature._id}"`,
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
const canonicalRefName = assembly.getCanonicalRefName(feature.refSeq)
|
|
116
|
+
if (!canonicalRefName) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`Could not find refSeq "${feature.refSeq}" to add feature "${feature._id}"`,
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
ref = apolloAssembly.addRefSeq(feature.refSeq, canonicalRefName)
|
|
101
122
|
}
|
|
102
123
|
ref.features.put(feature)
|
|
103
124
|
},
|
|
@@ -212,15 +233,12 @@ export function clientDataStoreFactory(
|
|
|
212
233
|
},
|
|
213
234
|
}))
|
|
214
235
|
.views((self) => ({
|
|
215
|
-
getBackendDriver(assemblyId: string) {
|
|
216
|
-
if (!assemblyId) {
|
|
217
|
-
return self.collaborationServerDriver
|
|
218
|
-
}
|
|
236
|
+
getBackendDriver(assemblyId: string): BackendDriver | undefined {
|
|
219
237
|
const session = getSession(self)
|
|
220
238
|
const { assemblyManager } = session
|
|
221
239
|
const assembly = assemblyManager.get(assemblyId)
|
|
222
240
|
if (!assembly) {
|
|
223
|
-
return
|
|
241
|
+
return
|
|
224
242
|
}
|
|
225
243
|
const { file, internetAccountConfigId } = getConf(assembly, [
|
|
226
244
|
'sequence',
|