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

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 (86) hide show
  1. package/dist/index.esm.js +11212 -10483
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +11251 -10509
  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 +7726 -9014
  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 +18 -18
  12. package/src/ApolloInternetAccount/model.ts +123 -70
  13. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +4 -4
  14. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +9 -7
  15. package/src/BackendDrivers/CollaborationServerDriver.ts +72 -20
  16. package/src/BackendDrivers/DesktopFileDriver.ts +2 -2
  17. package/src/ChangeManager.ts +36 -14
  18. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +64 -5
  19. package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -4
  20. package/src/FeatureDetailsWidget/NumberTextField.tsx +5 -2
  21. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +70 -73
  22. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +72 -234
  23. package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +92 -0
  24. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +23 -131
  25. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +50 -194
  26. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +279 -217
  27. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +53 -34
  28. package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -9
  29. package/src/LinearApolloDisplay/glyphs/util.ts +19 -0
  30. package/src/LinearApolloDisplay/stateModel/base.ts +34 -43
  31. package/src/LinearApolloDisplay/stateModel/layouts.ts +3 -2
  32. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +32 -261
  33. package/src/LinearApolloDisplay/stateModel/rendering.ts +43 -343
  34. package/src/LinearApolloReferenceSequenceDisplay/components/LinearApolloReferenceSequenceDisplay.tsx +87 -0
  35. package/src/LinearApolloReferenceSequenceDisplay/components/index.ts +1 -0
  36. package/src/LinearApolloReferenceSequenceDisplay/configSchema.ts +7 -0
  37. package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +181 -0
  38. package/src/LinearApolloReferenceSequenceDisplay/drawSequenceTrack.ts +218 -0
  39. package/src/LinearApolloReferenceSequenceDisplay/index.ts +3 -0
  40. package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +227 -0
  41. package/src/LinearApolloReferenceSequenceDisplay/stateModel/index.ts +25 -0
  42. package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +157 -0
  43. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +101 -38
  44. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +334 -262
  45. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +12 -8
  46. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +42 -4
  47. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +4 -8
  48. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +73 -97
  49. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +49 -61
  50. package/src/TabularEditor/HybridGrid/Feature.tsx +16 -14
  51. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +7 -5
  52. package/src/components/AddAssembly.tsx +34 -38
  53. package/src/components/AddAssemblyAliases.tsx +1 -1
  54. package/src/components/AddChildFeature.tsx +5 -2
  55. package/src/components/AddFeature.tsx +30 -21
  56. package/src/components/AddRefSeqAliases.tsx +64 -50
  57. package/src/components/CopyFeature.tsx +4 -2
  58. package/src/components/CreateApolloAnnotation.tsx +22 -9
  59. package/src/components/DeleteAssembly.tsx +3 -10
  60. package/src/components/DownloadGFF3.tsx +2 -2
  61. package/src/components/EditZoomThresholdDialog.tsx +69 -0
  62. package/src/components/FilterFeatures.tsx +7 -7
  63. package/src/components/FilterTranscripts.tsx +6 -6
  64. package/src/components/ImportFeatures.tsx +1 -1
  65. package/src/components/ManageChecks.tsx +3 -10
  66. package/src/components/ManageUsers.tsx +23 -22
  67. package/src/components/MergeTranscripts.tsx +12 -15
  68. package/src/components/OntologyTermAutocomplete.tsx +1 -8
  69. package/src/components/OntologyTermMultiSelect.tsx +11 -11
  70. package/src/components/OpenLocalFile.tsx +11 -7
  71. package/src/components/ViewChangeLog.tsx +25 -50
  72. package/src/components/ViewCheckResults.tsx +2 -8
  73. package/src/components/index.ts +1 -0
  74. package/src/config.ts +6 -0
  75. package/src/index.ts +53 -115
  76. package/src/makeDisplayComponent.tsx +9 -14
  77. package/src/menus/index.ts +1 -0
  78. package/src/{ApolloInternetAccount/addMenuItems.ts → menus/topLevelMenu.ts} +56 -47
  79. package/src/menus/topLevelMenuAdmin.ts +154 -0
  80. package/src/session/ClientDataStore.ts +32 -14
  81. package/src/session/session.ts +159 -121
  82. package/src/util/annotationFeatureUtils.ts +15 -21
  83. package/src/util/displayUtils.ts +149 -0
  84. package/src/util/glyphUtils.ts +329 -0
  85. package/src/util/loadAssemblyIntoClient.ts +3 -2
  86. package/src/util/mouseEventsUtils.ts +32 -0
