@apollo-annotation/jbrowse-plugin-apollo 0.3.0 → 0.3.2
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 +2072 -1496
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +2069 -1493
- 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 +2256 -1533
- 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 +13 -11
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +7 -10
- package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +3 -0
- package/src/FeatureDetailsWidget/Attributes.tsx +27 -27
- package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +65 -0
- package/src/FeatureDetailsWidget/TranscriptBasic.tsx +6 -1
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +25 -2
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +0 -1
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +8 -1
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +88 -40
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +8 -1
- package/src/LinearApolloDisplay/stateModel/base.ts +28 -2
- package/src/LinearApolloDisplay/stateModel/layouts.ts +65 -11
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +25 -6
- package/src/LinearApolloDisplay/stateModel/rendering.ts +1 -2
- package/src/OntologyManager/OntologyStore/index.ts +6 -2
- package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +41 -13
- package/src/OntologyManager/index.ts +35 -0
- package/src/SixFrameFeatureDisplay/stateModel.ts +11 -2
- package/src/TabularEditor/HybridGrid/Feature.tsx +1 -2
- package/src/TabularEditor/HybridGrid/HybridGrid.tsx +0 -1
- package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +8 -1
- package/src/components/AddRefSeqAliases.tsx +7 -8
- package/src/components/CopyFeature.tsx +1 -1
- package/src/components/CreateApolloAnnotation.tsx +304 -0
- package/src/components/DownloadGFF3.tsx +5 -1
- package/src/components/FilterFeatures.tsx +120 -0
- package/src/components/ModifyFeatureAttribute.tsx +27 -27
- package/src/components/OntologyTermMultiSelect.tsx +5 -5
- package/src/extensions/annotationFromJBrowseFeature.test.ts +119 -0
- package/src/extensions/annotationFromJBrowseFeature.ts +171 -0
- package/src/extensions/annotationFromPileup.ts +1 -1
- package/src/extensions/index.ts +1 -0
- package/src/index.ts +8 -2
- package/src/session/ClientDataStore.ts +29 -0
- package/src/session/session.ts +2 -5
- package/src/LinearApolloDisplay/stateModel/getGlyph.ts +0 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apollo-annotation/jbrowse-plugin-apollo",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Apollo plugin for JBrowse 2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -48,14 +48,14 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@apollo-annotation/common": "^0.3.
|
|
52
|
-
"@apollo-annotation/mst": "^0.3.
|
|
53
|
-
"@apollo-annotation/shared": "^0.3.
|
|
51
|
+
"@apollo-annotation/common": "^0.3.2",
|
|
52
|
+
"@apollo-annotation/mst": "^0.3.2",
|
|
53
|
+
"@apollo-annotation/shared": "^0.3.2",
|
|
54
54
|
"@emotion/react": "^11.10.6",
|
|
55
55
|
"@emotion/styled": "^11.10.6",
|
|
56
56
|
"@gmod/gff": "1.2.0",
|
|
57
|
-
"@jbrowse/plugin-authentication": "^
|
|
58
|
-
"@jbrowse/plugin-linear-genome-view": "^
|
|
57
|
+
"@jbrowse/plugin-authentication": "^3.0.1",
|
|
58
|
+
"@jbrowse/plugin-linear-genome-view": "^3.0.1",
|
|
59
59
|
"@mui/icons-material": "^5.8.4",
|
|
60
60
|
"@types/jsonpath": "^0.2.0",
|
|
61
61
|
"autosuggest-highlight": "^3.3.4",
|
|
@@ -71,11 +71,11 @@
|
|
|
71
71
|
"tslib": "^2.3.1"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@jbrowse/cli": "^
|
|
75
|
-
"@jbrowse/core": "^
|
|
74
|
+
"@jbrowse/cli": "^3.0.1",
|
|
75
|
+
"@jbrowse/core": "^3.0.1",
|
|
76
76
|
"@jbrowse/development-tools": "^2.1.1",
|
|
77
77
|
"@jest/globals": "^29.0.3",
|
|
78
|
-
"@mui/material": "^
|
|
78
|
+
"@mui/material": "^6.0.0",
|
|
79
79
|
"@mui/x-data-grid": "^7.0.0",
|
|
80
80
|
"@types/autosuggest-highlight": "^3",
|
|
81
81
|
"@types/file-saver": "^2",
|
|
@@ -84,6 +84,8 @@
|
|
|
84
84
|
"@types/react": "^18.3.4",
|
|
85
85
|
"@types/react-dom": "^18",
|
|
86
86
|
"cypress": "12.17.3",
|
|
87
|
+
"cypress-image-diff-html-report": "^2.2.0",
|
|
88
|
+
"cypress-image-diff-js": "^2.3.0",
|
|
87
89
|
"cypress-mongodb": "^6.2.0",
|
|
88
90
|
"fake-indexeddb": "^4.0.2",
|
|
89
91
|
"jest": "^29.6.2",
|
|
@@ -108,8 +110,8 @@
|
|
|
108
110
|
"typescript": "^5.5.3"
|
|
109
111
|
},
|
|
110
112
|
"peerDependencies": {
|
|
111
|
-
"@jbrowse/core": "^
|
|
112
|
-
"@mui/material": "^
|
|
113
|
+
"@jbrowse/core": "^3.0.1",
|
|
114
|
+
"@mui/material": "^6.0.0",
|
|
113
115
|
"mobx": "^6.6.1",
|
|
114
116
|
"mobx-react": "^7.2.1",
|
|
115
117
|
"mobx-state-tree": "^5.4.0",
|
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
6
6
|
import { readConfObject } from '@jbrowse/core/configuration'
|
|
7
|
-
import {
|
|
8
|
-
BaseOptions,
|
|
9
|
-
BaseSequenceAdapter,
|
|
10
|
-
} from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
7
|
+
import { BaseSequenceAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
11
8
|
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
|
|
12
9
|
import SimpleFeature, { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
13
10
|
import { NoAssemblyRegion, Region } from '@jbrowse/core/util/types'
|
|
@@ -48,12 +45,12 @@ const isInWebWorker = typeof sessionStorage === 'undefined'
|
|
|
48
45
|
export class ApolloSequenceAdapter extends BaseSequenceAdapter {
|
|
49
46
|
private regions: NoAssemblyRegion[] | undefined
|
|
50
47
|
|
|
51
|
-
public async getRefNames(
|
|
52
|
-
const regions = await this.getRegions(
|
|
48
|
+
public async getRefNames() {
|
|
49
|
+
const regions = await this.getRegions()
|
|
53
50
|
return regions.map((regions) => regions.refName)
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
public async getRegions(
|
|
53
|
+
public async getRegions(): Promise<NoAssemblyRegion[]> {
|
|
57
54
|
if (this.regions) {
|
|
58
55
|
return this.regions
|
|
59
56
|
}
|
|
@@ -93,7 +90,7 @@ export class ApolloSequenceAdapter extends BaseSequenceAdapter {
|
|
|
93
90
|
removeEventListener('message', messageListener)
|
|
94
91
|
resolve(data.regions)
|
|
95
92
|
}
|
|
96
|
-
addEventListener('message', messageListener
|
|
93
|
+
addEventListener('message', messageListener)
|
|
97
94
|
// @ts-expect-error waiting for types to be published
|
|
98
95
|
globalThis.rpcServer.emit('apollo', {
|
|
99
96
|
apollo: true,
|
|
@@ -112,7 +109,7 @@ export class ApolloSequenceAdapter extends BaseSequenceAdapter {
|
|
|
112
109
|
* @param param -
|
|
113
110
|
* @returns Observable of Feature objects in the region
|
|
114
111
|
*/
|
|
115
|
-
public getFeatures(region: Region
|
|
112
|
+
public getFeatures(region: Region) {
|
|
116
113
|
const { end, refName, start } = region
|
|
117
114
|
const assemblyId = readConfObject(this.config, 'assemblyId')
|
|
118
115
|
const regionWithAssemblyName = { ...region, assemblyName: assemblyId }
|
|
@@ -161,7 +158,7 @@ export class ApolloSequenceAdapter extends BaseSequenceAdapter {
|
|
|
161
158
|
removeEventListener('message', messageListener)
|
|
162
159
|
resolve(data.sequence)
|
|
163
160
|
}
|
|
164
|
-
addEventListener('message', messageListener
|
|
161
|
+
addEventListener('message', messageListener)
|
|
165
162
|
// @ts-expect-error waiting for types to be published
|
|
166
163
|
globalThis.rpcServer.emit('apollo', {
|
|
167
164
|
apollo: true,
|
|
@@ -8,6 +8,7 @@ import { Attributes } from './Attributes'
|
|
|
8
8
|
import { BasicInformation } from './BasicInformation'
|
|
9
9
|
import { ApolloFeatureDetailsWidget as ApolloFeatureDetails } from './model'
|
|
10
10
|
import { Sequence } from './Sequence'
|
|
11
|
+
import { FeatureDetailsNavigation } from './FeatureDetailsNavigation'
|
|
11
12
|
|
|
12
13
|
const useStyles = makeStyles()((theme) => ({
|
|
13
14
|
root: {
|
|
@@ -59,6 +60,8 @@ export const ApolloFeatureDetailsWidget = observer(
|
|
|
59
60
|
assembly={currentAssembly._id}
|
|
60
61
|
refName={refName}
|
|
61
62
|
/>
|
|
63
|
+
<hr />
|
|
64
|
+
<FeatureDetailsNavigation model={model} feature={feature} />
|
|
62
65
|
</div>
|
|
63
66
|
)
|
|
64
67
|
},
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
FormControl,
|
|
12
12
|
FormControlLabel,
|
|
13
13
|
FormLabel,
|
|
14
|
-
|
|
14
|
+
Grid2,
|
|
15
15
|
IconButton,
|
|
16
16
|
Paper,
|
|
17
17
|
Radio,
|
|
@@ -243,7 +243,7 @@ export const Attributes = observer(function Attributes({
|
|
|
243
243
|
return (
|
|
244
244
|
<>
|
|
245
245
|
<Typography variant="h5">Attributes</Typography>
|
|
246
|
-
<
|
|
246
|
+
<Grid2 container direction="column" spacing={1}>
|
|
247
247
|
{Object.entries(attributes).map(([key, value]) => {
|
|
248
248
|
if (key === '') {
|
|
249
249
|
return null
|
|
@@ -251,20 +251,20 @@ export const Attributes = observer(function Attributes({
|
|
|
251
251
|
const EditorComponent =
|
|
252
252
|
reservedKeys.get(key) ?? CustomAttributeValueEditor
|
|
253
253
|
return (
|
|
254
|
-
<
|
|
255
|
-
<
|
|
254
|
+
<Grid2 container spacing={3} alignItems="center" key={key}>
|
|
255
|
+
<Grid2>
|
|
256
256
|
<Paper variant="outlined" className={classes.attributeName}>
|
|
257
257
|
<Typography>{key}</Typography>
|
|
258
258
|
</Paper>
|
|
259
|
-
</
|
|
260
|
-
<
|
|
259
|
+
</Grid2>
|
|
260
|
+
<Grid2 flexGrow={1}>
|
|
261
261
|
<EditorComponent
|
|
262
262
|
session={session}
|
|
263
263
|
value={value}
|
|
264
264
|
onChange={(newValue) => onChangeCommitted(key, newValue)}
|
|
265
265
|
/>
|
|
266
|
-
</
|
|
267
|
-
<
|
|
266
|
+
</Grid2>
|
|
267
|
+
<Grid2>
|
|
268
268
|
<IconButton
|
|
269
269
|
aria-label="delete"
|
|
270
270
|
size="medium"
|
|
@@ -273,11 +273,11 @@ export const Attributes = observer(function Attributes({
|
|
|
273
273
|
>
|
|
274
274
|
<DeleteIcon fontSize="medium" key={key} />
|
|
275
275
|
</IconButton>
|
|
276
|
-
</
|
|
277
|
-
</
|
|
276
|
+
</Grid2>
|
|
277
|
+
</Grid2>
|
|
278
278
|
)
|
|
279
279
|
})}
|
|
280
|
-
<
|
|
280
|
+
<Grid2>
|
|
281
281
|
<Button
|
|
282
282
|
color="primary"
|
|
283
283
|
variant="contained"
|
|
@@ -288,12 +288,12 @@ export const Attributes = observer(function Attributes({
|
|
|
288
288
|
>
|
|
289
289
|
Add new
|
|
290
290
|
</Button>
|
|
291
|
-
</
|
|
291
|
+
</Grid2>
|
|
292
292
|
{showAddNewForm ? (
|
|
293
|
-
<
|
|
293
|
+
<Grid2>
|
|
294
294
|
<Paper elevation={8} className={classes.newAttributePaper}>
|
|
295
|
-
<
|
|
296
|
-
<
|
|
295
|
+
<Grid2 container direction="column">
|
|
296
|
+
<Grid2>
|
|
297
297
|
<FormControl>
|
|
298
298
|
<FormLabel id="attribute-radio-button-group">
|
|
299
299
|
Select attribute type
|
|
@@ -309,11 +309,11 @@ export const Attributes = observer(function Attributes({
|
|
|
309
309
|
control={<Radio />}
|
|
310
310
|
disableTypography
|
|
311
311
|
label={
|
|
312
|
-
<
|
|
313
|
-
<
|
|
312
|
+
<Grid2 container spacing={1} alignItems="center">
|
|
313
|
+
<Grid2>
|
|
314
314
|
<Typography>Custom</Typography>
|
|
315
|
-
</
|
|
316
|
-
<
|
|
315
|
+
</Grid2>
|
|
316
|
+
<Grid2>
|
|
317
317
|
<TextField
|
|
318
318
|
label="Custom attribute key"
|
|
319
319
|
variant="outlined"
|
|
@@ -327,8 +327,8 @@ export const Attributes = observer(function Attributes({
|
|
|
327
327
|
setNewAttributeKey(event.target.value)
|
|
328
328
|
}}
|
|
329
329
|
/>
|
|
330
|
-
</
|
|
331
|
-
</
|
|
330
|
+
</Grid2>
|
|
331
|
+
</Grid2>
|
|
332
332
|
}
|
|
333
333
|
/>
|
|
334
334
|
{[...reservedKeys.keys()].map((key) => (
|
|
@@ -341,8 +341,8 @@ export const Attributes = observer(function Attributes({
|
|
|
341
341
|
))}
|
|
342
342
|
</RadioGroup>
|
|
343
343
|
</FormControl>
|
|
344
|
-
</
|
|
345
|
-
<
|
|
344
|
+
</Grid2>
|
|
345
|
+
<Grid2>
|
|
346
346
|
<DialogActions>
|
|
347
347
|
<Button
|
|
348
348
|
key="addButton"
|
|
@@ -366,12 +366,12 @@ export const Attributes = observer(function Attributes({
|
|
|
366
366
|
Cancel
|
|
367
367
|
</Button>
|
|
368
368
|
</DialogActions>
|
|
369
|
-
</
|
|
370
|
-
</
|
|
369
|
+
</Grid2>
|
|
370
|
+
</Grid2>
|
|
371
371
|
</Paper>
|
|
372
|
-
</
|
|
372
|
+
</Grid2>
|
|
373
373
|
) : null}
|
|
374
|
-
</
|
|
374
|
+
</Grid2>
|
|
375
375
|
{errorMessage ? (
|
|
376
376
|
<Typography color="error">{errorMessage}</Typography>
|
|
377
377
|
) : null}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { Button, Typography } from '@mui/material'
|
|
4
|
+
import { observer } from 'mobx-react'
|
|
5
|
+
|
|
6
|
+
import { AnnotationFeature } from '@apollo-annotation/mst'
|
|
7
|
+
import { ApolloFeatureDetailsWidget as ApolloFeatureDetails } from './model'
|
|
8
|
+
|
|
9
|
+
export const FeatureDetailsNavigation = observer(
|
|
10
|
+
function FeatureDetailsNavigation(props: {
|
|
11
|
+
model: ApolloFeatureDetails
|
|
12
|
+
feature: AnnotationFeature
|
|
13
|
+
}) {
|
|
14
|
+
const { feature, model } = props
|
|
15
|
+
const { children, parent } = feature
|
|
16
|
+
const childFeatures = []
|
|
17
|
+
if (children) {
|
|
18
|
+
for (const [, child] of children) {
|
|
19
|
+
childFeatures.push(child)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!(parent ?? childFeatures.length > 0)) {
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div>
|
|
29
|
+
<Typography variant="h5">Go to related feature</Typography>
|
|
30
|
+
{parent && (
|
|
31
|
+
<div>
|
|
32
|
+
<Typography variant="h6">Parent:</Typography>
|
|
33
|
+
<Button
|
|
34
|
+
variant="contained"
|
|
35
|
+
onClick={() => {
|
|
36
|
+
model.setFeature(parent)
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{parent.type} ({parent.min}..{parent.max})
|
|
40
|
+
</Button>
|
|
41
|
+
</div>
|
|
42
|
+
)}
|
|
43
|
+
{childFeatures.length > 0 && (
|
|
44
|
+
<div>
|
|
45
|
+
<Typography variant="h6">
|
|
46
|
+
{childFeatures.length === 1 ? 'Child' : 'Children'}:
|
|
47
|
+
</Typography>
|
|
48
|
+
{childFeatures.map((child) => (
|
|
49
|
+
<div key={child._id} style={{ marginBottom: 5 }}>
|
|
50
|
+
<Button
|
|
51
|
+
variant="contained"
|
|
52
|
+
onClick={() => {
|
|
53
|
+
model.setFeature(child)
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
{child.type} ({child.min}..{child.max})
|
|
57
|
+
</Button>
|
|
58
|
+
</div>
|
|
59
|
+
))}
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
},
|
|
65
|
+
)
|
|
@@ -83,7 +83,12 @@ export const TranscriptBasicInformation = observer(
|
|
|
83
83
|
return null
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
let strand, transcriptParts
|
|
87
|
+
try {
|
|
88
|
+
;({ strand, transcriptParts } = feature)
|
|
89
|
+
} catch {
|
|
90
|
+
return null
|
|
91
|
+
}
|
|
87
92
|
const [firstLocation] = transcriptParts
|
|
88
93
|
|
|
89
94
|
const locationData = firstLocation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnnotationFeature } from '@apollo-annotation/mst'
|
|
2
2
|
import { splitStringIntoChunks } from '@apollo-annotation/shared'
|
|
3
|
-
import { revcom } from '@jbrowse/core/util'
|
|
3
|
+
import { defaultCodonTable, revcom } from '@jbrowse/core/util'
|
|
4
4
|
import {
|
|
5
5
|
Button,
|
|
6
6
|
MenuItem,
|
|
@@ -18,7 +18,7 @@ import { ApolloSessionModel } from '../session'
|
|
|
18
18
|
const SEQUENCE_WRAP_LENGTH = 60
|
|
19
19
|
|
|
20
20
|
type SegmentType = 'upOrDownstream' | 'UTR' | 'CDS' | 'intron' | 'protein'
|
|
21
|
-
type SegmentListType = 'CDS' | 'cDNA' | 'genomic'
|
|
21
|
+
type SegmentListType = 'CDS' | 'cDNA' | 'genomic' | 'protein'
|
|
22
22
|
|
|
23
23
|
interface SequenceSegment {
|
|
24
24
|
type: SegmentType
|
|
@@ -121,6 +121,28 @@ function getSequenceSegments(
|
|
|
121
121
|
segments.push({ type: 'CDS', sequenceLines, locs })
|
|
122
122
|
return segments
|
|
123
123
|
}
|
|
124
|
+
case 'protein': {
|
|
125
|
+
let wholeSequence = ''
|
|
126
|
+
const [firstLocation] = cdsLocations
|
|
127
|
+
const locs: { min: number; max: number }[] = []
|
|
128
|
+
for (const loc of firstLocation) {
|
|
129
|
+
let sequence = getSequence(loc.min, loc.max)
|
|
130
|
+
if (strand === -1) {
|
|
131
|
+
sequence = revcom(sequence)
|
|
132
|
+
}
|
|
133
|
+
wholeSequence += sequence
|
|
134
|
+
locs.push({ min: loc.min, max: loc.max })
|
|
135
|
+
}
|
|
136
|
+
let protein = ''
|
|
137
|
+
for (let i = 0; i < wholeSequence.length; i += 3) {
|
|
138
|
+
const codonSeq: string = wholeSequence.slice(i, i + 3).toUpperCase()
|
|
139
|
+
protein +=
|
|
140
|
+
defaultCodonTable[codonSeq as keyof typeof defaultCodonTable] || '&'
|
|
141
|
+
}
|
|
142
|
+
const sequenceLines = splitStringIntoChunks(protein, SEQUENCE_WRAP_LENGTH)
|
|
143
|
+
segments.push({ type: 'protein', sequenceLines, locs })
|
|
144
|
+
return segments
|
|
145
|
+
}
|
|
124
146
|
}
|
|
125
147
|
}
|
|
126
148
|
|
|
@@ -238,6 +260,7 @@ export const TranscriptSequence = observer(function TranscriptSequence({
|
|
|
238
260
|
<MenuItem value="CDS">CDS</MenuItem>
|
|
239
261
|
<MenuItem value="cDNA">cDNA</MenuItem>
|
|
240
262
|
<MenuItem value="genomic">Genomic</MenuItem>
|
|
263
|
+
<MenuItem value="protein">Protein</MenuItem>
|
|
241
264
|
</Select>
|
|
242
265
|
<Paper
|
|
243
266
|
style={{
|
|
@@ -389,7 +389,14 @@ function getContextMenuItems(
|
|
|
389
389
|
},
|
|
390
390
|
},
|
|
391
391
|
)
|
|
392
|
-
|
|
392
|
+
const { featureTypeOntology } = session.apolloDataStore.ontologyManager
|
|
393
|
+
if (!featureTypeOntology) {
|
|
394
|
+
throw new Error('featureTypeOntology is undefined')
|
|
395
|
+
}
|
|
396
|
+
if (
|
|
397
|
+
featureTypeOntology.isTypeOf(sourceFeature.type, 'transcript') &&
|
|
398
|
+
isSessionModelWithWidgets(session)
|
|
399
|
+
) {
|
|
393
400
|
menuItems.push({
|
|
394
401
|
label: 'Edit transcript details',
|
|
395
402
|
onClick: () => {
|