@apollo-annotation/jbrowse-plugin-apollo 0.3.5 → 0.3.7

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 (136) hide show
  1. package/dist/index.esm.js +6964 -4598
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +6610 -4261
  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 +11563 -7493
  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 +4 -4
  12. package/src/ApolloInternetAccount/addMenuItems.ts +23 -2
  13. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
  14. package/src/ApolloInternetAccount/components/LoginButtons.tsx +1 -1
  15. package/src/ApolloInternetAccount/components/LoginIcons.tsx +1 -1
  16. package/src/ApolloInternetAccount/configSchema.ts +1 -1
  17. package/src/ApolloInternetAccount/model.ts +11 -10
  18. package/src/ApolloJobModel.ts +1 -1
  19. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +8 -6
  20. package/src/ApolloRefNameAliasAdapter/index.ts +2 -2
  21. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +4 -4
  22. package/src/ApolloSequenceAdapter/index.ts +1 -1
  23. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +8 -7
  24. package/src/ApolloTextSearchAdapter/index.ts +1 -1
  25. package/src/BackendDrivers/BackendDriver.ts +7 -7
  26. package/src/BackendDrivers/CollaborationServerDriver.ts +14 -10
  27. package/src/BackendDrivers/DesktopFileDriver.ts +11 -10
  28. package/src/BackendDrivers/InMemoryFileDriver.ts +10 -6
  29. package/src/ChangeManager.ts +15 -11
  30. package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +8 -7
  31. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +35 -14
  32. package/src/FeatureDetailsWidget/AttributeKey.tsx +50 -0
  33. package/src/FeatureDetailsWidget/AttributeKeySelector.tsx +104 -0
  34. package/src/FeatureDetailsWidget/Attributes.tsx +215 -367
  35. package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -5
  36. package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +104 -0
  37. package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +22 -0
  38. package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +4 -4
  39. package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -1
  40. package/src/FeatureDetailsWidget/Sequence.tsx +2 -2
  41. package/src/FeatureDetailsWidget/StringTextField.tsx +1 -1
  42. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +15 -23
  43. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +950 -196
  44. package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +8 -4
  45. package/src/FeatureDetailsWidget/model.ts +8 -3
  46. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +7 -7
  47. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +59 -72
  48. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +253 -60
  49. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +52 -6
  50. package/src/LinearApolloDisplay/glyphs/Glyph.ts +16 -8
  51. package/src/LinearApolloDisplay/stateModel/base.ts +81 -10
  52. package/src/LinearApolloDisplay/stateModel/index.ts +4 -3
  53. package/src/LinearApolloDisplay/stateModel/layouts.ts +8 -39
  54. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +63 -46
  55. package/src/LinearApolloDisplay/stateModel/rendering.ts +60 -31
  56. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +226 -0
  57. package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +32 -0
  58. package/src/LinearApolloSixFrameDisplay/components/index.ts +2 -0
  59. package/src/LinearApolloSixFrameDisplay/configSchema.ts +7 -0
  60. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +940 -0
  61. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +63 -0
  62. package/src/LinearApolloSixFrameDisplay/glyphs/index.ts +1 -0
  63. package/src/LinearApolloSixFrameDisplay/index.ts +2 -0
  64. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +302 -0
  65. package/src/LinearApolloSixFrameDisplay/stateModel/index.ts +27 -0
  66. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +252 -0
  67. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +368 -0
  68. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +201 -0
  69. package/src/LinearApolloSixFrameDisplay/types.ts +1 -0
  70. package/src/OntologyManager/OntologyStore/fulltext.test.ts +1 -1
  71. package/src/OntologyManager/OntologyStore/fulltext.ts +8 -3
  72. package/src/OntologyManager/OntologyStore/index.test.ts +3 -1
  73. package/src/OntologyManager/OntologyStore/index.ts +19 -14
  74. package/src/OntologyManager/OntologyStore/indexeddb-schema.ts +6 -5
  75. package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +11 -5
  76. package/src/OntologyManager/index.ts +12 -7
  77. package/src/OntologyManager/util.ts +3 -2
  78. package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
  79. package/src/TabularEditor/HybridGrid/Feature.tsx +13 -7
  80. package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +1 -1
  81. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +3 -2
  82. package/src/TabularEditor/HybridGrid/ToolBar.tsx +1 -1
  83. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +114 -22
  84. package/src/TabularEditor/TabularEditorPane.tsx +1 -1
  85. package/src/TabularEditor/model.ts +2 -2
  86. package/src/TabularEditor/types.ts +5 -2
  87. package/src/components/AddAssembly.tsx +182 -179
  88. package/src/components/AddAssemblyAliases.tsx +114 -0
  89. package/src/components/AddChildFeature.tsx +8 -10
  90. package/src/components/AddFeature.tsx +216 -44
  91. package/src/components/AddRefSeqAliases.tsx +14 -12
  92. package/src/components/CopyFeature.tsx +10 -11
  93. package/src/components/CreateApolloAnnotation.tsx +342 -158
  94. package/src/components/DeleteAssembly.tsx +9 -8
  95. package/src/components/DeleteFeature.tsx +362 -14
  96. package/src/components/Dialog.tsx +1 -1
  97. package/src/components/DownloadGFF3.tsx +31 -11
  98. package/src/components/FilterFeatures.tsx +6 -4
  99. package/src/components/FilterTranscripts.tsx +86 -0
  100. package/src/components/ImportFeatures.tsx +7 -6
  101. package/src/components/LogOut.tsx +5 -4
  102. package/src/components/ManageChecks.tsx +9 -8
  103. package/src/components/ManageUsers.tsx +11 -10
  104. package/src/components/MergeExons.tsx +193 -0
  105. package/src/components/MergeTranscripts.tsx +185 -0
  106. package/src/components/OntologyTermAutocomplete.tsx +5 -5
  107. package/src/components/OntologyTermMultiSelect.tsx +6 -6
  108. package/src/components/OpenLocalFile.tsx +4 -3
  109. package/src/components/SplitExon.tsx +134 -0
  110. package/src/components/ViewChangeLog.tsx +7 -6
  111. package/src/components/ViewCheckResults.tsx +8 -7
  112. package/src/components/index.ts +3 -0
  113. package/src/config.ts +5 -0
  114. package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -0
  115. package/src/extensions/annotationFromJBrowseFeature.ts +13 -10
  116. package/src/extensions/annotationFromPileup.ts +104 -94
  117. package/src/index.ts +33 -50
  118. package/src/makeDisplayComponent.tsx +90 -37
  119. package/src/session/ClientDataStore.ts +21 -17
  120. package/src/session/session.ts +46 -39
  121. package/src/types.ts +4 -4
  122. package/src/util/annotationFeatureUtils.ts +66 -1
  123. package/src/util/copyToClipboard.ts +21 -0
  124. package/src/util/glyphUtils.ts +49 -0
  125. package/src/util/index.ts +5 -3
  126. package/src/util/loadAssemblyIntoClient.ts +10 -3
  127. package/src/util/mouseEventsUtils.ts +113 -0
  128. package/src/ApolloSixFrameRenderer/ApolloSixFrameRenderer.tsx +0 -13
  129. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +0 -707
  130. package/src/ApolloSixFrameRenderer/configSchema.ts +0 -7
  131. package/src/ApolloSixFrameRenderer/index.ts +0 -3
  132. package/src/SixFrameFeatureDisplay/components/TrackLines.tsx +0 -19
  133. package/src/SixFrameFeatureDisplay/components/index.ts +0 -1
  134. package/src/SixFrameFeatureDisplay/configSchema.ts +0 -21
  135. package/src/SixFrameFeatureDisplay/index.ts +0 -2
  136. package/src/SixFrameFeatureDisplay/stateModel.ts +0 -443
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/unbound-method */
2
- import PluginManager from '@jbrowse/core/PluginManager'
3
- import type LinearGenomeViewPlugin from '@jbrowse/plugin-linear-genome-view'
2
+ import { getSession } from '@jbrowse/core/util'
4
3
  import ExpandLessIcon from '@mui/icons-material/ExpandLess'
