@apollo-annotation/jbrowse-plugin-apollo 0.3.12 → 1.0.0

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