@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,14 +1,10 @@
1
1
  /* eslint-disable @typescript-eslint/unbound-method */
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
4
- /* eslint-disable @typescript-eslint/no-unnecessary-condition */
5
3
  /* eslint-disable @typescript-eslint/no-misused-promises */
6
- import type { ApolloAssembly } from '@apollo-annotation/mst'
7
4
  import { annotationFeatureToGFF3 } from '@apollo-annotation/shared'
8
- import { type GFF3Item, formatSync } from '@gmod/gff'
9
- import type { Assembly } from '@jbrowse/core/assemblyManager/assembly'
5
+ import { GFFFormattingTransformer } from '@gmod/gff'
10
6
  import { getConf } from '@jbrowse/core/configuration'
11
- import { type IMSTMap, getSnapshot } from '@jbrowse/mobx-state-tree'
7
+ import type { AbstractSessionModel } from '@jbrowse/core/util'
12
8
  import {
13
9
  Button,
14
10
  Checkbox,
@@ -17,9 +13,8 @@ import {
17
13
  DialogContentText,
18
14
  FormControlLabel,
19
15
  FormGroup,
20
- MenuItem,
21
- Select,
22
- type SelectChangeEvent,
16
+ SvgIcon,
17
+ type SvgIconProps,
23
18
  } from '@mui/material'
24
19
  import { saveAs } from 'file-saver'
25
20
  import React, { useState } from 'react'
@@ -27,8 +22,8 @@ import React, { useState } from 'react'
27
22
  import type {
28
23
  ApolloInternetAccount,
29
24
  CollaborationServerDriver,
30
- InMemoryFileDriver,
31
25
  } from '../BackendDrivers'
26
+ import { openDb } from '../BackendDrivers/LocalDriver/db'
32
27
  import type { ApolloSessionModel } from '../session'
33
28
  import { createFetchErrorMessage } from '../util'
34
29
 
@@ -37,67 +32,65 @@ import { Dialog } from './Dialog'
37
32
  interface DownloadGFF3Props {
38
33
  session: ApolloSessionModel
39
34
  handleClose(): void
35
+ assembly: string
40
36
  }
41
37
 
42
- export function DownloadGFF3({ handleClose, session }: DownloadGFF3Props) {
38
+ // Icon source: https://pictogrammers.com/library/mdi/icon/export/
39
+ export function Export(props: SvgIconProps) {
40
+ return (
41
+ <SvgIcon viewBox="0 0 24 24" {...props}>
42
+ <path d="M23,12L19,8V11H10V13H19V16M1,18V6C1,4.89 1.9,4 3,4H15A2,2 0 0,1 17,6V9H15V6H3V18H15V15H17V18A2,2 0 0,1 15,20H3A2,2 0 0,1 1,18Z" />
43
+ </SvgIcon>
44
+ )
45
+ }
46
+
47
+ export function DownloadGFF3({
48
+ handleClose,
49
+ session,
50
+ assembly: assemblyName,
51
+ }: DownloadGFF3Props) {
43
52
  const [includeFASTA, setincludeFASTA] = useState(false)
44
- const [selectedAssembly, setSelectedAssembly] = useState<Assembly>()
45
53
  const [errorMessage, setErrorMessage] = useState('')
46
54
 
47
- const { collaborationServerDriver, getInternetAccount, inMemoryFileDriver } =
48
- session.apolloDataStore as {
49
- collaborationServerDriver: CollaborationServerDriver
50
- inMemoryFileDriver: InMemoryFileDriver
51
- getInternetAccount(
52
- assemblyName?: string,
53
- internetAccountId?: string,
54
- ): ApolloInternetAccount
55
- }
56
- const assemblies = [
57
- ...collaborationServerDriver.getAssemblies(),
58
- ...inMemoryFileDriver.getAssemblies(),
59
- ]
60
-
61
- function handleChangeAssembly(e: SelectChangeEvent) {
62
- const newAssembly = assemblies.find((asm) => asm.name === e.target.value)
63
- setSelectedAssembly(newAssembly)
55
+ const { getInternetAccount } = session.apolloDataStore as {
56
+ collaborationServerDriver: CollaborationServerDriver
57
+ getInternetAccount(
58
+ assemblyName?: string,
59
+ internetAccountId?: string,
60
+ ): ApolloInternetAccount
64
61
  }
65
62
 
63
+ const { assemblyManager } = session as unknown as AbstractSessionModel
64
+ const assembly = assemblyManager.get(assemblyName)
65
+ if (!assembly) {
66
+ setErrorMessage(`Assembly "${assemblyName}" not found`)
67
+ return
68
+ }
69
+
70
+ const { internetAccountConfigId } = getConf(assembly, [
71
+ 'sequence',
72
+ 'metadata',
73
+ ]) as { internetAccountConfigId?: string }
74
+
66
75
  async function onSubmit(event: React.FormEvent<HTMLFormElement>) {
67
76
  event.preventDefault()
68
77
  setErrorMessage('')
69
- if (!selectedAssembly) {
70
- setErrorMessage('Must select assembly to download')
71
- return
72
- }
73
78
 
74
- const { internetAccountConfigId } = getConf(selectedAssembly, [
75
- 'sequence',
76
- 'metadata',
77
- ]) as { internetAccountConfigId?: string }
78
- if (internetAccountConfigId) {
79
- await exportFromCollaborationServer(internetAccountConfigId)
80
- } else {
81
- exportFromMemory(session)
82
- }
79
+ await (internetAccountConfigId
80
+ ? exportFromCollaborationServer(internetAccountConfigId)
81
+ : downloadAssemblyGFF3(assemblyName))
83
82
  handleClose()
84
83
  }
85
84
 
86
85
  async function exportFromCollaborationServer(
87
86
  internetAccountConfigId: string,
88
87
  ) {
89
- if (!selectedAssembly) {
90
- setErrorMessage('Must select assembly to download')
91
- return
92
- }
93
88
  const internetAccount = getInternetAccount(
94
- selectedAssembly.configuration.name,
89
+ assemblyName,
95
90
  internetAccountConfigId,
96
91
  )
97
92
  const url = new URL('export/getID', internetAccount.baseURL)
98
- const searchParams = new URLSearchParams({
99
- assembly: selectedAssembly.name,
100
- })
93
+ const searchParams = new URLSearchParams({ assembly: assemblyName })
101
94
  url.search = searchParams.toString()
102
95
  const uri = url.toString()
103
96
  const apolloFetch = internetAccount.getFetcher({
@@ -127,83 +120,19 @@ export function DownloadGFF3({ handleClose, session }: DownloadGFF3Props) {
127
120
  window.open(exportUri, '_blank')
128
121
  }
129
122
 
130
- function exportFromMemory(session: ApolloSessionModel) {
131
- if (!selectedAssembly) {
132
- setErrorMessage('Must select assembly to download')
133
- return
134
- }
135
- const { assemblies } = session.apolloDataStore as {
136
- assemblies: IMSTMap<typeof ApolloAssembly>
137
- }
138
- const assembly = assemblies.get(selectedAssembly.name)
139
- const refSeqs = assembly?.refSeqs
140
- if (!refSeqs) {
141
- setErrorMessage(
142
- `No refSeqs found for assembly "${selectedAssembly.name}"`,
143
- )
144
- return
145
- }
146
- const gff3Items: GFF3Item[] = [{ directive: 'gff-version', value: '3' }]
147
- const sequenceFeatures = getConf(selectedAssembly, [
148
- 'sequence',
149
- 'adapter',
150
- 'features',
151
- ]) as { refName: string; start: number; end: number; seq: string }[]
152
- for (const sequenceFeature of sequenceFeatures) {
153
- const { end, refName, start } = sequenceFeature
154
- gff3Items.push({
155
- directive: 'sequence-region',
156
- value: `${refName} ${start + 1} ${end}`,
157
- })
158
- }
159
- for (const [, refSeq] of refSeqs) {
160
- const { features } = refSeq
161
- if (!features) {
162
- continue
163
- }
164
- for (const [, feature] of features) {
165
- gff3Items.push(annotationFeatureToGFF3(getSnapshot(feature)))
166
- }
167
- }
168
- for (const sequenceFeature of sequenceFeatures) {
169
- const { refName, seq } = sequenceFeature
170
- gff3Items.push({ id: refName, description: '', sequence: seq })
171
- }
172
- const gff3 = formatSync(gff3Items)
173
- const gff3Blob = new Blob([gff3], { type: 'text/plain;charset=utf-8' })
174
- saveAs(
175
- gff3Blob,
176
- `${selectedAssembly.displayName ?? selectedAssembly.name}.gff3`,
177
- )
178
- }
179
-
180
123
  return (
181
124
  <Dialog
182
125
  open
183
- title="Export GFF3"
126
+ title="Export annotations"
184
127
  handleClose={handleClose}
185
128
  maxWidth={false}
186
129
  data-testid="download-gff3"
187
130
  >
188
131
  <form onSubmit={onSubmit}>
189
132
  <DialogContent style={{ display: 'flex', flexDirection: 'column' }}>
190
- <DialogContentText>Select assembly</DialogContentText>
191
- <Select
192
- labelId="label"
193
- value={selectedAssembly?.name ?? ''}
194
- onChange={handleChangeAssembly}
195
- disabled={assemblies.length === 0}
196
- >
197
- {assemblies.map((option) => (
198
- <MenuItem key={option.name} value={option.name}>
199
- {option.displayName ?? option.name}
200
- </MenuItem>
201
- ))}
202
- </Select>
203
133
  <DialogContentText>
204
- Select assembly to export to GFF3
134
+ Exporting annotations for {assemblyName}
205
135
  </DialogContentText>
206
-
207
136
  <FormGroup>
208
137
  <FormControlLabel
209
138
  data-testid="include-fasta-checkbox"
@@ -213,6 +142,7 @@ export function DownloadGFF3({ handleClose, session }: DownloadGFF3Props) {
213
142
  onChange={() => {
214
143
  setincludeFASTA(!includeFASTA)
215
144
  }}
145
+ disabled={!internetAccountConfigId}
216
146
  />
217
147
  }
218
148
  label="Include fasta sequence in GFF output"
@@ -220,11 +150,7 @@ export function DownloadGFF3({ handleClose, session }: DownloadGFF3Props) {
220
150
  </FormGroup>
221
151
  </DialogContent>
222
152
  <DialogActions>
223
- <Button
224
- disabled={!selectedAssembly}
225
- variant="contained"
226
- type="submit"
227
- >
153
+ <Button variant="contained" type="submit">
228
154
  Download
229
155
  </Button>
230
156
  <Button variant="outlined" type="submit" onClick={handleClose}>
@@ -240,3 +166,48 @@ export function DownloadGFF3({ handleClose, session }: DownloadGFF3Props) {
240
166
  </Dialog>
241
167
  )
242
168
  }
169
+
170
+ function getAssemblyGFF3Stream(assemblyName: string): ReadableStream<string> {
171
+ const featureStream = new ReadableStream({
172
+ async start(controller) {
173
+ for await (const feature of getFeaturesForAssembly(assemblyName)) {
174
+ const gff3Feature = annotationFeatureToGFF3(feature)
175
+ controller.enqueue(gff3Feature)
176
+ }
177
+ controller.close()
178
+ },
179
+ })
180
+ return featureStream.pipeThrough(
181
+ new TransformStream(new GFFFormattingTransformer()),
182
+ )
183
+ }
184
+
185
+ async function downloadAssemblyGFF3(assemblyName: string) {
186
+ const stream = getAssemblyGFF3Stream(assemblyName)
187
+ const fileName = `${assemblyName}.gff3`
188
+ try {
189
+ const handle = await (
190
+ globalThis as unknown as {
191
+ showSaveFilePicker: (opts: {
192
+ suggestedName: string
193
+ }) => Promise<FileSystemFileHandle>
194
+ }
195
+ ).showSaveFilePicker({ suggestedName: fileName })
196
+ const writable = await handle.createWritable()
197
+ await stream.pipeTo(writable)
198
+ } catch {
199
+ const blob = await new Response(stream).blob()
200
+ saveAs(blob, fileName)
201
+ }
202
+ }
203
+
204
+ async function* getFeaturesForAssembly(assemblyName: string) {
205
+ const db = await openDb(assemblyName, [])
206
+ for (const storeName of db.objectStoreNames) {
207
+ const tx = db.transaction(storeName)
208
+ for await (const cursor of tx.store.iterate()) {
209
+ yield cursor.value
210
+ }
211
+ }
212
+ db.close()
213
+ }
@@ -4,6 +4,7 @@ import type {
4
4
  AnnotationFeatureSnapshot,
5
5
  } from '@apollo-annotation/mst'
6
6
  import { AddFeatureChange } from '@apollo-annotation/shared'
7
+ import { readConfObject } from '@jbrowse/core/configuration'
7
8
  import type { AbstractSessionModel } from '@jbrowse/core/util/types'
8
9
  import { getSnapshot } from '@jbrowse/mobx-state-tree'
9
10
  import {
@@ -17,6 +18,7 @@ import React, { useState } from 'react'
17
18
 
18
19
  import type { ChangeManager } from '../ChangeManager'
19
20
  import type { ApolloSessionModel } from '../session'
21
+ import { removeSkippedAttributes } from '../util'
20
22
 
21
23
  import { Dialog } from './Dialog'
22
24
 
@@ -71,6 +73,14 @@ export function DuplicateTranscript({
71
73
  duplicateTranscript.children = newChildren
72
74
  }
73
75
 
76
+ // skip attributes that are configured (SKIPPED_ATTRIBUTES_ON_COPY env var in backend)
77
+ const configuredSkippedAttributes = readConfObject(
78
+ session.getPluginConfiguration(),
79
+ 'skippedAttributesOnCopy',
80
+ ) as string[] | undefined
81
+ const skippedAttributesOnCopy = new Set(configuredSkippedAttributes ?? [])
82
+ removeSkippedAttributes(duplicateTranscript, skippedAttributesOnCopy)
83
+
74
84
  const change = new AddFeatureChange({
75
85
  parentFeatureId: parentGene._id,
76
86
  changedIds: [parentGene._id],
@@ -1,44 +1,36 @@
1
1
  /* eslint-disable @typescript-eslint/unbound-method */
2
2
  /* eslint-disable @typescript-eslint/use-unknown-in-catch-callback-variable */
3
3
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
4
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
5
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
6
4
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
7
5
  /* eslint-disable @typescript-eslint/no-unsafe-return */
8
6
  import { changeRegistry } from '@apollo-annotation/common'
7
+ import type { AbstractSessionModel } from '@jbrowse/core/util'
9
8
  import { makeStyles } from '@jbrowse/core/util/tss-react'
10
- import { getRoot } from '@jbrowse/mobx-state-tree'
11
9
  import {
12
10
  Button,
13
11
  DialogActions,
14
12
  DialogContent,
15
13
  DialogContentText,
16
- MenuItem,
17
- Select,
18
- type SelectChangeEvent,
19
14
  } from '@mui/material'
20
15
  import {
21
16
  DataGrid,
22
17
  type GridColDef,
18
+ type GridFilterModel,
19
+ type GridPaginationModel,
23
20
  type GridRowsProp,
24
- GridToolbar,
21
+ type GridSortModel,
25
22
  } from '@mui/x-data-grid'
26
23
  import React, { useEffect, useState } from 'react'
27
24
 
28
- import type { ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
29
- import type {
30
- ApolloInternetAccount,
31
- CollaborationServerDriver,
32
- } from '../BackendDrivers'
25
+ import type { GetChangesOpts } from '../BackendDrivers/BackendDriver'
33
26
  import type { ApolloSessionModel } from '../session'
34
- import type { ApolloRootModel } from '../types'
35
- import { createFetchErrorMessage } from '../util'
36
27
 
37
28
  import { Dialog } from './Dialog'
38
29
 
39
30
  interface ViewChangeLogProps {
40
31
  session: ApolloSessionModel
41
32
  handleClose(): void
33
+ assembly: string
42
34
  }
43
35
 
44
36
  const useStyles = makeStyles()((theme) => ({
@@ -51,28 +43,67 @@ const useStyles = makeStyles()((theme) => ({
51
43
  },
52
44
  }))
53
45
 
54
- export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
55
- const { internetAccounts } = getRoot<ApolloRootModel>(session)
56
- const apolloInternetAccount = internetAccounts.find(
57
- (ia) => ia.type === 'ApolloInternetAccount',
58
- ) as ApolloInternetAccountModel | undefined
59
- if (!apolloInternetAccount) {
60
- throw new Error('No Apollo internet account found')
46
+ function buildFiltersFromModel(
47
+ filterModel: GridFilterModel,
48
+ ): GetChangesOpts['filters'] {
49
+ const filters: NonNullable<GetChangesOpts['filters']> = {}
50
+ for (const item of filterModel.items) {
51
+ if (item.value === undefined || item.value === '' || item.value === null) {
52
+ continue
53
+ }
54
+ switch (item.field) {
55
+ case 'user': {
56
+ filters.user = String(item.value)
57
+ break
58
+ }
59
+ case 'typeName': {
60
+ filters.typeName = String(item.value)
61
+ break
62
+ }
63
+ case 'createdAt': {
64
+ const date = new Date(
65
+ item.value as string | number | Date,
66
+ ).toISOString()
67
+ if (item.operator === 'after' || item.operator === 'onOrAfter') {
68
+ filters.startTime = date
69
+ } else if (
70
+ item.operator === 'before' ||
71
+ item.operator === 'onOrBefore'
72
+ ) {
73
+ filters.endTime = date
74
+ }
75
+ break
76
+ }
77
+ }
61
78
  }
62
- const { baseURL } = apolloInternetAccount
79
+ return filters
80
+ }
81
+
82
+ export function ViewChangeLog({
83
+ handleClose,
84
+ session,
85
+ assembly: assemblyId,
86
+ }: ViewChangeLogProps) {
63
87
  const { classes } = useStyles()
64
88
  const [errorMessage, setErrorMessage] = useState<string>()
65
89
  const [displayGridData, setDisplayGridData] = useState<GridRowsProp[]>([])
90
+ const [rowCount, setRowCount] = useState(0)
91
+ const [loading, setLoading] = useState(false)
92
+ const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
93
+ page: 0,
94
+ pageSize: 15,
95
+ })
96
+ const [sortModel, setSortModel] = useState<GridSortModel>([
97
+ { field: 'sequence', sort: 'desc' },
98
+ ])
99
+ const [filterModel, setFilterModel] = useState<GridFilterModel>({
100
+ items: [],
101
+ })
66
102
 
67
- const { collaborationServerDriver } = session.apolloDataStore as {
68
- collaborationServerDriver: CollaborationServerDriver
69
- getInternetAccount(
70
- assemblyName?: string,
71
- internetAccountId?: string,
72
- ): ApolloInternetAccount
73
- }
74
- const assemblies = collaborationServerDriver.getAssemblies()
75
- const [selectedAssembly, setSelectedAssembly] = useState(assemblies.at(0))
103
+ const { apolloDataStore } = session
104
+ const { assemblyManager } = session as unknown as AbstractSessionModel
105
+ const assembly = assemblyManager.get(assemblyId)
106
+ const assemblyName = assembly?.displayName ?? assemblyId
76
107
 
77
108
  const gridColumns: GridColDef[] = [
78
109
  { field: 'sequence' },
@@ -85,9 +116,11 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
85
116
  valueOptions: [...changeRegistry.changes.keys()],
86
117
  },
87
118
  {
88
- field: 'changes',
119
+ field: 'changeData',
89
120
  headerName: 'Change JSON',
90
121
  width: 600,
122
+ sortable: false,
123
+ filterable: false,
91
124
  renderCell: ({ value }) => (
92
125
  <textarea
93
126
  className={classes.changeTextarea}
@@ -108,46 +141,53 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
108
141
 
109
142
  useEffect(() => {
110
143
  async function getGridData() {
111
- if (!selectedAssembly) {
144
+ const backendDriver = apolloDataStore.getBackendDriver(assemblyId)
145
+ if (!backendDriver) {
146
+ setErrorMessage(`No driver found for assembly "${assemblyId}"`)
112
147
  return
113
148
  }
114
-
115
- // Get changes
116
- const url = new URL('changes', baseURL)
117
- const searchParams = new URLSearchParams({
118
- assembly: selectedAssembly.name,
119
- })
120
- url.search = searchParams.toString()
121
- const uri = url.toString()
122
- const apolloFetch = apolloInternetAccount?.getFetcher({
123
- locationType: 'UriLocation',
124
- uri,
149
+ setLoading(true)
150
+ const [sortEntry] = sortModel
151
+ const sortField = sortEntry?.field
152
+ const sortOrderValue = sortEntry?.sort
153
+ const sortOrder: 'asc' | 'desc' | undefined =
154
+ sortOrderValue === 'asc' || sortOrderValue === 'desc'
155
+ ? sortOrderValue
156
+ : undefined
157
+ const { changes, totalCount } = await backendDriver.getChanges(
158
+ assemblyId,
159
+ {
160
+ page: paginationModel.page,
161
+ pageSize: paginationModel.pageSize,
162
+ sortField,
163
+ sortOrder,
164
+ filters: buildFiltersFromModel(filterModel),
165
+ },
166
+ )
167
+ const gridData = changes.map((change) => {
168
+ const {
169
+ sequence,
170
+ typeName,
171
+ changes: nestedChanges,
172
+ user,
173
+ createdAt,
174
+ ...rest
175
+ } = change
176
+ const changeData = nestedChanges ?? { typeName, ...rest }
177
+ return { sequence, typeName, changeData, user, createdAt }
125
178
  })
126
- if (apolloFetch) {
127
- const response = await apolloFetch(uri, {
128
- headers: new Headers({ 'Content-Type': 'application/json' }),
129
- })
130
- if (!response.ok) {
131
- const newErrorMessage = await createFetchErrorMessage(
132
- response,
133
- 'Error when retrieving changes',
134
- )
135
- setErrorMessage(newErrorMessage)
136
- return
137
- }
138
- const data = await response.json()
139
- setDisplayGridData(data)
140
- }
179
+ // @ts-expect-error not sure how to type this
180
+ setDisplayGridData(gridData)
181
+ setRowCount(totalCount)
141
182
  }
142
- getGridData().catch((error) => {
143
- setErrorMessage(String(error))
144
- })
145
- }, [apolloInternetAccount, baseURL, selectedAssembly])
146
-
147
- function handleChangeAssembly(e: SelectChangeEvent) {
148
- const newAssembly = assemblies.find((asm) => asm.name === e.target.value)
149
- setSelectedAssembly(newAssembly)
150
- }
183
+ getGridData()
184
+ .catch((error) => {
185
+ setErrorMessage(String(error))
186
+ })
187
+ .finally(() => {
188
+ setLoading(false)
189
+ })
190
+ }, [apolloDataStore, assemblyId, paginationModel, sortModel, filterModel])
151
191
 
152
192
  return (
153
193
  <Dialog
@@ -157,27 +197,27 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
157
197
  handleClose={handleClose}
158
198
  data-testid="view-changelog"
159
199
  >
160
- <Select
161
- style={{ width: 200, marginLeft: 40 }}
162
- value={selectedAssembly?.name ?? ''}
163
- onChange={handleChangeAssembly}
164
- >
165
- {assemblies.map((option) => (
166
- <MenuItem key={option.name} value={option.name}>
167
- {option.displayName || option.name}
168
- </MenuItem>
169
- ))}
170
- </Select>
171
-
172
200
  <DialogContent>
201
+ <DialogContentText>Changes for {assemblyName}</DialogContentText>
173
202
  <DataGrid
174
203
  pagination
204
+ paginationMode="server"
205
+ sortingMode="server"
206
+ filterMode="server"
207
+ rowCount={rowCount}
208
+ paginationModel={paginationModel}
209
+ onPaginationModelChange={setPaginationModel}
210
+ sortModel={sortModel}
211
+ onSortModelChange={setSortModel}
212
+ filterModel={filterModel}
213
+ onFilterModelChange={setFilterModel}
214
+ loading={loading}
175
215
  rows={displayGridData}
176
216
  columns={gridColumns}
177
- getRowId={(row) => row._id}
178
- slots={{ toolbar: GridToolbar }}
217
+ getRowId={(row) => row.sequence}
218
+ showToolbar
219
+ pageSizeOptions={[5, 15, 25, 50, 100]}
179
220
  initialState={{
180
- sorting: { sortModel: [{ field: 'sequence', sort: 'desc' }] },
181
221
  columns: { columnVisibilityModel: { sequence: false } },
182
222
  }}
183
223
  />