5
4
  import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
6
5
  import { Alert, Typography, alpha } from '@mui/material'
@@ -9,13 +8,11 @@ import React, { useCallback, useEffect, useRef } from 'react'
9
8
  import { makeStyles } from 'tss-react/mui'
10
9
 
11
10
  import { LinearApolloDisplay } from './LinearApolloDisplay/components'
12
- import { LinearApolloDisplay as LinearApolloDisplayI } from './LinearApolloDisplay/stateModel'
13
- import { TrackLines } from './SixFrameFeatureDisplay/components'
14
- import { SixFrameFeatureDisplay } from './SixFrameFeatureDisplay/stateModel'
11
+ import { type LinearApolloDisplay as LinearApolloDisplayI } from './LinearApolloDisplay/stateModel'
12
+ import { LinearApolloSixFrameDisplay } from './LinearApolloSixFrameDisplay/components'
13
+ import { type LinearApolloSixFrameDisplay as LinearApolloSixFrameDisplayI } from './LinearApolloSixFrameDisplay/stateModel'
15
14
  import { TabularEditorPane } from './TabularEditor'
16
-
17
- import { getSession } from '@jbrowse/core/util'
18
- import { ApolloSessionModel } from './session'
15
+ import { type ApolloSessionModel } from './session'
19
16
 
