@apollo-annotation/jbrowse-plugin-apollo 0.3.7 → 0.3.8
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 +2371 -1642
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +2384 -1641
- 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 +4387 -2952
- 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 +15 -15
- package/src/ApolloInternetAccount/model.ts +48 -13
- package/src/BackendDrivers/CollaborationServerDriver.ts +23 -2
- package/src/ChangeManager.ts +33 -13
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +64 -5
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +70 -73
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +33 -31
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +60 -72
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +50 -194
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +441 -180
- package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +53 -34
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -9
- 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/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 +481 -0
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +95 -38
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +221 -201
- 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 +1 -1
- package/src/components/AddAssemblyAliases.tsx +1 -1
- package/src/components/AddChildFeature.tsx +5 -2
- package/src/components/AddFeature.tsx +9 -3
- package/src/components/AddRefSeqAliases.tsx +9 -9
- package/src/components/CopyFeature.tsx +3 -1
- package/src/components/CreateApolloAnnotation.tsx +1 -0
- package/src/components/DeleteAssembly.tsx +1 -1
- 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 +1 -1
- package/src/components/MergeTranscripts.tsx +12 -15
- package/src/components/OntologyTermMultiSelect.tsx +11 -11
- package/src/components/OpenLocalFile.tsx +11 -7
- package/src/components/ViewCheckResults.tsx +1 -1
- package/src/components/index.ts +1 -0
- package/src/config.ts +6 -0
- package/src/index.ts +42 -105
- package/src/makeDisplayComponent.tsx +0 -1
- 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/session.ts +162 -116
- package/src/util/annotationFeatureUtils.ts +15 -21
- package/src/util/displayUtils.ts +149 -0
- package/src/util/glyphUtils.ts +152 -0
- package/src/util/mouseEventsUtils.ts +32 -0
|
@@ -10,6 +10,7 @@ import { makeStyles } from 'tss-react/mui'
|
|
|
10
10
|
import { isOntologyClass } from '../../OntologyManager'
|
|
11
11
|
import type OntologyStore from '../../OntologyManager/OntologyStore'
|
|
12
12
|
import { OntologyTermAutocomplete } from '../../components/OntologyTermAutocomplete'
|
|
13
|
+
import { navToFeatureCenter } from '../../util'
|
|
13
14
|
import { type DisplayStateModel } from '../types'
|
|
14
15
|
|
|
15
16
|
import {
|
|
@@ -84,12 +85,13 @@ function makeContextMenuItems(
|
|
|
84
85
|
)
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
function navigateHere(
|
|
89
|
+
displayState: DisplayStateModel,
|
|
90
|
+
feature: AnnotationFeature,
|
|
91
|
+
) {
|
|
92
|
+
displayState.lgv.navTo(
|
|
93
|
+
navToFeatureCenter(feature, 0.1, displayState.lgv.totalBp),
|
|
94
|
+
)
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
export const Feature = observer(function Feature({
|
|
@@ -111,8 +113,8 @@ export const Feature = observer(function Feature({
|
|
|
111
113
|
}) {
|
|
112
114
|
const { classes } = useStyles()
|
|
113
115
|
const {
|
|
114
|
-
apolloHover,
|
|
115
116
|
changeManager,
|
|
117
|
+
hoveredFeature,
|
|
116
118
|
selectedFeature,
|
|
117
119
|
session,
|
|
118
120
|
tabularEditor: tabularEditorState,
|
|
@@ -134,12 +136,7 @@ export const Feature = observer(function Feature({
|
|
|
134
136
|
<>
|
|
135
137
|
<tr
|
|
136
138
|
onMouseEnter={(_e) => {
|
|
137
|
-
displayState.
|
|
138
|
-
feature,
|
|
139
|
-
topLevelFeature: getTopLevelFeature(feature),
|
|
140
|
-
// @ts-expect-error TODO fix in future when moving hover logic to session.
|
|
141
|
-
glyph: displayState.getGlyph(getTopLevelFeature(feature)),
|
|
142
|
-
})
|
|
139
|
+
displayState.setHoveredFeature({ feature, bp: min })
|
|
143
140
|
}}
|
|
144
141
|
className={
|
|
145
142
|
classes.feature +
|
|
@@ -153,6 +150,10 @@ export const Feature = observer(function Feature({
|
|
|
153
150
|
e.stopPropagation()
|
|
154
151
|
displayState.setSelectedFeature(feature)
|
|
155
152
|
}}
|
|
153
|
+
onDoubleClick={() => {
|
|
154
|
+
displayState.setSelectedFeature(feature)
|
|
155
|
+
navigateHere(displayState, feature)
|
|
156
|
+
}}
|
|
156
157
|
onContextMenu={(e) => {
|
|
157
158
|
e.preventDefault()
|
|
158
159
|
setContextMenu({
|
|
@@ -258,7 +259,8 @@ export const Feature = observer(function Feature({
|
|
|
258
259
|
return text.includes(filterText)
|
|
259
260
|
})
|
|
260
261
|
.map(([featureId, childFeature]) => {
|
|
261
|
-
const childHovered =
|
|
262
|
+
const childHovered =
|
|
263
|
+
hoveredFeature?.feature._id === childFeature._id
|
|
262
264
|
const childSelected = selectedFeature?._id === childFeature._id
|
|
263
265
|
return (
|
|
264
266
|
<Feature
|
|
@@ -37,7 +37,7 @@ const HybridGrid = observer(function HybridGrid({
|
|
|
37
37
|
}: {
|
|
38
38
|
model: DisplayStateModel
|
|
39
39
|
}) {
|
|
40
|
-
const {
|
|
40
|
+
const { hoveredFeature, seenFeatures, selectedFeature, tabularEditor } = model
|
|
41
41
|
const theme = useTheme()
|
|
42
42
|
const { classes } = useStyles()
|
|
43
43
|
const scrollContainerRef = useRef<HTMLDivElement>(null)
|
|
@@ -96,7 +96,7 @@ const HybridGrid = observer(function HybridGrid({
|
|
|
96
96
|
})
|
|
97
97
|
.map(([featureId, feature]) => {
|
|
98
98
|
const isSelected = selectedFeature?._id === featureId
|
|
99
|
-
const isHovered =
|
|
99
|
+
const isHovered = hoveredFeature?.feature._id === featureId
|
|
100
100
|
return (
|
|
101
101
|
<Feature
|
|
102
102
|
key={featureId}
|
|
@@ -121,9 +121,11 @@ const HybridGrid = observer(function HybridGrid({
|
|
|
121
121
|
onClose={() => {
|
|
122
122
|
setContextMenu(null)
|
|
123
123
|
}}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
slotProps={{
|
|
125
|
+
transition: {
|
|
126
|
+
onExit: () => {
|
|
127
|
+
setContextMenu(null)
|
|
128
|
+
},
|
|
127
129
|
},
|
|
128
130
|
}}
|
|
129
131
|
style={{ zIndex: theme.zIndex.tooltip }}
|
|
@@ -57,7 +57,7 @@ export function AddAssemblyAliases({
|
|
|
57
57
|
const rows: AssemblyAlias[] = assemblies.map((assembly) => {
|
|
58
58
|
return {
|
|
59
59
|
id: assembly.name,
|
|
60
|
-
name: assembly.displayName
|
|
60
|
+
name: assembly.displayName,
|
|
61
61
|
aliases: assembly.aliases.join(', '),
|
|
62
62
|
} as AssemblyAlias
|
|
63
63
|
})
|
|
@@ -64,12 +64,13 @@ export function AddChildFeature({
|
|
|
64
64
|
function onSubmit(event: React.FormEvent<HTMLFormElement>) {
|
|
65
65
|
event.preventDefault()
|
|
66
66
|
setErrorMessage('')
|
|
67
|
+
const _id = new ObjectID().toHexString()
|
|
67
68
|
const change = new AddFeatureChange({
|
|
68
69
|
changedIds: [sourceFeature._id],
|
|
69
70
|
typeName: 'AddFeatureChange',
|
|
70
71
|
assembly: sourceAssemblyId,
|
|
71
72
|
addedFeature: {
|
|
72
|
-
_id
|
|
73
|
+
_id,
|
|
73
74
|
refSeq: sourceFeature.refSeq,
|
|
74
75
|
min: Number(start) - 1,
|
|
75
76
|
max: Number(end),
|
|
@@ -77,7 +78,9 @@ export function AddChildFeature({
|
|
|
77
78
|
},
|
|
78
79
|
parentFeatureId: sourceFeature._id,
|
|
79
80
|
})
|
|
80
|
-
void changeManager.submit(change)
|
|
81
|
+
void changeManager.submit(change).then(() => {
|
|
82
|
+
session.apolloSetSelectedFeature(_id)
|
|
83
|
+
})
|
|
81
84
|
handleClose()
|
|
82
85
|
event.preventDefault()
|
|
83
86
|
}
|
|
@@ -147,7 +147,9 @@ export function AddFeature({
|
|
|
147
147
|
children,
|
|
148
148
|
},
|
|
149
149
|
})
|
|
150
|
-
void changeManager.submit(change)
|
|
150
|
+
void changeManager.submit(change).then(() => {
|
|
151
|
+
session.apolloSetSelectedFeature(id)
|
|
152
|
+
})
|
|
151
153
|
handleClose()
|
|
152
154
|
return
|
|
153
155
|
}
|
|
@@ -164,7 +166,9 @@ export function AddFeature({
|
|
|
164
166
|
assembly: region.assemblyName,
|
|
165
167
|
addedFeature: mRNA,
|
|
166
168
|
})
|
|
167
|
-
void changeManager.submit(change)
|
|
169
|
+
void changeManager.submit(change).then(() => {
|
|
170
|
+
session.apolloSetSelectedFeature(mRNA._id)
|
|
171
|
+
})
|
|
168
172
|
handleClose()
|
|
169
173
|
return
|
|
170
174
|
}
|
|
@@ -187,7 +191,9 @@ export function AddFeature({
|
|
|
187
191
|
strand,
|
|
188
192
|
},
|
|
189
193
|
})
|
|
190
|
-
void changeManager.submit(change)
|
|
194
|
+
void changeManager.submit(change).then(() => {
|
|
195
|
+
session.apolloSetSelectedFeature(id)
|
|
196
|
+
})
|
|
191
197
|
handleClose()
|
|
192
198
|
return
|
|
193
199
|
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
DialogContent,
|
|
11
11
|
DialogContentText,
|
|
12
12
|
FormControl,
|
|
13
|
-
|
|
13
|
+
Grid,
|
|
14
14
|
InputLabel,
|
|
15
15
|
MenuItem,
|
|
16
16
|
Select,
|
|
@@ -212,8 +212,8 @@ export function AddRefSeqAliases({
|
|
|
212
212
|
fullWidth
|
|
213
213
|
>
|
|
214
214
|
<DialogContent style={{ display: 'flex', flexDirection: 'column' }}>
|
|
215
|
-
<
|
|
216
|
-
<
|
|
215
|
+
<Grid container spacing={2}>
|
|
216
|
+
<Grid>
|
|
217
217
|
<FormControl disabled={enableSubmit && !errorMessage} fullWidth>
|
|
218
218
|
<InputLabel id="demo-simple-select-label">Assembly</InputLabel>
|
|
219
219
|
<Select
|
|
@@ -225,13 +225,13 @@ export function AddRefSeqAliases({
|
|
|
225
225
|
>
|
|
226
226
|
{assemblies.map((option) => (
|
|
227
227
|
<MenuItem key={option.name} value={option.name}>
|
|
228
|
-
{option.displayName
|
|
228
|
+
{option.displayName}
|
|
229
229
|
</MenuItem>
|
|
230
230
|
))}
|
|
231
231
|
</Select>
|
|
232
232
|
</FormControl>
|
|
233
|
-
</
|
|
234
|
-
<
|
|
233
|
+
</Grid>
|
|
234
|
+
<Grid>
|
|
235
235
|
<InputLabel>Load RefName alias</InputLabel>
|
|
236
236
|
<input
|
|
237
237
|
type="file"
|
|
@@ -239,8 +239,8 @@ export function AddRefSeqAliases({
|
|
|
239
239
|
ref={fileRef}
|
|
240
240
|
disabled={(enableSubmit && !errorMessage) || !selectedAssembly}
|
|
241
241
|
/>
|
|
242
|
-
</
|
|
243
|
-
</
|
|
242
|
+
</Grid>
|
|
243
|
+
</Grid>
|
|
244
244
|
{selectedAssembly && refNameAliasMap.size > 0 ? (
|
|
245
245
|
<div style={{ height: 200, width: '100%', marginTop: 20 }}>
|
|
246
246
|
<InputLabel>
|
|
@@ -256,7 +256,7 @@ export function AddRefSeqAliases({
|
|
|
256
256
|
}}
|
|
257
257
|
pageSizeOptions={[5, 10]}
|
|
258
258
|
onRowSelectionModelChange={(ids) => {
|
|
259
|
-
rowSelectionChange(ids as number[])
|
|
259
|
+
rowSelectionChange(ids as unknown as number[])
|
|
260
260
|
}}
|
|
261
261
|
processRowUpdate={processRowUpdate}
|
|
262
262
|
checkboxSelection
|
|
@@ -203,7 +203,9 @@ export function CopyFeature({
|
|
|
203
203
|
copyFeature: true,
|
|
204
204
|
allIds: featureIds,
|
|
205
205
|
})
|
|
206
|
-
void changeManager.submit(change)
|
|
206
|
+
void changeManager.submit(change).then(() => {
|
|
207
|
+
session.apolloSetSelectedFeature(newFeatureLine._id)
|
|
208
|
+
})
|
|
207
209
|
handleClose()
|
|
208
210
|
event.preventDefault()
|
|
209
211
|
}
|
|
@@ -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
|
)
|
|
@@ -238,7 +238,7 @@ export function ManageChecks({ handleClose, session }: ManageChecksProps) {
|
|
|
238
238
|
>
|
|
239
239
|
{assemblies.map((option) => (
|
|
240
240
|
<MenuItem key={option.name} value={option.name}>
|
|
241
|
-
{option.displayName
|
|
241
|
+
{option.displayName}
|
|
242
242
|
</MenuItem>
|
|
243
243
|
))}
|
|
244
244
|
</Select>
|
|
@@ -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
|
|
@@ -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?
|
package/src/components/index.ts
CHANGED
package/src/config.ts
CHANGED
|
@@ -15,6 +15,12 @@ const ApolloPluginConfigurationSchema = ConfigurationSchema('ApolloPlugin', {
|
|
|
15
15
|
type: 'boolean',
|
|
16
16
|
defaultValue: false,
|
|
17
17
|
},
|
|
18
|
+
backgroundColorForFeature: {
|
|
19
|
+
description: 'Color ',
|
|
20
|
+
type: 'string',
|
|
21
|
+
defaultValue: 'jexl:colorFeature(featureType)',
|
|
22
|
+
contextVariable: ['featureType'],
|
|
23
|
+
},
|
|
18
24
|
})
|
|
19
25
|
|
|
20
26
|
export default ApolloPluginConfigurationSchema
|