@apollo-annotation/jbrowse-plugin-apollo 0.1.18 → 0.1.20

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 (85) hide show
  1. package/dist/index.esm.js +3189 -3575
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +3185 -3570
  4. package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
  5. package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
  6. package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
  7. package/dist/jbrowse-plugin-apollo.umd.development.js +14884 -15905
  8. package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
  9. package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
  10. package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
  11. package/package.json +33 -33
  12. package/src/ApolloInternetAccount/addMenuItems.ts +18 -0
  13. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
  14. package/src/ApolloInternetAccount/configSchema.ts +5 -2
  15. package/src/ApolloInternetAccount/model.ts +14 -5
  16. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +94 -0
  17. package/src/ApolloRefNameAliasAdapter/configSchema.ts +12 -0
  18. package/src/ApolloRefNameAliasAdapter/index.ts +21 -0
  19. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +1 -0
  20. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +10 -10
  21. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +35 -32
  22. package/src/BackendDrivers/BackendDriver.ts +8 -0
  23. package/src/BackendDrivers/CollaborationServerDriver.ts +49 -1
  24. package/src/BackendDrivers/DesktopFileDriver.ts +14 -1
  25. package/src/BackendDrivers/InMemoryFileDriver.ts +17 -1
  26. package/src/ChangeManager.ts +1 -1
  27. package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +5 -25
  28. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +82 -0
  29. package/src/FeatureDetailsWidget/Attributes.tsx +11 -3
  30. package/src/FeatureDetailsWidget/BasicInformation.tsx +38 -30
  31. package/src/FeatureDetailsWidget/Sequence.tsx +7 -7
  32. package/src/FeatureDetailsWidget/TranscriptBasic.tsx +446 -0
  33. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +365 -0
  34. package/src/FeatureDetailsWidget/index.ts +2 -0
  35. package/src/FeatureDetailsWidget/model.ts +77 -9
  36. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +0 -2
  37. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +453 -380
  38. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +520 -0
  39. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +138 -134
  40. package/src/LinearApolloDisplay/glyphs/Glyph.ts +38 -370
  41. package/src/LinearApolloDisplay/glyphs/index.ts +1 -2
  42. package/src/LinearApolloDisplay/stateModel/base.ts +3 -6
  43. package/src/LinearApolloDisplay/stateModel/getGlyph.ts +30 -30
  44. package/src/LinearApolloDisplay/stateModel/index.ts +5 -1
  45. package/src/LinearApolloDisplay/stateModel/layouts.ts +32 -24
  46. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +206 -217
  47. package/src/LinearApolloDisplay/stateModel/rendering.ts +43 -67
  48. package/src/OntologyManager/OntologyStore/fulltext.ts +1 -1
  49. package/src/OntologyManager/OntologyStore/index.ts +2 -1
  50. package/src/OntologyManager/index.ts +6 -2
  51. package/src/OntologyManager/util.ts +2 -2
  52. package/src/SixFrameFeatureDisplay/stateModel.ts +15 -10
  53. package/src/TabularEditor/HybridGrid/ChangeHandling.ts +21 -46
  54. package/src/TabularEditor/HybridGrid/Feature.tsx +31 -82
  55. package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +3 -2
  56. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +2 -3
  57. package/src/TabularEditor/HybridGrid/NumberCell.tsx +1 -0
  58. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +46 -5
  59. package/src/TabularEditor/model.ts +5 -3
  60. package/src/components/AddAssembly.tsx +15 -9
  61. package/src/components/AddChildFeature.tsx +7 -73
  62. package/src/components/AddFeature.tsx +2 -57
  63. package/src/components/AddRefSeqAliases.tsx +285 -0
  64. package/src/components/CopyFeature.tsx +16 -33
  65. package/src/components/DeleteFeature.tsx +4 -6
  66. package/src/components/ImportFeatures.tsx +6 -3
  67. package/src/components/LogOut.tsx +105 -0
  68. package/src/components/ManageChecks.tsx +1 -0
  69. package/src/components/ManageUsers.tsx +21 -1
  70. package/src/components/ModifyFeatureAttribute.tsx +2 -2
  71. package/src/components/OntologyTermAutocomplete.tsx +0 -2
  72. package/src/components/OntologyTermMultiSelect.tsx +1 -0
  73. package/src/components/OpenLocalFile.tsx +6 -5
  74. package/src/components/ViewChangeLog.tsx +1 -0
  75. package/src/components/ViewCheckResults.tsx +1 -0
  76. package/src/components/index.ts +4 -0
  77. package/src/extensions/annotationFromPileup.ts +10 -16
  78. package/src/index.ts +57 -3
  79. package/src/session/ClientDataStore.ts +49 -46
  80. package/src/session/session.ts +186 -114
  81. package/src/util/loadAssemblyIntoClient.ts +4 -210
  82. package/src/FeatureDetailsWidget/RelatedFeature.tsx +0 -97
  83. package/src/LinearApolloDisplay/glyphs/CanonicalGeneGlyph.ts +0 -1204
  84. package/src/LinearApolloDisplay/glyphs/ImplicitExonGeneGlyph.ts +0 -716
  85. package/src/LinearApolloDisplay/stateModel/glyphs.ts +0 -47