20
17
  const accordionControlHeight = 12
21
18
 
@@ -63,7 +60,7 @@ const useStyles = makeStyles()((theme) => ({
63
60
  }))
64
61
 
65
62
  function scrollSelectedFeatureIntoView(
66
- model: LinearApolloDisplayI,
63
+ model: LinearApolloDisplayI | LinearApolloSixFrameDisplayI,
67
64
  scrollContainerRef: React.RefObject<HTMLDivElement>,
68
65
  ) {
69
66
  const { apolloRowHeight, selectedFeature } = model
@@ -157,7 +154,7 @@ const AccordionControl = observer(function AccordionControl({
157
154
  )
158
155
  })
159
156
 
160
- export const DisplayComponent = observer(function DisplayComponent({
157
+ export const LinearApolloDisplayComponent = observer(function DisplayComponent({
161
158
  model,
162
159
  ...other
163
160
  }: {
@@ -248,40 +245,96 @@ export const DisplayComponent = observer(function DisplayComponent({
248
245
  )
249
246
  })
250
247
 
251
- export function makeSixFrameDisplayComponent(pluginManager: PluginManager) {
252
- const LGVPlugin = pluginManager.getPlugin('LinearGenomeViewPlugin') as
253
- | LinearGenomeViewPlugin
254
- | undefined
255
- if (!LGVPlugin) {
256
- throw new Error('LinearGenomeView plugin not found')
257
- }
258
- const { BaseLinearDisplayComponent } = LGVPlugin.exports
259
- function ApolloDisplayComponent({
248
+ export const LinearApolloSixFrameDisplayComponent = observer(
249
+ function DisplayComponent({
260
250
  model,
261
251
  ...other
262
252
  }: {
263
- model: SixFrameFeatureDisplay
253
+ model: LinearApolloSixFrameDisplayI
264
254
  }) {
255
+ const session = getSession(model) as unknown as ApolloSessionModel
256
+ const { ontologyManager } = session.apolloDataStore
257
+ const { featureTypeOntology } = ontologyManager
258
+ const ontologyStore = featureTypeOntology?.dataStore
259
+
265
260
  const { classes } = useStyles()
266
- const { height, selectedFeature } = model
267
- let { detailsHeight } = model
268
- if (!selectedFeature) {
269
- detailsHeight = 0
261
+
262
+ const {
263
+ detailsHeight,
264
+ graphical,
265
+ height: overallHeight,
266
+ isShown,
267
+ selectedFeature,
268
+ table,
269
+ tabularEditor,
270
+ toggleShown,
271
+ } = model
272
+
273
+ const canvasScrollContainerRef = useRef<HTMLDivElement>(null)
274
+ useEffect(() => {
275
+ scrollSelectedFeatureIntoView(model, canvasScrollContainerRef)
276
+ }, [model, selectedFeature])
277
+
278
+ const onDetailsResize = (delta: number) => {
279
+ model.setDetailsHeight(detailsHeight - delta)
270
280
  }
271
- const featureAreaHeight = height - detailsHeight
272
- return (
273
- <div style={{ height: model.height }}>
274
- <div className={classes.shading} style={{ height: featureAreaHeight }}>
275
- <BaseLinearDisplayComponent model={model} {...other} />
281
+
282
+ if (!ontologyStore) {
283
+ return (
284
+ <div className={classes.alertContainer}>
285
+ <Alert severity="error">Could not load feature type ontology.</Alert>
286
+ </div>
287
+ )
288
+ }
289
+
290
+ if (graphical && table) {
291
+ const tabularHeight = tabularEditor.isShown ? detailsHeight : 0
292
+ const featureAreaHeight = isShown
293
+ ? overallHeight - detailsHeight - accordionControlHeight * 2
294
+ : 0
295
+ return (
296
+ <div style={{ height: overallHeight }}>
297
+ <AccordionControl
298
+ open={isShown}
299
+ title="Graphical"
300
+ onClick={toggleShown}
301
+ />
302
+ <div
303
+ className={classes.shading}
304
+ ref={canvasScrollContainerRef}
305
+ style={{ height: featureAreaHeight }}
306
+ >
307
+ <LinearApolloSixFrameDisplay model={model} {...other} />
308
+ </div>
309
+ <AccordionControl
310
+ title="Table"
311
+ open={tabularEditor.isShown}
312
+ onClick={tabularEditor.togglePane}
313
+ onResize={onDetailsResize}
314
+ />
315
+ <div className={classes.details} style={{ height: tabularHeight }}>
316
+ <TabularEditorPane model={model} />
317
+ </div>
276
318
  </div>
277
- {/* <div className={classes.details} style={{ height: detailsHeight }}>
278
- <ApolloDetails model={model} />
279
- </div> */}
280
- <div className="testTrackLines">
281
- <TrackLines model={model} />
319
+ )
320
+ }
321
+
322
+ if (graphical) {
323
+ return (
324
+ <div
325
+ className={classes.shading}
326
+ ref={canvasScrollContainerRef}
327
+ style={{ height: overallHeight }}
328
+ >
329
+ <LinearApolloSixFrameDisplay model={model} {...other} />
282
330
  </div>
331
+ )
332
+ }
333
+
334
+ return (
335
+ <div className={classes.details} style={{ height: overallHeight }}>
336
+ <TabularEditorPane model={model} />
283
337
  </div>
284
338
  )
285
- }
286
- return observer(ApolloDisplayComponent)
287
- }
339
+ },
340
+ )
@@ -2,23 +2,27 @@
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3
3
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
4
4
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
5
- import { ClientDataStore as ClientDataStoreType } from '@apollo-annotation/common'
5
+ import { type ClientDataStore as ClientDataStoreType } from '@apollo-annotation/common'
6
6
  import {
7
- AnnotationFeatureModel,
8
- AnnotationFeatureSnapshot,
7
+ type AnnotationFeatureModel,
8
+ type AnnotationFeatureSnapshot,
9
9
  ApolloAssembly,
10
- ApolloAssemblySnapshot,
10
+ type ApolloAssemblySnapshot,
11
11
  ApolloRefSeq,
12
- BackendDriverType,
12
+ type BackendDriverType,
13
13
  CheckResult,
14
- CheckResultSnapshot,
14
+ type CheckResultSnapshot,
15
15
  } from '@apollo-annotation/mst'
16
16
  import { getConf, readConfObject } from '@jbrowse/core/configuration'
17
- import { ConfigurationModel } from '@jbrowse/core/configuration/types'
18
- import { Region, getSession, isElectron } from '@jbrowse/core/util'
19
- import { LocalPathLocation, UriLocation } from '@jbrowse/core/util/types/mst'
17
+ import { type ConfigurationModel } from '@jbrowse/core/configuration/types'
18
+ import { type Region, getSession, isElectron } from '@jbrowse/core/util'
20
19
  import {
21
- Instance,
20
+ type LocalPathLocation,
21
+ type UriLocation,
22
+ } from '@jbrowse/core/util/types/mst'
23
+ import { autorun } from 'mobx'
24
+ import {
25
+ type Instance,
22
26
  addDisposer,
23
27
  flow,
24
28
  getParentOfType,
@@ -28,21 +32,21 @@ import {
28
32
  } from 'mobx-state-tree'
29
33
 
30
34
  import {
31
- ApolloInternetAccount,
35
+ type ApolloInternetAccount,
32
36
  CollaborationServerDriver,
33
37
  DesktopFileDriver,
34
38
  InMemoryFileDriver,
35
39
  } from '../BackendDrivers'
36
40
  import { ChangeManager } from '../ChangeManager'
37
- import ApolloPluginConfigurationSchema from '../config'
38
41
  import {
39
42
  OntologyManagerType,
40
- OntologyRecordConfiguration,
41
- TextIndexFieldDefinition,
43
+ type OntologyRecordConfiguration,
44
+ type TextIndexFieldDefinition,
42
45
  } from '../OntologyManager'
43
- import { ApolloRootModel } from '../types'
44
- import { autorun } from 'mobx'
45
- import { ApolloSessionModel } from './session'
46
+ import type ApolloPluginConfigurationSchema from '../config'
47
+ import { type ApolloRootModel } from '../types'
48
+
49
+ import { type ApolloSessionModel } from './session'
46
50
 
47
51
  export function clientDataStoreFactory(
48
52
  AnnotationFeatureExtended: typeof AnnotationFeatureModel,
@@ -1,27 +1,31 @@
1
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
- import { ClientDataStore as ClientDataStoreType } from '@apollo-annotation/common'
4
+ import { type ClientDataStore as ClientDataStoreType } from '@apollo-annotation/common'
5
5
  import {
6
- AnnotationFeature,
6
+ type AnnotationFeature,
7
7
  AnnotationFeatureModel,
8
8
  } from '@apollo-annotation/mst'
9
9
  import {
10
- filterJBrowseConfig,
11
10
  ImportJBrowseConfigChange,
12
- JBrowseConfig,
13
- UserLocation,
11
+ type JBrowseConfig,
12
+ type UserLocation,
13
+ filterJBrowseConfig,
14
14
  } from '@apollo-annotation/shared'
15
- import { readConfObject, getConf } from '@jbrowse/core/configuration'
16
- import { BaseTrackConfig } from '@jbrowse/core/pluggableElementTypes'
17
- import PluginManager from '@jbrowse/core/PluginManager'
18
- import { AbstractSessionModel, SessionWithAddTracks } from '@jbrowse/core/util'
19
- import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
15
+ import type PluginManager from '@jbrowse/core/PluginManager'
16
+ import { type AssemblyModel } from '@jbrowse/core/assemblyManager/assembly'
17
+ import { getConf, readConfObject } from '@jbrowse/core/configuration'
18
+ import { type BaseTrackConfig } from '@jbrowse/core/pluggableElementTypes'
19
+ import {
20
+ type AbstractSessionModel,
21
+ type SessionWithAddTracks,
22
+ } from '@jbrowse/core/util'
23
+ import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
20
24
  import SaveIcon from '@mui/icons-material/Save'
21
25
  import { autorun, observable } from 'mobx'
22
26
  import {
23
- Instance,
24
- SnapshotOut,
27
+ type Instance,
28
+ type SnapshotOut,
25
29
  applySnapshot,
26
30
  flow,
27
31
  getRoot,
@@ -29,13 +33,14 @@ import {
29
33
  types,
30
34
  } from 'mobx-state-tree'
31
35
 
32
- import { ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
36
+ import { type ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
33
37
  import { ApolloJobModel } from '../ApolloJobModel'
34
- import { ChangeManager } from '../ChangeManager'
35
- import { ApolloRootModel } from '../types'
38
+ import { type ChangeManager } from '../ChangeManager'
39
+ import type ApolloPluginConfigurationSchema from '../config'
40
+ import { type ApolloRootModel } from '../types'
36
41
  import { createFetchErrorMessage } from '../util'
42
+
37
43
  import { clientDataStoreFactory } from './ClientDataStore'
38
- import { AssemblyModel } from '@jbrowse/core/assemblyManager/assembly'
39
44
 
40
45
  export interface ApolloSession extends AbstractSessionModel {
41
46
  apolloDataStore: ClientDataStoreType & { changeManager: ChangeManager }
@@ -119,16 +124,6 @@ export function extendSession(
119
124
  : {}),
120
125
  },
121
126
  },
122
- displays: [
123
- {
124
- type: 'LinearApolloDisplay',
125
- displayId: `${trackId}-LinearApolloDisplay`,
126
- },
127
- {
128
- type: 'SixFrameFeatureDisplay',
129
- displayId: `${trackId}-SixFrameFeatureDisplay`,
130
- },
131
- ],
132
127
  })
133
128
  }
134
129
  },
@@ -191,15 +186,6 @@ export function extendSession(
191
186
  }))
192
187
  .actions((self) => ({
193
188
  afterCreate: flow(function* afterCreate() {
194
- // When the initial config.json loads, it doesn't include the Apollo
195
- // tracks, which would result in a potentially invalid session snapshot
196
- // if any tracks are open. Here we copy the session snapshot, apply an
197
- // empty session snapshot, and then restore the original session
198
- // snapshot after the updated config.json loads.
199
- const sessionSnapshot = getSnapshot(self)
200
- const { id, name } = sessionSnapshot
201
- applySnapshot(self, { name, id })
202
- const { internetAccounts, jbrowse } = getRoot<ApolloRootModel>(self)
203
189
  autorun(
204
190
  () => {
205
191
  // broadcastLocations() // **** This is not working and therefore we need to duplicate broadcastLocations() -method code here because autorun() does not observe changes otherwise
@@ -260,7 +246,29 @@ export function extendSession(
260
246
  },
261
247
  { name: 'ApolloSession' },
262
248
  )
263
- // END AUTORUN
249
+ // When the initial config.json loads, it doesn't include the Apollo
250
+ // tracks, which would result in a potentially invalid session snapshot
251
+ // if any tracks are open. Here we copy the session snapshot, apply an
252
+ // empty session snapshot, and then restore the original session
253
+ // snapshot after the updated config.json loads.
254
+ // @ts-expect-error type is missing on ApolloRootModel
255
+ const { internetAccounts, jbrowse, reloadPluginManagerCallback } =
256
+ getRoot<ApolloRootModel>(self)
257
+ const pluginConfiguration =
258
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
259
+ jbrowse.configuration.ApolloPlugin as Instance<
260
+ typeof ApolloPluginConfigurationSchema
261
+ >
262
+ const hasRole = readConfObject(
263
+ pluginConfiguration,
264
+ 'hasRole',
265
+ ) as boolean
266
+ if (hasRole) {
267
+ return
268
+ }
269
+ const sessionSnapshot = getSnapshot(self)
270
+ const { id, name } = sessionSnapshot
271
+ applySnapshot(self, { name, id })
264
272
 
265
273
  // fetch and initialize assemblies for each of our Apollo internet accounts
266
274
  for (const internetAccount of internetAccounts as ApolloInternetAccountModel[]) {
@@ -296,9 +304,8 @@ export function extendSession(
296
304
  console.error(error)
297
305
  continue
298
306
  }
299
- applySnapshot(jbrowse, jbrowseConfig)
300
- // @ts-expect-error snapshot seems to get wrong type?
301
- applySnapshot(self, sessionSnapshot)
307
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
308
+ reloadPluginManagerCallback(jbrowseConfig, sessionSnapshot)
302
309
  }
303
310
  }),
304
311
  beforeDestroy() {
package/src/types.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { BaseInternetAccountModel } from '@jbrowse/core/pluggableElementTypes'
2
- import { AppRootModel } from '@jbrowse/core/util'
1
+ import { type BaseInternetAccountModel } from '@jbrowse/core/pluggableElementTypes'
2
+ import { type AppRootModel } from '@jbrowse/core/util'
3
3
 
4
- import { ApolloInternetAccountModel } from './ApolloInternetAccount/model'
5
- import { ApolloSessionModel } from './session'
4
+ import { type ApolloInternetAccountModel } from './ApolloInternetAccount/model'
5
+ import { type ApolloSessionModel } from './session'
6
6
 
7
7
  export interface ApolloRootModel extends Omit<AppRootModel, 'session'> {
8
8
  session: ApolloSessionModel
@@ -1,4 +1,6 @@
1
- import { AnnotationFeature } from '@apollo-annotation/mst'
1
+ import { type AnnotationFeature } from '@apollo-annotation/mst'
2
+
3
+ import { type MousePosition } from '../LinearApolloDisplay/stateModel/mouseEvents'
2
4
 
3
5
  export function getFeatureName(feature: AnnotationFeature) {
4
6
  const { attributes } = feature
@@ -51,3 +53,66 @@ export function getStrand(strand: number | undefined) {
51
53
  }
52
54
  return ''
53
55
  }
56
+
57
+ function getChildren(feature: AnnotationFeature): AnnotationFeature[] {
58
+ const children: AnnotationFeature[] = []
59
+ //
60
+ if (feature.children) {
61
+ for (const [, ff] of feature.children) {
62
+ children.push(ff)
63
+ }
64
+ }
65
+ return children
66
+ }
67
+
68
+ function getParents(feature: AnnotationFeature): AnnotationFeature[] {
69
+ const parents: AnnotationFeature[] = []
70
+ let { parent } = feature
71
+ while (parent) {
72
+ parents.push(parent)
73
+ ;({ parent } = parent)
74
+ }
75
+ return parents
76
+ }
77
+
78
+ export function getFeaturesUnderClick(
79
+ mousePosition: MousePosition,
80
+ includeSiblings = false,
81
+ ): AnnotationFeature[] {
82
+ const clickedFeatures: AnnotationFeature[] = []
83
+ if (!mousePosition.featureAndGlyphUnderMouse) {
84
+ return clickedFeatures
85
+ }
86
+ clickedFeatures.push(mousePosition.featureAndGlyphUnderMouse.feature)
87
+ for (const x of getParents(mousePosition.featureAndGlyphUnderMouse.feature)) {
88
+ clickedFeatures.push(x)
89
+ }
90
+ const { bp } = mousePosition
91
+ const children = getChildren(mousePosition.featureAndGlyphUnderMouse.feature)
92
+ for (const child of children) {
93
+ if (child.min < bp && child.max >= bp) {
94
+ clickedFeatures.push(child)
95
+ }
96
+ }
97
+ if (!includeSiblings) {
98
+ return clickedFeatures
99
+ }
100
+
101
+ // Also add siblings , i.e. features having the same parent as the clicked
102
+ // one and intersecting the click position
103
+ if (mousePosition.featureAndGlyphUnderMouse.feature.parent) {
104
+ const siblings =
105
+ mousePosition.featureAndGlyphUnderMouse.feature.parent.children
106
+ if (siblings) {
107
+ for (const [, sib] of siblings) {
108
+ if (sib._id == mousePosition.featureAndGlyphUnderMouse.feature._id) {
109
+ continue
110
+ }
111
+ if (sib.min < bp && sib.max >= bp) {
112
+ clickedFeatures.push(sib)
113
+ }
114
+ }
115
+ }
116
+ }
117
+ return clickedFeatures
118
+ }
@@ -0,0 +1,21 @@
1
+ export async function copyToClipboard(element: HTMLElement) {
2
+ if (isSecureContext) {
3
+ const textBlob = new Blob([element.outerText], { type: 'text/plain' })
4
+ const htmlBlob = new Blob([element.outerHTML], { type: 'text/html' })
5
+ const clipboardItem = new ClipboardItem({
6
+ [textBlob.type]: textBlob,
7
+ [htmlBlob.type]: htmlBlob,
8
+ })
9
+ return navigator.clipboard.write([clipboardItem])
10
+ }
11
+ const copyCallback = (event: ClipboardEvent) => {
12
+ event.clipboardData?.setData('text/plain', element.outerText)
13
+ event.clipboardData?.setData('text/html', element.outerHTML)
14
+ event.preventDefault()
15
+ }
16
+ document.addEventListener('copy', copyCallback)
17
+ // fall back to deprecated only in non-secure contexts
18
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
19
+ document.execCommand('copy')
20
+ document.removeEventListener('copy', copyCallback)
21
+ }
@@ -0,0 +1,49 @@
1
+ import {
2
+ type AnnotationFeature,
3
+ type TranscriptPartCoding,
4
+ } from '@apollo-annotation/mst'
5
+ import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
6
+
7
+ export function getMinAndMaxPx(
8
+ feature: AnnotationFeature | TranscriptPartCoding,
9
+ refName: string,
10
+ regionNumber: number,
11
+ lgv: LinearGenomeViewModel,
12
+ ): [number, number] | undefined {
13
+ const minPxInfo = lgv.bpToPx({
14
+ refName,
15
+ coord: feature.min,
16
+ regionNumber,
17
+ })
18
+ const maxPxInfo = lgv.bpToPx({
19
+ refName,
20
+ coord: feature.max,
21
+ regionNumber,
22
+ })
23
+ if (minPxInfo === undefined || maxPxInfo === undefined) {
24
+ return
25
+ }
26
+ const { offsetPx } = lgv
27
+ const minPx = minPxInfo.offsetPx - offsetPx
28
+ const maxPx = maxPxInfo.offsetPx - offsetPx
29
+ return [minPx, maxPx]
30
+ }
31
+
32
+ export function getOverlappingEdge(
33
+ feature: AnnotationFeature,
34
+ x: number,
35
+ minMax: [number, number],
36
+ ): { feature: AnnotationFeature; edge: 'min' | 'max' } | undefined {
37
+ const [minPx, maxPx] = minMax
38
+ // Feature is too small to tell if we're overlapping an edge
39
+ if (Math.abs(maxPx - minPx) < 8) {
40
+ return
41
+ }
42
+ if (Math.abs(minPx - x) < 4) {
43
+ return { feature, edge: 'min' }
44
+ }
45
+ if (Math.abs(maxPx - x) < 4) {
46
+ return { feature, edge: 'max' }
47
+ }
48
+ return
49
+ }
package/src/util/index.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { getParent } from 'mobx-state-tree'
2
2
 
3
- import { ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
4
- import { ApolloSessionModel } from '../session'
5
- import { ApolloRootModel } from '../types'
3
+ import { type ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
4
+ import { type ApolloSessionModel } from '../session'
5
+ import { type ApolloRootModel } from '../types'
6
6
 
7
7
  export async function createFetchErrorMessage(
8
8
  response: Response,
@@ -30,3 +30,5 @@ export function getApolloInternetAccount(session: ApolloSessionModel) {
30
30
 
31
31
  export * from './loadAssemblyIntoClient'
32
32
  export * from './annotationFeatureUtils'
33
+ export * from './glyphUtils'
34
+ export * from './mouseEventsUtils'
@@ -1,7 +1,14 @@
1
- import { ClientDataStore, checkRegistry } from '@apollo-annotation/common'
2
- import { ApolloAssemblyI, CheckResultSnapshot } from '@apollo-annotation/mst'
1
+ import { type ClientDataStore, checkRegistry } from '@apollo-annotation/common'
2
+ import {
3
+ type ApolloAssemblyI,
4
+ type CheckResultSnapshot,
5
+ } from '@apollo-annotation/mst'
3
6
  import { gff3ToAnnotationFeature } from '@apollo-annotation/shared'
4
- import gff, { GFF3Comment, GFF3Feature, GFF3Sequence } from '@gmod/gff'
7
+ import gff, {
8
+ type GFF3Comment,
9
+ type GFF3Feature,
10
+ type GFF3Sequence,
11
+ } from '@gmod/gff'
5
12
  import { getSnapshot } from 'mobx-state-tree'
6
13
 
7
14
  export async function loadAssemblyIntoClient(
@@ -0,0 +1,113 @@
1
+ import { type AnnotationFeature } from '@apollo-annotation/mst'
2
+
3
+ type MinEdge = 'min'
4
+ type MaxEdge = 'max'
5
+ export type Edge = MinEdge | MaxEdge
6
+
7
+ interface LocationChange {
8
+ featureId: string
9
+ oldLocation: number
10
+ newLocation: number
11
+ }
12
+
13
+ function expandFeatures(
14
+ feature: AnnotationFeature,
15
+ newLocation: number,
16
+ edge: Edge,
17
+ ): LocationChange[] {
18
+ const featureId = feature._id
19
+ const oldLocation = feature[edge]
20
+ const changes: LocationChange[] = [{ featureId, oldLocation, newLocation }]
21
+ const { parent } = feature
22
+ if (
23
+ parent &&
24
+ ((edge === 'min' && parent[edge] > newLocation) ||
25
+ (edge === 'max' && parent[edge] < newLocation))
26
+ ) {
27
+ changes.push(...expandFeatures(parent, newLocation, edge))
28
+ }
29
+ return changes
30
+ }
31
+
32
+ function shrinkFeatures(
33
+ feature: AnnotationFeature,
34
+ newLocation: number,
35
+ edge: Edge,
36
+ shrinkParent: boolean,
37
+ childIdToSkip?: string,
38
+ ): LocationChange[] {
39
+ const featureId = feature._id
40
+ const oldLocation = feature[edge]
41
+ const changes: LocationChange[] = [{ featureId, oldLocation, newLocation }]
42
+ const { parent, children } = feature
43
+ if (children) {
44
+ for (const [, child] of children) {
45
+ if (child._id === childIdToSkip) {
46
+ continue
47
+ }
48
+ if (
49
+ (edge === 'min' && child[edge] < newLocation) ||
50
+ (edge === 'max' && child[edge] > newLocation)
51
+ ) {
52
+ changes.push(...shrinkFeatures(child, newLocation, edge, shrinkParent))
53
+ }
54
+ }
55
+ }
56
+ if (parent && shrinkParent) {
57
+ const siblings: AnnotationFeature[] = []
58
+ if (parent.children) {
59
+ for (const [, c] of parent.children) {
60
+ if (c._id === featureId) {
61
+ continue
62
+ }
63
+ siblings.push(c)
64
+ }
65
+ }
66
+ if (siblings.length === 0) {
67
+ changes.push(
68
+ ...shrinkFeatures(parent, newLocation, edge, shrinkParent, featureId),
69
+ )
70
+ } else {
71
+ const oldLocation = parent[edge]
72
+ const boundedLocation = Math[edge](
73
+ ...siblings.map((s) => s[edge]),
74
+ newLocation,
75
+ )
76
+ if (boundedLocation !== oldLocation) {
77
+ changes.push(
78
+ ...shrinkFeatures(
79
+ parent,
80
+ boundedLocation,
81
+ edge,
82
+ shrinkParent,
83
+ featureId,
84
+ ),
85
+ )
86
+ }
87
+ }
88
+ }
89
+ return changes
90
+ }
91
+
92
+ export function getPropagatedLocationChanges(
93
+ feature: AnnotationFeature,
94
+ newLocation: number,
95
+ edge: Edge,
96
+ shrinkParent = false,
97
+ ): LocationChange[] {
98
+ const oldLocation = feature[edge]
99
+ if (newLocation === oldLocation) {
100
+ throw new Error(`New and existing locations are the same: "${newLocation}"`)
101
+ }
102
+ if (edge === 'min') {
103
+ if (newLocation > oldLocation) {
104
+ // shrinking feature, may need to shrink children and/or parents
105
+ return shrinkFeatures(feature, newLocation, edge, shrinkParent)
106
+ }
107
+ return expandFeatures(feature, newLocation, edge)
108
+ }
109
+ if (newLocation < oldLocation) {
110
+ return shrinkFeatures(feature, newLocation, edge, shrinkParent)
111
+ }
112
+ return expandFeatures(feature, newLocation, edge)
113
+ }