@apollo-annotation/jbrowse-plugin-apollo 0.3.7 → 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 +11212 -10483
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +11251 -10509
- 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 +7726 -9014
- 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 +18 -18
- package/src/ApolloInternetAccount/model.ts +123 -70
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +4 -4
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +9 -7
- package/src/BackendDrivers/CollaborationServerDriver.ts +72 -20
- package/src/BackendDrivers/DesktopFileDriver.ts +2 -2
- package/src/ChangeManager.ts +36 -14
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +64 -5
- package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -4
- package/src/FeatureDetailsWidget/NumberTextField.tsx +5 -2
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +70 -73
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +72 -234
- package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +92 -0
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +23 -131
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +50 -194
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +279 -217
- package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +53 -34
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -9
- package/src/LinearApolloDisplay/glyphs/util.ts +19 -0
- package/src/LinearApolloDisplay/stateModel/base.ts +34 -43
- package/src/LinearApolloDisplay/stateModel/layouts.ts +3 -2
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +32 -261
- package/src/LinearApolloDisplay/stateModel/rendering.ts +43 -343
- package/src/LinearApolloReferenceSequenceDisplay/components/LinearApolloReferenceSequenceDisplay.tsx +87 -0
- package/src/LinearApolloReferenceSequenceDisplay/components/index.ts +1 -0
- package/src/LinearApolloReferenceSequenceDisplay/configSchema.ts +7 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +181 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceTrack.ts +218 -0
- package/src/LinearApolloReferenceSequenceDisplay/index.ts +3 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +227 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/index.ts +25 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +157 -0
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +101 -38
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +334 -262
- package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +12 -8
- package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +42 -4
- package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +4 -8
- package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +73 -97
- package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +49 -61
- package/src/TabularEditor/HybridGrid/Feature.tsx +16 -14
- package/src/TabularEditor/HybridGrid/HybridGrid.tsx +7 -5
- package/src/components/AddAssembly.tsx +34 -38
- package/src/components/AddAssemblyAliases.tsx +1 -1
- package/src/components/AddChildFeature.tsx +5 -2
- package/src/components/AddFeature.tsx +30 -21
- package/src/components/AddRefSeqAliases.tsx +64 -50
- package/src/components/CopyFeature.tsx +4 -2
- package/src/components/CreateApolloAnnotation.tsx +22 -9
- package/src/components/DeleteAssembly.tsx +3 -10
- package/src/components/DownloadGFF3.tsx +2 -2
- package/src/components/EditZoomThresholdDialog.tsx +69 -0
- package/src/components/FilterFeatures.tsx +7 -7
- package/src/components/FilterTranscripts.tsx +6 -6
- package/src/components/ImportFeatures.tsx +1 -1
- package/src/components/ManageChecks.tsx +3 -10
- package/src/components/ManageUsers.tsx +23 -22
- package/src/components/MergeTranscripts.tsx +12 -15
- package/src/components/OntologyTermAutocomplete.tsx +1 -8
- package/src/components/OntologyTermMultiSelect.tsx +11 -11
- package/src/components/OpenLocalFile.tsx +11 -7
- package/src/components/ViewChangeLog.tsx +25 -50
- package/src/components/ViewCheckResults.tsx +2 -8
- package/src/components/index.ts +1 -0
- package/src/config.ts +6 -0
- package/src/index.ts +53 -115
- package/src/makeDisplayComponent.tsx +9 -14
- package/src/menus/index.ts +1 -0
- package/src/{ApolloInternetAccount/addMenuItems.ts → menus/topLevelMenu.ts} +56 -47
- package/src/menus/topLevelMenuAdmin.ts +154 -0
- package/src/session/ClientDataStore.ts +32 -14
- package/src/session/session.ts +159 -121
- package/src/util/annotationFeatureUtils.ts +15 -21
- package/src/util/displayUtils.ts +149 -0
- package/src/util/glyphUtils.ts +329 -0
- package/src/util/loadAssemblyIntoClient.ts +3 -2
- package/src/util/mouseEventsUtils.ts +32 -0
|
@@ -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,7 +426,7 @@ export function CreateApolloAnnotation({
|
|
|
419
426
|
},
|
|
420
427
|
},
|
|
421
428
|
})
|
|
422
|
-
await submitChange(change)
|
|
429
|
+
await submitChange(change, newGeneId)
|
|
423
430
|
}
|
|
424
431
|
|
|
425
432
|
const extendSelectedDestinationFeatureLocation = async (
|
|
@@ -461,8 +468,14 @@ export function CreateApolloAnnotation({
|
|
|
461
468
|
|
|
462
469
|
const submitChange = async (
|
|
463
470
|
change: AddFeatureChange | LocationStartChange | LocationEndChange,
|
|
471
|
+
selectedFeatureId?: string,
|
|
464
472
|
) => {
|
|
465
|
-
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
|
+
})
|
|
466
479
|
}
|
|
467
480
|
|
|
468
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)
|
|
@@ -142,7 +135,7 @@ export function DeleteAssembly({
|
|
|
142
135
|
>
|
|
143
136
|
{assemblies.map((option) => (
|
|
144
137
|
<MenuItem key={option.name} value={option.name}>
|
|
145
|
-
{option.displayName
|
|
138
|
+
{option.displayName}
|
|
146
139
|
</MenuItem>
|
|
147
140
|
))}
|
|
148
141
|
</Select>
|
|
@@ -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,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Dialog } from '@jbrowse/core/ui'
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
DialogActions,
|
|
5
|
+
DialogContent,
|
|
6
|
+
TextField,
|
|
7
|
+
Typography,
|
|
8
|
+
} from '@mui/material'
|
|
9
|
+
import { observer } from 'mobx-react'
|
|
10
|
+
import React, { useState } from 'react'
|
|
11
|
+
|
|
12
|
+
const EditZoomThresholdDialog = observer(function ({
|
|
13
|
+
model,
|
|
14
|
+
handleClose,
|
|
15
|
+
}: {
|
|
16
|
+
model: {
|
|
17
|
+
zoomThresholdSetting: number
|
|
18
|
+
setZoomThresholdSetting: (a: { zoomThreshold: number }) => void
|
|
19
|
+
}
|
|
20
|
+
handleClose: () => void
|
|
21
|
+
}) {
|
|
22
|
+
const [zoomThreshold, setZoomThreshold] = useState(
|
|
23
|
+
`${model.zoomThresholdSetting}`,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<Dialog open onClose={handleClose} title="Edit zoom threshold setting">
|
|
28
|
+
<DialogContent>
|
|
29
|
+
<Typography>
|
|
30
|
+
The zoom level in base pairs (bp) per pixel at which features are
|
|
31
|
+
rendered in this Annotations track. Increasing the value will allow
|
|
32
|
+
features to render when zooming out, but might impact performance.
|
|
33
|
+
</Typography>
|
|
34
|
+
<TextField
|
|
35
|
+
label="Threshold value (bpPerPx)"
|
|
36
|
+
value={zoomThreshold}
|
|
37
|
+
onChange={(event) => {
|
|
38
|
+
setZoomThreshold(event.target.value)
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
|
|
42
|
+
<DialogActions>
|
|
43
|
+
<Button
|
|
44
|
+
variant="contained"
|
|
45
|
+
onClick={() => {
|
|
46
|
+
model.setZoomThresholdSetting({
|
|
47
|
+
zoomThreshold: +zoomThreshold,
|
|
48
|
+
})
|
|
49
|
+
handleClose()
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
Submit
|
|
53
|
+
</Button>
|
|
54
|
+
<Button
|
|
55
|
+
variant="contained"
|
|
56
|
+
color="secondary"
|
|
57
|
+
onClick={() => {
|
|
58
|
+
handleClose()
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
Cancel
|
|
62
|
+
</Button>
|
|
63
|
+
</DialogActions>
|
|
64
|
+
</DialogContent>
|
|
65
|
+
</Dialog>
|
|
66
|
+
)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
export default EditZoomThresholdDialog
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
Chip,
|
|
5
5
|
DialogContent,
|
|
6
6
|
DialogContentText,
|
|
7
|
-
|
|
7
|
+
Grid,
|
|
8
8
|
TextField,
|
|
9
9
|
} from '@mui/material'
|
|
10
10
|
import { observer } from 'mobx-react'
|
|
@@ -62,8 +62,8 @@ export const FilterFeatures = observer(function FilterFeatures({
|
|
|
62
62
|
<DialogContentText>
|
|
63
63
|
Select the feature types you want to display in the apollo track
|
|
64
64
|
</DialogContentText>
|
|
65
|
-
<
|
|
66
|
-
<
|
|
65
|
+
<Grid container spacing={2}>
|
|
66
|
+
<Grid size={8}>
|
|
67
67
|
<OntologyTermAutocomplete
|
|
68
68
|
session={session}
|
|
69
69
|
ontologyName="Sequence Ontology"
|
|
@@ -84,8 +84,8 @@ export const FilterFeatures = observer(function FilterFeatures({
|
|
|
84
84
|
}
|
|
85
85
|
}}
|
|
86
86
|
/>
|
|
87
|
-
</
|
|
88
|
-
<
|
|
87
|
+
</Grid>
|
|
88
|
+
<Grid size={4}>
|
|
89
89
|
<Button
|
|
90
90
|
variant="contained"
|
|
91
91
|
onClick={handleAddFeatureType}
|
|
@@ -95,8 +95,8 @@ export const FilterFeatures = observer(function FilterFeatures({
|
|
|
95
95
|
>
|
|
96
96
|
Add
|
|
97
97
|
</Button>
|
|
98
|
-
</
|
|
99
|
-
</
|
|
98
|
+
</Grid>
|
|
99
|
+
</Grid>
|
|
100
100
|
{selectedFeatureTypes.length > 0 && (
|
|
101
101
|
<div>
|
|
102
102
|
<hr />
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
DialogContentText,
|
|
6
6
|
FormControlLabel,
|
|
7
7
|
FormGroup,
|
|
8
|
-
|
|
8
|
+
Grid,
|
|
9
9
|
} from '@mui/material'
|
|
10
10
|
import { observer } from 'mobx-react'
|
|
11
11
|
import React, { useState } from 'react'
|
|
@@ -59,8 +59,8 @@ export const FilterTranscripts = observer(function FilterTranscripts({
|
|
|
59
59
|
Select the alternate transcripts you want to display in the apollo
|
|
60
60
|
track
|
|
61
61
|
</DialogContentText>
|
|
62
|
-
<
|
|
63
|
-
<
|
|
62
|
+
<Grid container spacing={2}>
|
|
63
|
+
<Grid size={8}>
|
|
64
64
|
<FormGroup>
|
|
65
65
|
{allTranscripts.map((item) => (
|
|
66
66
|
// eslint-disable-next-line react/jsx-key
|
|
@@ -71,15 +71,15 @@ export const FilterTranscripts = observer(function FilterTranscripts({
|
|
|
71
71
|
onChange={() => {
|
|
72
72
|
handleChange(item)
|
|
73
73
|
}}
|
|
74
|
-
|
|
74
|
+
slotProps={{ input: { 'aria-label': 'controlled' } }}
|
|
75
75
|
/>
|
|
76
76
|
}
|
|
77
77
|
label={item}
|
|
78
78
|
/>
|
|
79
79
|
))}
|
|
80
80
|
</FormGroup>
|
|
81
|
-
</
|
|
82
|
-
</
|
|
81
|
+
</Grid>
|
|
82
|
+
</Grid>
|
|
83
83
|
</DialogContent>
|
|
84
84
|
</Dialog>
|
|
85
85
|
)
|
|
@@ -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) {
|
|
@@ -238,7 +231,7 @@ export function ManageChecks({ handleClose, session }: ManageChecksProps) {
|
|
|
238
231
|
>
|
|
239
232
|
{assemblies.map((option) => (
|
|
240
233
|
<MenuItem key={option.name} value={option.name}>
|
|
241
|
-
{option.displayName
|
|
234
|
+
{option.displayName}
|
|
242
235
|
</MenuItem>
|
|
243
236
|
))}
|
|
244
237
|
</Select>
|
|
@@ -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({
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
3
2
|
import { type AnnotationFeature } from '@apollo-annotation/mst'
|
|
4
3
|
import { MergeTranscriptsChange } from '@apollo-annotation/shared'
|
|
5
|
-
import { type AbstractSessionModel } from '@jbrowse/core/util'
|
|
6
4
|
import {
|
|
7
5
|
Box,
|
|
8
6
|
Button,
|
|
@@ -82,17 +80,20 @@ export function MergeTranscripts({
|
|
|
82
80
|
sourceAssemblyId,
|
|
83
81
|
sourceFeature,
|
|
84
82
|
}: MergeTranscriptsProps) {
|
|
85
|
-
const { notify } = session as unknown as AbstractSessionModel
|
|
86
83
|
const [errorMessage, setErrorMessage] = useState('')
|
|
87
|
-
const
|
|
88
|
-
|
|
84
|
+
const transcripts = getTranscripts(sourceFeature, session)
|
|
85
|
+
const firstTranscript = Object.keys(transcripts).at(0)
|
|
86
|
+
const [selectedTranscriptId, setSelectedTranscriptId] = useState<
|
|
87
|
+
string | undefined
|
|
88
|
+
>(firstTranscript)
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
function onSubmit(event: React.FormEvent<HTMLFormElement>) {
|
|
91
91
|
event.preventDefault()
|
|
92
92
|
setErrorMessage('')
|
|
93
|
-
if (!
|
|
93
|
+
if (!selectedTranscriptId) {
|
|
94
94
|
return
|
|
95
95
|
}
|
|
96
|
+
const selectedTranscript = transcripts[selectedTranscriptId]
|
|
96
97
|
if (selectedFeature?._id === sourceFeature._id) {
|
|
97
98
|
setSelectedFeature()
|
|
98
99
|
}
|
|
@@ -109,20 +110,16 @@ export function MergeTranscripts({
|
|
|
109
110
|
secondTranscript: getSnapshot(selectedTranscript),
|
|
110
111
|
parentFeatureId: sourceFeature.parent._id,
|
|
111
112
|
})
|
|
112
|
-
|
|
113
|
-
notify('Transcripts successfully merged', 'success')
|
|
113
|
+
void changeManager.submit(change)
|
|
114
114
|
handleClose()
|
|
115
|
-
event.preventDefault()
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
const handleTypeChange = (e: SelectChangeEvent) => {
|
|
119
118
|
setErrorMessage('')
|
|
120
119
|
const { value } = e.target
|
|
121
|
-
|
|
120
|
+
setSelectedTranscriptId(value)
|
|
122
121
|
}
|
|
123
122
|
|
|
124
|
-
const transcripts = getTranscripts(sourceFeature, session)
|
|
125
|
-
|
|
126
123
|
return (
|
|
127
124
|
<Dialog
|
|
128
125
|
open
|
|
@@ -140,7 +137,7 @@ export function MergeTranscripts({
|
|
|
140
137
|
<RadioGroup
|
|
141
138
|
aria-labelledby="demo-radio-buttons-group-label"
|
|
142
139
|
name="radio-buttons-group"
|
|
143
|
-
value={
|
|
140
|
+
value={selectedTranscriptId}
|
|
144
141
|
onChange={handleTypeChange}
|
|
145
142
|
>
|
|
146
143
|
{Object.keys(transcripts).map((key) => (
|
|
@@ -165,7 +162,7 @@ export function MergeTranscripts({
|
|
|
165
162
|
type="submit"
|
|
166
163
|
disabled={
|
|
167
164
|
Object.keys(transcripts).length === 0 ||
|
|
168
|
-
|
|
165
|
+
selectedTranscriptId === undefined
|
|
169
166
|
}
|
|
170
167
|
>
|
|
171
168
|
Submit
|
|
@@ -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
|
}
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
import { isAbortException } from '@jbrowse/core/util/aborting'
|
|
5
5
|
import {
|
|
6
6
|
Autocomplete,
|
|
7
|
-
type
|
|
7
|
+
type AutocompleteRenderValueGetItemProps,
|
|
8
8
|
Chip,
|
|
9
|
-
|
|
9
|
+
Grid,
|
|
10
10
|
TextField,
|
|
11
11
|
Tooltip,
|
|
12
12
|
Typography,
|
|
@@ -49,14 +49,14 @@ interface TermValue {
|
|
|
49
49
|
// const hiliteRegex = /(?<=<em class="hilite">)(.*?)(?=<\/em>)/g
|
|
50
50
|
|
|
51
51
|
function TermTagWithTooltip({
|
|
52
|
-
|
|
52
|
+
getItemProps,
|
|
53
53
|
index,
|
|
54
54
|
ontology,
|
|
55
55
|
termId,
|
|
56
56
|
}: {
|
|
57
57
|
termId: string
|
|
58
58
|
index: number
|
|
59
|
-
|
|
59
|
+
getItemProps: AutocompleteRenderValueGetItemProps<true>
|
|
60
60
|
ontology: OntologyRecord
|
|
61
61
|
}) {
|
|
62
62
|
const manager = getParent<OntologyManager>(ontology, 2)
|
|
@@ -100,7 +100,7 @@ function TermTagWithTooltip({
|
|
|
100
100
|
label={errorMessage || manager.applyPrefixes(termId)}
|
|
101
101
|
color={errorMessage ? 'error' : 'default'}
|
|
102
102
|
size="small"
|
|
103
|
-
{...
|
|
103
|
+
{...getItemProps({ index })}
|
|
104
104
|
/>
|
|
105
105
|
</div>
|
|
106
106
|
</Tooltip>
|
|
@@ -270,13 +270,13 @@ export function OntologyTermMultiSelect({
|
|
|
270
270
|
inputValue={inputValue}
|
|
271
271
|
/>
|
|
272
272
|
)}
|
|
273
|
-
|
|
273
|
+
renderValue={(v, getItemProps) =>
|
|
274
274
|
v.map((option, index) => (
|
|
275
275
|
<TermTagWithTooltip
|
|
276
276
|
termId={option.term.id}
|
|
277
277
|
index={index}
|
|
278
278
|
ontology={ontology}
|
|
279
|
-
|
|
279
|
+
getItemProps={getItemProps}
|
|
280
280
|
key={option.term.id}
|
|
281
281
|
/>
|
|
282
282
|
))
|
|
@@ -336,8 +336,8 @@ function Option(props: {
|
|
|
336
336
|
// .join(', ')
|
|
337
337
|
return (
|
|
338
338
|
<li {...other}>
|
|
339
|
-
<
|
|
340
|
-
<
|
|
339
|
+
<Grid container>
|
|
340
|
+
<Grid>
|
|
341
341
|
<Typography component="span">
|
|
342
342
|
{ontologyManager.applyPrefixes(option.term.id)}
|
|
343
343
|
</Typography>{' '}
|
|
@@ -347,8 +347,8 @@ function Option(props: {
|
|
|
347
347
|
/>{' '}
|
|
348
348
|
{/* ({lblScore}) */}
|
|
349
349
|
<dl>{fields}</dl>
|
|
350
|
-
</
|
|
351
|
-
</
|
|
350
|
+
</Grid>
|
|
351
|
+
</Grid>
|
|
352
352
|
</li>
|
|
353
353
|
)
|
|
354
354
|
}
|
|
@@ -87,6 +87,13 @@ export function OpenLocalFile({ handleClose, session }: OpenLocalFileProps) {
|
|
|
87
87
|
return
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
const fileMetadata: { file?: string } = {}
|
|
91
|
+
if (isElectron) {
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
93
|
+
const { webUtils } = globalThis.require('electron')
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
95
|
+
fileMetadata.file = webUtils.getPathForFile(file) as string
|
|
96
|
+
}
|
|
90
97
|
const assemblyConfig = {
|
|
91
98
|
name: assemblyId,
|
|
92
99
|
aliases: [assemblyName],
|
|
@@ -95,17 +102,14 @@ export function OpenLocalFile({ handleClose, session }: OpenLocalFileProps) {
|
|
|
95
102
|
trackId: `sequenceConfigId-${assemblyName}`,
|
|
96
103
|
type: 'ReferenceSequenceTrack',
|
|
97
104
|
adapter: { type: 'ApolloSequenceAdapter', assemblyId },
|
|
98
|
-
metadata: {
|
|
99
|
-
apollo: true,
|
|
100
|
-
...(isElectron
|
|
101
|
-
? { file: (file as File & { path: string }).path }
|
|
102
|
-
: {}),
|
|
103
|
-
},
|
|
105
|
+
metadata: { apollo: true, ...fileMetadata },
|
|
104
106
|
},
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
// Save assembly into session
|
|
108
|
-
await (
|
|
110
|
+
await (isElectron
|
|
111
|
+
? addAssembly?.(assemblyConfig)
|
|
112
|
+
: (addSessionAssembly || addAssembly)(assemblyConfig))
|
|
109
113
|
const a = await assemblyManager.waitForAssembly(assemblyConfig.name)
|
|
110
114
|
if (a) {
|
|
111
115
|
// @ts-expect-error MST type coercion problem?
|