@@ -1,14 +1,15 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3
- /* eslint-disable @typescript-eslint/no-unsafe-call */
4
3
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
5
4
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
6
5
  import { ClientDataStore as ClientDataStoreType } from '@apollo-annotation/common'
7
6
  import {
8
- AnnotationFeature,
7
+ AnnotationFeatureModel,
9
8
  AnnotationFeatureSnapshot,
10
9
  ApolloAssembly,
10
+ ApolloAssemblySnapshot,
11
11
  ApolloRefSeq,
12
+ BackendDriverType,
12
13
  CheckResult,
13
14
  CheckResultSnapshot,
14
15
  } from '@apollo-annotation/mst'
@@ -18,7 +19,7 @@ import { Region, getSession, isElectron } from '@jbrowse/core/util'
18
19
  import { LocalPathLocation, UriLocation } from '@jbrowse/core/util/types/mst'
19
20
  import {
20
21
  Instance,
21
- SnapshotOut,
22
+ addDisposer,
22
23
  flow,
23
24
  getParentOfType,
24
25
  getRoot,
@@ -40,11 +41,12 @@ import {
40
41
  TextIndexFieldDefinition,
41
42
  } from '../OntologyManager'
42
43
  import { ApolloRootModel } from '../types'
44
+ import { autorun } from 'mobx'
43
45
 
44
46
  export function clientDataStoreFactory(
45
- AnnotationFeatureExtended: typeof AnnotationFeature,
47
+ AnnotationFeatureExtended: typeof AnnotationFeatureModel,
46
48
  ) {
47
- const clientStoreType = types
49
+ return types
48
50
  .model('ClientDataStore', {
49
51
  typeName: types.optional(types.literal('Client'), 'Client'),
50
52
  assemblies: types.map(ApolloAssembly),
@@ -68,8 +70,15 @@ export function clientDataStoreFactory(
68
70
  },
69
71
  }))
70
72
  .actions((self) => ({
71
- addAssembly(assemblyId: string) {
72
- return self.assemblies.put({ _id: assemblyId, refSeqs: {} })
73
+ addAssembly(assemblyId: string, backendDriverType?: BackendDriverType) {
74
+ const assemblySnapshot: ApolloAssemblySnapshot = {
75
+ _id: assemblyId,
76
+ refSeqs: {},
77
+ }
78
+ if (backendDriverType) {
79
+ assemblySnapshot.backendDriverType = backendDriverType
80
+ }
81
+ return self.assemblies.put(assemblySnapshot)
73
82
  },
74
83
  addFeature(assemblyId: string, feature: AnnotationFeatureSnapshot) {
75
84
  const assembly = self.assemblies.get(assemblyId)
@@ -131,36 +140,39 @@ export function clientDataStoreFactory(
131
140
  }))
132
141
  .actions((self) => ({
133
142
  afterCreate() {
134
- // Merge in the ontologies from our plugin configuration.
135
- // Ontologies of a given name that are already in the session
136
- // take precedence over the ontologies in the configuration.
137
- const { ontologyManager, pluginConfiguration } = self
138
- const configuredOntologies =
139
- pluginConfiguration.ontologies as ConfigurationModel<
140
- typeof OntologyRecordConfiguration
141
- >[]
142
-
143
- for (const ont of configuredOntologies || []) {
144
- const [name, version, source, indexFields] = [
145
- readConfObject(ont, 'name') as string,
146
- readConfObject(ont, 'version') as string,
147
- readConfObject(ont, 'source') as
148
- | Instance<typeof LocalPathLocation>
149
- | Instance<typeof UriLocation>,
150
- readConfObject(
151
- ont,
152
- 'textIndexFields',
153
- ) as TextIndexFieldDefinition[],
154
- ]
155
- if (!ontologyManager.findOntology(name)) {
156
- ontologyManager.addOntology(name, version, source, {
157
- textIndexing: { indexFields },
158
- })
159
- }
160
- }
161
-
162
- // TODO: add in any configured ontology prefixes that we don't already
163
- // have in the session (or hardcoded in the model)
143
+ addDisposer(
144
+ self,
145
+ autorun(() => {
146
+ // Merge in the ontologies from our plugin configuration.
147
+ // Ontologies of a given name that are already in the session
148
+ // take precedence over the ontologies in the configuration.
149
+ const { ontologyManager, pluginConfiguration } = self
150
+ const configuredOntologies =
151
+ pluginConfiguration.ontologies as ConfigurationModel<
152
+ typeof OntologyRecordConfiguration
153
+ >[]
154
+ for (const ont of configuredOntologies || []) {
155
+ const [name, version, source, indexFields] = [
156
+ readConfObject(ont, 'name') as string,
157
+ readConfObject(ont, 'version') as string,
158
+ readConfObject(ont, 'source') as
159
+ | Instance<typeof LocalPathLocation>
160
+ | Instance<typeof UriLocation>,
161
+ readConfObject(
162
+ ont,
163
+ 'textIndexFields',
164
+ ) as TextIndexFieldDefinition[],
165
+ ]
166
+ if (!ontologyManager.findOntology(name)) {
167
+ ontologyManager.addOntology(name, version, source, {
168
+ textIndexing: { indexFields },
169
+ })
170
+ }
171
+ }
172
+ // TODO: add in any configured ontology prefixes that we don't already
173
+ // have in the session (or hardcoded in the model)
174
+ }),
175
+ )
164
176
  },
165
177
  }))
166
178
  .views((self) => ({
@@ -275,13 +287,4 @@ export function clientDataStoreFactory(
275
287
  }
276
288
  }),
277
289
  }))
278
-
279
- // assembly and feature data isn't actually reloaded on reload unless we delete it from the snap
280
- return types.snapshotProcessor(clientStoreType, {
281
- postProcessor(snap: SnapshotOut<typeof clientStoreType>) {
282
- snap.assemblies = {}
283
- snap.checkResults = {}
284
- return snap
285
- },
286
- })
287
290
  }
@@ -1,21 +1,36 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
1
+ /* eslint-disable @typescript-eslint/no-unsafe-return */
2
2
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
3
3
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
4
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
5
4
  import { ClientDataStore as ClientDataStoreType } from '@apollo-annotation/common'
6
- import { AnnotationFeature, AnnotationFeatureI } from '@apollo-annotation/mst'
7
- import { UserLocation } from '@apollo-annotation/shared'
8
- import { AssemblyModel } from '@jbrowse/core/assemblyManager/assembly'
9
- import { getConf } from '@jbrowse/core/configuration'
10
- import { BaseInternetAccountModel } from '@jbrowse/core/pluggableElementTypes'
5
+ import {
6
+ AnnotationFeature,
7
+ AnnotationFeatureModel,
8
+ } from '@apollo-annotation/mst'
9
+ import {
10
+ filterJBrowseConfig,
11
+ ImportJBrowseConfigChange,
12
+ JBrowseConfig,
13
+ UserLocation,
14
+ } from '@apollo-annotation/shared'
15
+ import { readConfObject, getConf } from '@jbrowse/core/configuration'
16
+ import { BaseTrackConfig } from '@jbrowse/core/pluggableElementTypes'
11
17
  import PluginManager from '@jbrowse/core/PluginManager'
12
18
  import {
13
19
  AbstractSessionModel,
14
20
  SessionWithConfigEditing,
15
21
  } from '@jbrowse/core/util'
16
22
  import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
23
+ import SaveIcon from '@mui/icons-material/Save'
17
24
  import { autorun, observable } from 'mobx'
18
- import { Instance, flow, getRoot, types } from 'mobx-state-tree'
25
+ import {
26
+ Instance,
27
+ SnapshotOut,
28
+ applySnapshot,
29
+ flow,
30
+ getRoot,
31
+ getSnapshot,
32
+ types,
33
+ } from 'mobx-state-tree'
19
34
 
20
35
  import { ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
21
36
  import { ApolloJobModel } from '../ApolloJobModel'
@@ -23,27 +38,12 @@ import { ChangeManager } from '../ChangeManager'
23
38
  import { ApolloRootModel } from '../types'
24
39
  import { createFetchErrorMessage } from '../util'
25
40
  import { clientDataStoreFactory } from './ClientDataStore'
41
+ import { AssemblyModel } from '@jbrowse/core/assemblyManager/assembly'
26
42
 
27
43
  export interface ApolloSession extends AbstractSessionModel {
28
44
  apolloDataStore: ClientDataStoreType & { changeManager: ChangeManager }
29
- apolloSelectedFeature?: AnnotationFeatureI
30
- apolloSetSelectedFeature(feature?: AnnotationFeatureI): void
31
- }
32
-
33
- interface ApolloAssemblyResponse {
34
- _id: string
35
- name: string
36
- displayName?: string
37
- description?: string
38
- aliases?: string[]
39
- }
40
-
41
- export interface ApolloRefSeqResponse {
42
- _id: string
43
- name: string
44
- description?: string
45
- length: string
46
- assembly: string
45
+ apolloSelectedFeature?: AnnotationFeature
46
+ apolloSetSelectedFeature(feature?: AnnotationFeature): void
47
47
  }
48
48
 
49
49
  export interface Collaborator {
@@ -60,10 +60,10 @@ export function extendSession(
60
60
  const { signal } = aborter
61
61
  const AnnotationFeatureExtended = pluginManager.evaluateExtensionPoint(
62
62
  'Apollo-extendAnnotationFeature',
63
- AnnotationFeature,
64
- ) as typeof AnnotationFeature
63
+ AnnotationFeatureModel,
64
+ ) as typeof AnnotationFeatureModel
65
65
  const ClientDataStore = clientDataStoreFactory(AnnotationFeatureExtended)
66
- return sessionModel
66
+ const sm = sessionModel
67
67
  .props({
68
68
  apolloDataStore: types.optional(ClientDataStore, { typeName: 'Client' }),
69
69
  apolloSelectedFeature: types.safeReference(AnnotationFeatureExtended),
@@ -93,7 +93,8 @@ export function extendSession(
93
93
  }
94
94
  })
95
95
  .actions((self) => ({
96
- apolloSetSelectedFeature(feature?: AnnotationFeatureI) {
96
+ apolloSetSelectedFeature(feature?: AnnotationFeature) {
97
+ // @ts-expect-error Not sure why TS thinks these MST types don't match
97
98
  self.apolloSelectedFeature = feature
98
99
  },
99
100
  addApolloTrackConfig(assembly: AssemblyModel, baseURL?: string) {
@@ -186,7 +187,15 @@ export function extendSession(
186
187
  }))
187
188
  .actions((self) => ({
188
189
  afterCreate: flow(function* afterCreate() {
189
- const { internetAccounts } = getRoot<ApolloRootModel>(self)
190
+ // When the initial config.json loads, it doesn't include the Apollo
191
+ // tracks, which would result in a potentially invalid session snapshot
192
+ // if any tracks are open. Here we copy the session snapshot, apply an
193
+ // empty session snapshot, and then restore the original session
194
+ // snapshot after the updated config.json loads.
195
+ const sessionSnapshot = getSnapshot(self)
196
+ const { id, name } = sessionSnapshot
197
+ applySnapshot(self, { name, id })
198
+ const { internetAccounts, jbrowse } = getRoot<ApolloRootModel>(self)
190
199
  autorun(
191
200
  () => {
192
201
  // broadcastLocations() // **** This is not working and therefore we need to duplicate broadcastLocations() -method code here because autorun() does not observe changes otherwise
@@ -248,8 +257,8 @@ export function extendSession(
248
257
  continue
249
258
  }
250
259
 
251
- const { baseURL, configuration } = internetAccount
252
- const uri = new URL('assemblies', baseURL).href
260
+ const { baseURL } = internetAccount
261
+ const uri = new URL('jbrowse/config.json', baseURL).href
253
262
  const fetch = internetAccount.getFetcher({
254
263
  locationType: 'UriLocation',
255
264
  uri,
@@ -259,7 +268,6 @@ export function extendSession(
259
268
  response = yield fetch(uri, { signal })
260
269
  } catch (error) {
261
270
  console.error(error)
262
- // setError(e instanceof Error ? e : new Error(String(e)))
263
271
  continue
264
272
  }
265
273
  if (!response.ok) {
@@ -270,96 +278,160 @@ export function extendSession(
270
278
  console.error(errorMessage)
271
279
  continue
272
280
  }
273
- let fetchedAssemblies
281
+ let jbrowseConfig
274
282
  try {
275
- fetchedAssemblies =
276
- (yield response.json()) as ApolloAssemblyResponse[]
283
+ jbrowseConfig = yield response.json()
277
284
  } catch (error) {
278
285
  console.error(error)
279
286
  continue
280
287
  }
281
- for (const assembly of fetchedAssemblies) {
282
- const { addAssembly, addSessionAssembly, assemblyManager } =
283
- self as unknown as AbstractSessionModel & {
284
- // eslint-disable-next-line @typescript-eslint/ban-types
285
- addSessionAssembly: Function
286
- }
287
- const selectedAssembly = assemblyManager.get(assembly.name)
288
- if (selectedAssembly) {
289
- // @ts-expect-error MST type coercion problem?
290
- self.addApolloTrackConfig(selectedAssembly, baseURL)
291
- continue
292
- }
293
- const url = new URL('refSeqs', baseURL)
294
- const searchParams = new URLSearchParams({ assembly: assembly._id })
295
- url.search = searchParams.toString()
296
- const uri2 = url.toString()
297
- const fetch2 = internetAccount.getFetcher({
298
- locationType: 'UriLocation',
299
- uri: uri2,
300
- })
301
- const response2 = (yield fetch2(uri2, {
302
- signal,
303
- })) as unknown as Response
304
- if (!response2.ok) {
305
- let errorMessage
306
- try {
307
- errorMessage = yield response2.text()
308
- } catch {
309
- errorMessage = ''
310
- }
311
- throw new Error(
312
- `Failed to fetch fasta info — ${response2.status} (${
313
- response2.statusText
314
- })${errorMessage ? ` (${errorMessage})` : ''}`,
315
- )
316
- }
317
- const f = (yield response2.json()) as ApolloRefSeqResponse[]
318
- const ids: Record<string, string> = {}
319
- const refNameAliasesFeatures = f.map((contig) => {
320
- ids[contig.name] = contig._id
321
- return {
322
- refName: contig.name,
323
- aliases: [contig._id],
324
- uniqueId: `alias-${contig._id}`,
325
- }
326
- })
327
- const assemblyConfig = {
328
- name: assembly._id,
329
- aliases: [assembly.name, ...(assembly.aliases ?? [])],
330
- displayName: assembly.displayName ?? assembly.name,
331
- sequence: {
332
- trackId: `sequenceConfigId-${assembly.name}`,
333
- type: 'ReferenceSequenceTrack',
334
- adapter: {
335
- type: 'ApolloSequenceAdapter',
336
- assemblyId: assembly._id,
337
- baseURL: { uri: baseURL, locationType: 'UriLocation' },
338
- },
339
- metadata: {
340
- apollo: true,
341
- internetAccountConfigId: configuration.internetAccountId,
342
- ids,
343
- },
344
- },
345
- refNameAliases: {
346
- adapter: {
347
- type: 'FromConfigAdapter',
348
- features: refNameAliasesFeatures,
349
- },
350
- },
351
- }
352
- ;(addSessionAssembly || addAssembly)(assemblyConfig)
353
- const a = yield assemblyManager.waitForAssembly(assemblyConfig.name)
354
- self.addApolloTrackConfig(a, baseURL)
355
- }
288
+ applySnapshot(jbrowse, jbrowseConfig)
289
+ applySnapshot(self, sessionSnapshot)
356
290
  }
357
291
  }),
358
292
  beforeDestroy() {
359
- aborter.abort()
293
+ aborter.abort('destroying session model')
360
294
  },
361
295
  }))
296
+
297
+ .views((self) => {
298
+ const superTrackActionMenuItems = (
299
+ self as unknown as AbstractSessionModel
300
+ ).getTrackActionMenuItems
301
+ return {
302
+ getTrackActionMenuItems(conf: BaseTrackConfig) {
303
+ if (
304
+ conf.type === 'ApolloTrack' ||
305
+ conf.type === 'ReferenceSequenceTrack'
306
+ ) {
307
+ return superTrackActionMenuItems?.(conf)
308
+ }
309
+ const trackId = readConfObject(conf, 'trackId') as string
310
+ const sessionTrackIdentifier = '-sessionTrack'
311
+ const isSessionTrack = trackId.endsWith(sessionTrackIdentifier)
312
+ return isSessionTrack
313
+ ? [
314
+ ...(superTrackActionMenuItems?.(conf) ?? []),
315
+ {
316
+ label: 'Save track to Apollo',
317
+ onClick: async () => {
318
+ const { internetAccounts, jbrowse } =
319
+ getRoot<ApolloRootModel>(self)
320
+ const currentConfig = getSnapshot<JBrowseConfig>(jbrowse)
321
+ let filteredConfig: JBrowseConfig | undefined
322
+ filteredConfig = filterJBrowseConfig(currentConfig)
323
+ if (Object.keys(filteredConfig).length === 0) {
324
+ filteredConfig = undefined
325
+ }
326
+ const trackConfigSnapshot = getSnapshot(conf) as {
327
+ trackId: string
328
+ type: string
329
+ }
330
+ const newTrackId = trackId.slice(
331
+ 0,
332
+ trackId.length - sessionTrackIdentifier.length,
333
+ )
334
+ const newTrackConfigSnapshot = {
335
+ ...trackConfigSnapshot,
336
+ trackId: newTrackId,
337
+ }
338
+ for (const internetAccount of internetAccounts as ApolloInternetAccountModel[]) {
339
+ if (internetAccount.type !== 'ApolloInternetAccount') {
340
+ continue
341
+ }
342
+ const change = new ImportJBrowseConfigChange({
343
+ typeName: 'ImportJBrowseConfigChange',
344
+ oldJBrowseConfig: filteredConfig,
345
+ newJBrowseConfig: {
346
+ ...filteredConfig,
347
+ tracks: filteredConfig?.tracks && [
348
+ ...filteredConfig.tracks,
349
+ newTrackConfigSnapshot,
350
+ ],
351
+ },
352
+ })
353
+ const { internetAccountId } = internetAccount
354
+ await self.apolloDataStore.changeManager.submit(change, {
355
+ internetAccountId,
356
+ })
357
+ const { notify } = self as unknown as AbstractSessionModel
358
+ notify('Track added', 'success')
359
+ }
360
+ // @ts-expect-error This method is missing in the JB types
361
+ self.deleteTrackConf(conf)
362
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
363
+ jbrowse.addTrackConf(newTrackConfigSnapshot)
364
+ },
365
+ icon: SaveIcon,
366
+ },
367
+ ]
368
+ : [
369
+ ...(superTrackActionMenuItems?.(conf) ?? []),
370
+ {
371
+ label: 'Remove track from Apollo',
372
+ onClick: async () => {
373
+ const { internetAccounts, jbrowse } =
374
+ getRoot<ApolloRootModel>(self)
375
+ const currentConfig = getSnapshot<JBrowseConfig>(jbrowse)
376
+ let filteredConfig: JBrowseConfig | undefined
377
+ filteredConfig = filterJBrowseConfig(currentConfig)
378
+ if (Object.keys(filteredConfig).length === 0) {
379
+ filteredConfig = undefined
380
+ }
381
+ const filteredTracks = filteredConfig?.tracks?.filter(
382
+ (t) => t.trackId !== trackId,
383
+ )
384
+ for (const internetAccount of internetAccounts as ApolloInternetAccountModel[]) {
385
+ if (internetAccount.type !== 'ApolloInternetAccount') {
386
+ continue
387
+ }
388
+ const change = new ImportJBrowseConfigChange({
389
+ typeName: 'ImportJBrowseConfigChange',
390
+ oldJBrowseConfig: filteredConfig,
391
+ newJBrowseConfig: {
392
+ ...filteredConfig,
393
+ tracks: filteredTracks,
394
+ },
395
+ })
396
+ const { internetAccountId } = internetAccount
397
+ await self.apolloDataStore.changeManager.submit(change, {
398
+ internetAccountId,
399
+ })
400
+ const { notify } = self as unknown as AbstractSessionModel
401
+ notify('Track removed', 'success')
402
+ }
403
+ // @ts-expect-error This method is missing in the JB types
404
+ self.deleteTrackConf(conf)
405
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
406
+ jbrowse.deleteTrackConf(conf)
407
+ },
408
+ icon: SaveIcon,
409
+ },
410
+ ]
411
+ },
412
+ }
413
+ })
414
+ return types.snapshotProcessor(sm, {
415
+ postProcessor(snap: SnapshotOut<typeof sm>) {
416
+ snap.apolloSelectedFeature = undefined
417
+ const assemblies = Object.fromEntries(
418
+ Object.entries(snap.apolloDataStore.assemblies).filter(
419
+ ([, assembly]) => assembly.backendDriverType === 'InMemoryFileDriver',
420
+ ),
421
+ )
422
+ snap.apolloDataStore = {
423
+ typeName: 'Client',
424
+ assemblies,
425
+ checkResults: {},
426
+ }
427
+ return snap
428
+ },
429
+ })
362
430
  }
363
431
 
364
432
  export type ApolloSessionStateModel = ReturnType<typeof extendSession>
365
- export type ApolloSessionModel = Instance<ApolloSessionStateModel>
433
+ // @ts-expect-error Snapshots seem to mess up types here
434
+ // eslint disable because of
435
+ // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
436
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
437
+ export interface ApolloSessionModel extends Instance<ApolloSessionStateModel> {}