@@ -26,6 +26,10 @@ import React, { useEffect, useState } from 'react'
26
26
  import { makeStyles } from 'tss-react/mui'
27
27
 
28
28
  import { type ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
29
+ import {
30
+ type ApolloInternetAccount,
31
+ type CollaborationServerDriver,
32
+ } from '../BackendDrivers'
29
33
  import { type ApolloSessionModel } from '../session'
30
34
  import { type ApolloRootModel } from '../types'
31
35
  import { createFetchErrorMessage } from '../util'
@@ -37,11 +41,6 @@ interface ViewChangeLogProps {
37
41
  handleClose(): void
38
42
  }
39
43
 
40
- interface AssemblyDocument {
41
- _id: string
42
- name: string
43
- }
44
-
45
44
  const useStyles = makeStyles()((theme) => ({
46
45
  changeTextarea: {
47
46
  fontFamily: 'monospace',
@@ -63,12 +62,18 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
63
62
  const { baseURL } = apolloInternetAccount
64
63
  const { classes } = useStyles()
65
64
  const [errorMessage, setErrorMessage] = useState<string>()
66
- const [assemblyCollection, setAssemblyCollection] = useState<
67
- AssemblyDocument[]
68
- >([])
69
- const [assemblyId, setAssemblyId] = useState<string>('')
70
65
  const [displayGridData, setDisplayGridData] = useState<GridRowsProp[]>([])
71
66
 
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))
76
+
72
77
  const gridColumns: GridColDef[] = [
73
78
  { field: 'sequence' },
74
79
  {
@@ -90,7 +95,6 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
90
95
  readOnly
91
96
  />
92
97
  ),
93
- valueFormatter: ({ value }) => JSON.stringify(value),
94
98
  },
95
99
  { field: 'user', headerName: 'User', width: 140 },
96
100
  {
@@ -102,47 +106,17 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
102
106
  },
103
107
  ]
104
108
 
105
- useEffect(() => {
106
- async function getAssemblies() {
107
- const uri = new URL('assemblies', baseURL).href
108
- const apolloFetch = apolloInternetAccount?.getFetcher({
109
- locationType: 'UriLocation',
110
- uri,
111
- })
112
- if (apolloFetch) {
113
- const response = await apolloFetch(uri, { method: 'GET' })
114
- if (!response.ok) {
115
- const newErrorMessage = await createFetchErrorMessage(
116
- response,
117
- 'Error when retrieving assemblies from server',
118
- )
119
- setErrorMessage(newErrorMessage)
120
- return
121
- }
122
- const data = (await response.json()) as AssemblyDocument[]
123
- setAssemblyCollection(data)
124
- }
125
- }
126
- getAssemblies().catch((error) => {
127
- setErrorMessage(String(error))
128
- })
129
- }, [apolloInternetAccount, baseURL])
130
-
131
- useEffect(() => {
132
- if (!assemblyId && assemblyCollection.length > 0) {
133
- setAssemblyId(assemblyCollection[0]._id)
134
- }
135
- }, [assemblyId, assemblyCollection])
136
-
137
109
  useEffect(() => {
138
110
  async function getGridData() {
139
- if (!assemblyId) {
111
+ if (!selectedAssembly) {
140
112
  return
141
113
  }
142
114
 
143
115
  // Get changes
144
116
  const url = new URL('changes', baseURL)
145
- const searchParams = new URLSearchParams({ assembly: assemblyId })
117
+ const searchParams = new URLSearchParams({
118
+ assembly: selectedAssembly.name,
119
+ })
146
120
  url.search = searchParams.toString()
147
121
  const uri = url.toString()
148
122
  const apolloFetch = apolloInternetAccount?.getFetcher({
@@ -168,10 +142,11 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
168
142
  getGridData().catch((error) => {
169
143
  setErrorMessage(String(error))
170
144
  })
171
- }, [assemblyId, apolloInternetAccount, baseURL])
145
+ }, [apolloInternetAccount, baseURL, selectedAssembly])
172
146
 
173
147
  function handleChangeAssembly(e: SelectChangeEvent) {
174
- setAssemblyId(e.target.value)
148
+ const newAssembly = assemblies.find((asm) => asm.name === e.target.value)
149
+ setSelectedAssembly(newAssembly)
175
150
  }
176
151
 
177
152
  return (
@@ -184,12 +159,12 @@ export function ViewChangeLog({ handleClose, session }: ViewChangeLogProps) {
184
159
  >
185
160
  <Select
186
161
  style={{ width: 200, marginLeft: 40 }}
187
- value={assemblyId}
162
+ value={selectedAssembly?.name ?? ''}
188
163
  onChange={handleChangeAssembly}
189
164
  >
190
- {assemblyCollection.map((option) => (
191
- <MenuItem key={option._id} value={option._id}>
192
- {option.name}
165
+ {assemblies.map((option) => (
166
+ <MenuItem key={option.name} value={option.name}>
167
+ {option.displayName || option.name}
193
168
  </MenuItem>
194
169
  ))}
195
170
  </Select>
@@ -4,7 +4,6 @@
4
4
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
5
5
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
6
6
  /* eslint-disable @typescript-eslint/no-unsafe-return */
7
- import { type Assembly } from '@jbrowse/core/assemblyManager/assembly'
8
7
  import {
9
8
  Button,
10
9
  DialogActions,
@@ -49,7 +48,6 @@ export function ViewCheckResults({
49
48
  }
50
49
  const { baseURL } = apolloInternetAccount
51
50
  const [errorMessage, setErrorMessage] = useState<string>()
52
- const [selectedAssembly, setSelectedAssembly] = useState<Assembly>()
53
51
  const [displayGridData, setDisplayGridData] = useState<GridRowsProp[]>([])
54
52
 
55
53
  const gridColumns: GridColDef[] = [
@@ -65,11 +63,7 @@ export function ViewCheckResults({
65
63
  ]
66
64
 
67
65
  const assemblies = collaborationServerDriver.getAssemblies()
68
- useEffect(() => {
69
- if (!selectedAssembly && assemblies.length > 0) {
70
- setSelectedAssembly(assemblies[0])
71
- }
72
- }, [assemblies, selectedAssembly])
66
+ const [selectedAssembly, setSelectedAssembly] = useState(assemblies.at(0))
73
67
 
74
68
  useEffect(() => {
75
69
  async function getGridData() {
@@ -127,7 +121,7 @@ export function ViewCheckResults({
127
121
  >
128
122
  {assemblies.map((option) => (
129
123
  <MenuItem key={option.name} value={option.name}>
130
- {option.displayName ?? option.name}
124
+ {option.displayName}
131
125
  </MenuItem>
132
126
  ))}
133
127
  </Select>
@@ -1,4 +1,5 @@
1
1
  export * from './AddAssembly'
2
+ export * from './AddAssemblyAliases'
2
3
  export * from './AddChildFeature'
3
4
  export * from './AddFeature'
4
5
  export * from './CopyFeature'
package/src/config.ts CHANGED
@@ -15,6 +15,12 @@ const ApolloPluginConfigurationSchema = ConfigurationSchema('ApolloPlugin', {
15
15
  type: 'boolean',
16
16
  defaultValue: false,
17
17
  },
18
+ geneBackgroundColor: {
19
+ description: 'Color for feature background',
20
+ type: 'string',
21
+ defaultValue: 'jexl:geneBackgroundColor(featureType)',
22
+ contextVariable: ['featureType'],
23
+ },
18
24
  })
19
25
 
20
26
  export default ApolloPluginConfigurationSchema
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  CDSCheck,
7
7
  CoreValidation,
8
8
  ParentChildValidation,
9
+ TranscriptCheck,
9
10
  changes,
10
11
  validationRegistry,
11
12
  } from '@apollo-annotation/shared'
@@ -30,6 +31,7 @@ import {
30
31
  } from '@jbrowse/core/util'
31
32
  import { type LinearGenomeViewStateModel } from '@jbrowse/plugin-linear-genome-view'
32
33
  import AddIcon from '@mui/icons-material/Add'
34
+ import { alpha } from '@mui/material'
33
35
 
34
36
  import { version } from '../package.json'
35
37
 
@@ -40,7 +42,6 @@ import {
40
42
  import { installApolloRefNameAliasAdapter } from './ApolloRefNameAliasAdapter'
41
43
  import { installApolloSequenceAdapter } from './ApolloSequenceAdapter'
42
44
  import { installApolloTextSearchAdapter } from './ApolloTextSearchAdapter'
43
- import { type BackendDriver } from './BackendDrivers'
44
45
  import {
45
46
  ApolloFeatureDetailsWidget,
46
47
  ApolloFeatureDetailsWidgetModel,
@@ -51,19 +52,16 @@ import {
51
52
  configSchema as linearApolloDisplayConfigSchema,
52
53
  stateModelFactory as LinearApolloDisplayStateModelFactory,
53
54
  } from './LinearApolloDisplay'
55
+ import {
56
+ LinearApolloReferenceSequenceDisplay,
57
+ configSchema as linearApolloReferenceSequenceDisplayConfigSchema,
58
+ stateModelFactory as LinearApolloReferenceSequenceDisplayStateModelFactory,
59
+ } from './LinearApolloReferenceSequenceDisplay'
54
60
  import {
55
61
  configSchema as linearApolloSixFrameDisplayConfigSchema,
56
62
  stateModelFactory as LinearApolloSixFrameDisplayStateModelFactory,
57
63
  } from './LinearApolloSixFrameDisplay'
58
- import {
59
- AddFeature,
60
- DownloadGFF3,
61
- LogOut,
62
- ManageChecks,
63
- OpenLocalFile,
64
- ViewChangeLog,
65
- ViewCheckResults,
66
- } from './components'
64
+ import { AddFeature } from './components'
67
65
  import ApolloPluginConfigurationSchema from './config'
68
66
  import {
69
67
  annotationFromJBrowseFeature,
@@ -73,6 +71,7 @@ import {
73
71
  LinearApolloDisplayComponent,
74
72
  LinearApolloSixFrameDisplayComponent,
75
73
  } from './makeDisplayComponent'
74
+ import { addTopLevelMenus } from './menus'
76
75
  import { type ApolloSessionModel, extendSession } from './session'
77
76
 
78
77
  interface RpcHandle {
@@ -106,6 +105,10 @@ for (const [changeName, change] of Object.entries(changes)) {
106
105
 
107
106
  const cdsCheck = new CDSCheck()
108
107
  checkRegistry.registerCheck(cdsCheck.name, cdsCheck)
108
+
109
+ const transcriptCheck = new TranscriptCheck()
110
+ checkRegistry.registerCheck(transcriptCheck.name, transcriptCheck)
111
+
109
112
  validationRegistry.registerValidation(new CoreValidation())
110
113
  validationRegistry.registerValidation(new ParentChildValidation())
111
114
 
@@ -201,6 +204,22 @@ export default class ApolloPlugin extends Plugin {
201
204
  })
202
205
  })
203
206
 
207
+ pluginManager.addDisplayType(() => {
208
+ const configSchema = linearApolloReferenceSequenceDisplayConfigSchema
209
+ return new DisplayType({
210
+ name: 'LinearApolloReferenceSequenceDisplay',
211
+ configSchema,
212
+ stateModel: LinearApolloReferenceSequenceDisplayStateModelFactory(
213
+ pluginManager,
214
+ configSchema,
215
+ ),
216
+ displayName: 'Apollo reference sequence display',
217
+ trackType: 'ReferenceSequenceTrack',
218
+ viewType: 'LinearGenomeView',
219
+ ReactComponent: LinearApolloReferenceSequenceDisplay,
220
+ })
221
+ })
222
+
204
223
  pluginManager.addToExtensionPoint(
205
224
  'Core-extendSession',
206
225
  // @ts-expect-error not sure how to deal with snapshot model types
@@ -289,9 +308,10 @@ export default class ApolloPlugin extends Plugin {
289
308
  if (!dataStore) {
290
309
  break
291
310
  }
292
- const backendDriver = dataStore.getBackendDriver(
293
- assemblyName,
294
- ) as BackendDriver
311
+ const backendDriver = dataStore.getBackendDriver(assemblyName)
312
+ if (!backendDriver) {
313
+ break
314
+ }
295
315
  const { seq: sequence } =
296
316
  await backendDriver.getSequence(region)
297
317
  handle.workers[0].postMessage({
@@ -311,9 +331,10 @@ export default class ApolloPlugin extends Plugin {
311
331
  if (!dataStore) {
312
332
  break
313
333
  }
314
- const backendDriver = dataStore.getBackendDriver(
315
- assembly,
316
- ) as BackendDriver
334
+ const backendDriver = dataStore.getBackendDriver(assembly)
335
+ if (!backendDriver) {
336
+ break
337
+ }
317
338
  const regions = await backendDriver.getRegions(assembly)
318
339
  handle.workers[0].postMessage({
319
340
  apollo,
@@ -332,9 +353,10 @@ export default class ApolloPlugin extends Plugin {
332
353
  if (!dataStore) {
333
354
  break
334
355
  }
335
- const backendDriver = dataStore.getBackendDriver(
336
- assembly,
337
- ) as BackendDriver
356
+ const backendDriver = dataStore.getBackendDriver(assembly)
357
+ if (!backendDriver) {
358
+ break
359
+ }
338
360
  const refNameAliases =
339
361
  await backendDriver.getRefNameAliases(assembly)
340
362
  handle.workers[0].postMessage({
@@ -357,103 +379,19 @@ export default class ApolloPlugin extends Plugin {
357
379
 
358
380
  configure(pluginManager: PluginManager) {
359
381
  if (isAbstractMenuManager(pluginManager.rootModel)) {
360
- pluginManager.rootModel.appendToMenu('Apollo', {
361
- label: 'Download GFF3',
362
- onClick: (session: ApolloSessionModel) => {
363
- ;(session as unknown as AbstractSessionModel).queueDialog(
364
- (doneCallback) => [
365
- DownloadGFF3,
366
- {
367
- session,
368
- handleClose: () => {
369
- doneCallback()
370
- },
371
- },
372
- ],
373
- )
374
- },
375
- })
376
- pluginManager.rootModel.appendToMenu('Apollo', {
377
- label: 'Manage Checks',
378
- onClick: (session: ApolloSessionModel) => {
379
- ;(session as unknown as AbstractSessionModel).queueDialog(
380
- (doneCallback) => [
381
- ManageChecks,
382
- {
383
- session,
384
- handleClose: () => {
385
- doneCallback()
386
- },
387
- },
388
- ],
389
- )
390
- },
391
- })
392
- pluginManager.rootModel.appendToMenu('Apollo', {
393
- label: 'View Change Log',
394
- onClick: (session: ApolloSessionModel) => {
395
- ;(session as unknown as AbstractSessionModel).queueDialog(
396
- (doneCallback) => [
397
- ViewChangeLog,
398
- {
399
- session,
400
- handleClose: () => {
401
- doneCallback()
402
- },
403
- },
404
- ],
405
- )
406
- },
407
- })
408
- pluginManager.rootModel.appendToMenu('Apollo', {
409
- label: 'Open local GFF3 file',
410
- onClick: (session: ApolloSessionModel) => {
411
- ;(session as unknown as AbstractSessionModel).queueDialog(
412
- (doneCallback) => [
413
- OpenLocalFile,
414
- {
415
- session,
416
- handleClose: () => {
417
- doneCallback()
418
- },
419
- inMemoryFileDriver: session.apolloDataStore.inMemoryFileDriver,
420
- },
421
- ],
422
- )
423
- },
424
- })
425
- pluginManager.rootModel.appendToMenu('Apollo', {
426
- label: 'View check results',
427
- onClick: (session: ApolloSessionModel) => {
428
- ;(session as unknown as AbstractSessionModel).queueDialog(
429
- (doneCallback) => [
430
- ViewCheckResults,
431
- {
432
- session,
433
- handleClose: () => {
434
- doneCallback()
435
- },
436
- },
437
- ],
438
- )
439
- },
440
- })
441
- pluginManager.rootModel.appendToMenu('Apollo', {
442
- label: 'Log out',
443
- onClick: (session: ApolloSessionModel) => {
444
- ;(session as unknown as AbstractSessionModel).queueDialog(
445
- (doneCallback) => [
446
- LogOut,
447
- {
448
- session,
449
- handleClose: () => {
450
- doneCallback()
451
- },
452
- },
453
- ],
454
- )
382
+ pluginManager.jexl.addFunction(
383
+ 'geneBackgroundColor',
384
+ (featureType: string) => {
385
+ if (featureType === 'pseudogene') {
386
+ return alpha('rgb(148, 203, 236)', 0.6)
387
+ }
388
+ if (featureType === 'ncRNA_gene') {
389
+ return alpha('rgb(194, 106, 119)', 0.6)
390
+ }
391
+ return
455
392
  },
456
- })
393
+ )
394
+ addTopLevelMenus(pluginManager.rootModel)
457
395
  }
458
396
  }
459
397
  }
@@ -19,7 +19,6 @@ const accordionControlHeight = 12
19
19
  const useStyles = makeStyles()((theme) => ({
20
20
  shading: {
21
21
  background: alpha(theme.palette.primary.main, 0.2),
22
- overflowY: 'scroll',
23
22
  overflowX: 'hidden',
24
23
  },
25
24
  details: {
@@ -88,25 +87,21 @@ const ResizeHandle = ({
88
87
  },
89
88
  [onResize],
90
89
  )
91
- const cancelDrag: (event: MouseEvent) => void = useCallback(
92
- (event: MouseEvent) => {
93
- event.stopPropagation()
94
- event.preventDefault()
95
- globalThis.removeEventListener('mousemove', mouseMove)
96
- globalThis.removeEventListener('mouseup', cancelDrag)
97
- globalThis.removeEventListener('mouseleave', cancelDrag)
98
- },
99
- [mouseMove],
100
- )
90
+
101
91
  return (
102
92
  // TODO: a11y
103
93
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
104
94
  <div
105
95
  onMouseDown={(event: React.MouseEvent) => {
106
96
  event.stopPropagation()
107
- globalThis.addEventListener('mousemove', mouseMove)
108
- globalThis.addEventListener('mouseup', cancelDrag)
109
- globalThis.addEventListener('mouseleave', cancelDrag)
97
+ const controller = new AbortController()
98
+ const { signal } = controller
99
+ function abortDrag() {
100
+ controller.abort()
101
+ }
102
+ globalThis.addEventListener('mousemove', mouseMove, { signal })
103
+ globalThis.addEventListener('mouseup', abortDrag, { signal })
104
+ globalThis.addEventListener('mouseleave', abortDrag, { signal })
110
105
  }}
111
106
  onClick={(e) => {
112
107
  e.stopPropagation()
@@ -0,0 +1 @@
1
+ export { addTopLevelMenus } from './topLevelMenu'
@@ -2,130 +2,139 @@ import {
2
2
  type AbstractMenuManager,
3
3
  type AbstractSessionModel,
4
4
  } from '@jbrowse/core/util'
5
+ import DownloadIcon from '@mui/icons-material/Download'
6
+ import FactCheckIcon from '@mui/icons-material/FactCheck'
7
+ import FileOpenIcon from '@mui/icons-material/FileOpen'
8
+ import LogoutIcon from '@mui/icons-material/Logout'
9
+ import RedoIcon from '@mui/icons-material/Redo'
10
+ import TrackChangesIcon from '@mui/icons-material/TrackChanges'
11
+ import UndoIcon from '@mui/icons-material/Undo'
5
12
 
6
13
  import {
7
- AddAssembly,
8
- AddRefSeqAliases,
9
- DeleteAssembly,
10
- ImportFeatures,
11
- ManageUsers,
14
+ DownloadGFF3,
15
+ LogOut,
16
+ OpenLocalFile,
17
+ ViewChangeLog,
18
+ ViewCheckResults,
12
19
  } from '../components'
13
- import { AddAssemblyAliases } from '../components/AddAssemblyAliases'
14
20
  import { type ApolloSessionModel } from '../session'
15
21
 
16
- export function addMenuItems(rootModel: AbstractMenuManager) {
22
+ export function addTopLevelMenus(rootModel: AbstractMenuManager) {
23
+ rootModel.insertInMenu(
24
+ 'Apollo',
25
+ {
26
+ label: 'Redo',
27
+ icon: RedoIcon,
28
+ onClick(session: ApolloSessionModel) {
29
+ const { apolloDataStore } = session
30
+ void apolloDataStore.changeManager.redoLastChange()
31
+ },
32
+ },
33
+ 0,
34
+ )
35
+ rootModel.insertInMenu(
36
+ 'Apollo',
37
+ {
38
+ label: 'Undo',
39
+ icon: UndoIcon,
40
+ onClick(session: ApolloSessionModel) {
41
+ const { apolloDataStore } = session
42
+ void apolloDataStore.changeManager.undoLastChange()
43
+ },
44
+ },
45
+ 0,
46
+ )
47
+
17
48
  rootModel.appendToMenu('Apollo', {
18
- label: 'Add Assembly',
49
+ label: 'Download GFF3',
50
+ icon: DownloadIcon,
19
51
  onClick: (session: ApolloSessionModel) => {
20
52
  ;(session as unknown as AbstractSessionModel).queueDialog(
21
53
  (doneCallback) => [
22
- AddAssembly,
54
+ DownloadGFF3,
23
55
  {
24
56
  session,
25
57
  handleClose: () => {
26
58
  doneCallback()
27
59
  },
28
- changeManager: session.apolloDataStore.changeManager,
29
60
  },
30
61
  ],
31
62
  )
32
63
  },
33
64
  })
34
65
  rootModel.appendToMenu('Apollo', {
35
- label: 'Delete Assembly',
66
+ label: 'View Change Log',
67
+ icon: TrackChangesIcon,
36
68
  onClick: (session: ApolloSessionModel) => {
37
69
  ;(session as unknown as AbstractSessionModel).queueDialog(
38
70
  (doneCallback) => [
39
- DeleteAssembly,
71
+ ViewChangeLog,
40
72
  {
41
73
  session,
42
74
  handleClose: () => {
43
75
  doneCallback()
44
76
  },
45
- changeManager: session.apolloDataStore.changeManager,
46
77
  },
47
78
  ],
48
79
  )
49
80
  },
50
81
  })
51
82
  rootModel.appendToMenu('Apollo', {
52
- label: 'Import Features',
83
+ label: 'Open local GFF3 file',
84
+ icon: FileOpenIcon,
53
85
  onClick: (session: ApolloSessionModel) => {
54
86
  ;(session as unknown as AbstractSessionModel).queueDialog(
55
87
  (doneCallback) => [
56
- ImportFeatures,
88
+ OpenLocalFile,
57
89
  {
58
90
  session,
59
91
  handleClose: () => {
60
92
  doneCallback()
61
93
  },
62
- changeManager: session.apolloDataStore.changeManager,
94
+ inMemoryFileDriver: session.apolloDataStore.inMemoryFileDriver,
63
95
  },
64
96
  ],
65
97
  )
66
98
  },
67
99
  })
68
100
  rootModel.appendToMenu('Apollo', {
69
- label: 'Add reference sequence aliases',
101
+ label: 'View check results',
102
+ icon: FactCheckIcon,
70
103
  onClick: (session: ApolloSessionModel) => {
71
104
  ;(session as unknown as AbstractSessionModel).queueDialog(
72
105
  (doneCallback) => [
73
- AddRefSeqAliases,
106
+ ViewCheckResults,
74
107
  {
75
108
  session,
76
109
  handleClose: () => {
77
110
  doneCallback()
78
111
  },
79
- changeManager: session.apolloDataStore.changeManager,
80
112
  },
81
113
  ],
82
114
  )
83
115
  },
84
116
  })
85
117
  rootModel.appendToMenu('Apollo', {
86
- label: 'Add Assembly aliases',
118
+ label: 'Lock/Unlock session',
87
119
  onClick: (session: ApolloSessionModel) => {
88
- ;(session as unknown as AbstractSessionModel).queueDialog(
89
- (doneCallback) => [
90
- AddAssemblyAliases,
91
- {
92
- session,
93
- handleClose: () => {
94
- doneCallback()
95
- },
96
- changeManager: session.apolloDataStore.changeManager,
97
- },
98
- ],
99
- )
120
+ session.toggleLocked()
100
121
  },
101
122
  })
102
123
  rootModel.appendToMenu('Apollo', {
103
- label: 'Manage Users',
124
+ label: 'Log out',
125
+ icon: LogoutIcon,
104
126
  onClick: (session: ApolloSessionModel) => {
105
127
  ;(session as unknown as AbstractSessionModel).queueDialog(
106
128
  (doneCallback) => [
107
- ManageUsers,
129
+ LogOut,
108
130
  {
109
131
  session,
110
132
  handleClose: () => {
111
133
  doneCallback()
112
134
  },
113
- changeManager: session.apolloDataStore.changeManager,
114
135
  },
115
136
  ],
116
137
  )
117
138
  },
118
139
  })
119
- rootModel.appendToMenu('Apollo', {
120
- label: 'Undo',
121
- onClick: (session: ApolloSessionModel) => {
122
- const { apolloDataStore } = session
123
- const { notify } = session as unknown as AbstractSessionModel
124
- if (apolloDataStore.changeManager.recentChanges.length > 0) {
125
- void apolloDataStore.changeManager.revertLastChange()
126
- } else {
127
- notify('No changes to undo', 'info')
128
- }
129
- },
130
- })
131
140
  }