@apollo-annotation/jbrowse-plugin-apollo 0.1.20 → 0.2.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 (61) hide show
  1. package/dist/index.esm.js +552 -642
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +560 -650
  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 +11294 -1232
  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 -5
  12. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +4 -2
  13. package/src/ApolloInternetAccount/configSchema.ts +1 -1
  14. package/src/ApolloInternetAccount/model.ts +5 -10
  15. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +1 -1
  16. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +4 -5
  17. package/src/BackendDrivers/DesktopFileDriver.ts +3 -2
  18. package/src/FeatureDetailsWidget/Attributes.tsx +1 -6
  19. package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -0
  20. package/src/FeatureDetailsWidget/StringTextField.tsx +1 -0
  21. package/src/FeatureDetailsWidget/TranscriptBasic.tsx +131 -382
  22. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +209 -284
  23. package/src/FeatureDetailsWidget/model.ts +4 -4
  24. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +1 -4
  25. package/src/LinearApolloDisplay/configSchema.ts +5 -14
  26. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +25 -3
  27. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +95 -32
  28. package/src/LinearApolloDisplay/index.ts +1 -1
  29. package/src/LinearApolloDisplay/stateModel/base.ts +104 -17
  30. package/src/LinearApolloDisplay/stateModel/index.ts +1 -1
  31. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +1 -1
  32. package/src/LinearApolloDisplay/stateModel/rendering.ts +1 -1
  33. package/src/OntologyManager/OntologyStore/fulltext.ts +5 -2
  34. package/src/OntologyManager/OntologyStore/index.ts +25 -22
  35. package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +8 -3
  36. package/src/OntologyManager/index.ts +31 -8
  37. package/src/SixFrameFeatureDisplay/stateModel.ts +1 -1
  38. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +1 -0
  39. package/src/TabularEditor/HybridGrid/NumberCell.tsx +1 -0
  40. package/src/TabularEditor/model.ts +1 -1
  41. package/src/components/AddChildFeature.tsx +1 -0
  42. package/src/components/AddFeature.tsx +1 -1
  43. package/src/components/AddRefSeqAliases.tsx +1 -0
  44. package/src/components/CopyFeature.tsx +1 -0
  45. package/src/components/DeleteAssembly.tsx +1 -0
  46. package/src/components/DeleteFeature.tsx +1 -0
  47. package/src/components/LogOut.tsx +2 -1
  48. package/src/components/ManageChecks.tsx +1 -1
  49. package/src/components/ManageUsers.tsx +2 -1
  50. package/src/components/OntologyTermAutocomplete.tsx +7 -9
  51. package/src/components/OntologyTermMultiSelect.tsx +2 -1
  52. package/src/components/OpenLocalFile.tsx +3 -1
  53. package/src/components/ViewChangeLog.tsx +1 -0
  54. package/src/components/ViewCheckResults.tsx +1 -0
  55. package/src/config.ts +5 -0
  56. package/src/extensions/annotationFromPileup.ts +1 -1
  57. package/src/index.ts +2 -2
  58. package/src/makeDisplayComponent.tsx +77 -32
  59. package/src/session/ClientDataStore.ts +1 -1
  60. package/src/session/session.ts +2 -1
  61. package/src/LinearApolloDisplay/stateModel/trackHeightMixin.ts +0 -43
@@ -2,7 +2,11 @@ import { AnnotationFeature } from '@apollo-annotation/mst'
2
2
  import { Theme, alpha } from '@mui/material'
3
3
  import { MenuItem } from '@jbrowse/core/ui'
4
4
 
5
- import { AbstractSessionModel, SessionWithWidgets } from '@jbrowse/core/util'
5
+ import {
6
+ AbstractSessionModel,
7
+ isSessionModelWithWidgets,
8
+ SessionWithWidgets,
9
+ } from '@jbrowse/core/util'
6
10
 
7
11
  import {
8
12
  AddChildFeature,
@@ -175,7 +179,7 @@ function drawTooltip(
175
179
  if (!position) {
176
180
  return
177
181
  }
178
- const { layoutIndex, layoutRow } = position
182
+ const { featureRow, layoutIndex, layoutRow } = position
179
183
  const { bpPerPx, displayedRegions, offsetPx } = lgv
180
184
  const displayedRegion = displayedRegions[layoutIndex]
181
185
  const { refName, reversed } = displayedRegion
@@ -191,7 +195,7 @@ function drawTooltip(
191
195
  coord: reversed ? max : min,
192
196
  regionNumber: layoutIndex,
193
197
  })?.offsetPx ?? 0) - offsetPx
194
- const top = layoutRow * apolloRowHeight
198
+ const top = (layoutRow + featureRow) * apolloRowHeight
195
199
  const widthPx = length / bpPerPx
196
200
 
197
201
  const featureType = `Type: ${feature.type}`
@@ -385,6 +389,24 @@ function getContextMenuItems(
385
389
  },
386
390
  },
387
391
  )
392
+ if (sourceFeature.type === 'mRNA' && isSessionModelWithWidgets(session)) {
393
+ menuItems.push({
394
+ label: 'Edit transcript details',
395
+ onClick: () => {
396
+ const apolloTranscriptWidget = session.addWidget(
397
+ 'ApolloTranscriptDetails',
398
+ 'apolloTranscriptDetails',
399
+ {
400
+ feature: sourceFeature,
401
+ assembly: currentAssemblyId,
402
+ changeManager,
403
+ refName: region.refName,
404
+ },
405
+ )
406
+ session.showWidget(apolloTranscriptWidget)
407
+ },
408
+ })
409
+ }
388
410
  return menuItems
389
411
  }
390
412
 
@@ -13,35 +13,49 @@ import { Glyph } from './Glyph'
13
13
  import { boxGlyph } from './BoxGlyph'
14
14
  import { LinearApolloDisplayRendering } from '../stateModel/rendering'
15
15
 
16
- let forwardFill: CanvasPattern | null = null
17
- let backwardFill: CanvasPattern | null = null
18
- if ('document' in window) {
16
+ let forwardFillLight: CanvasPattern | null = null
17
+ let backwardFillLight: CanvasPattern | null = null
18
+ let forwardFillDark: CanvasPattern | null = null
19
+ let backwardFillDark: CanvasPattern | null = null
20
+ if ('document' in globalThis) {
19
21
  for (const direction of ['forward', 'backward']) {
20
- const canvas = document.createElement('canvas')
21
- const canvasSize = 10
22
- canvas.width = canvas.height = canvasSize
23
- const ctx = canvas.getContext('2d')
24
- if (ctx) {
25
- const stripeColor1 = 'rgba(0,0,0,0)'
26
- const stripeColor2 = 'rgba(255,255,255,0.25)'
27
- const gradient =
28
- direction === 'forward'
29
- ? ctx.createLinearGradient(0, canvasSize, canvasSize, 0)
30
- : ctx.createLinearGradient(0, 0, canvasSize, canvasSize)
31
- gradient.addColorStop(0, stripeColor1)
32
- gradient.addColorStop(0.25, stripeColor1)
33
- gradient.addColorStop(0.25, stripeColor2)
34
- gradient.addColorStop(0.5, stripeColor2)
35
- gradient.addColorStop(0.5, stripeColor1)
36
- gradient.addColorStop(0.75, stripeColor1)
37
- gradient.addColorStop(0.75, stripeColor2)
38
- gradient.addColorStop(1, stripeColor2)
39
- ctx.fillStyle = gradient
40
- ctx.fillRect(0, 0, 10, 10)
41
- if (direction === 'forward') {
42
- forwardFill = ctx.createPattern(canvas, 'repeat')
43
- } else {
44
- backwardFill = ctx.createPattern(canvas, 'repeat')
22
+ for (const themeMode of ['light', 'dark']) {
23
+ const canvas = document.createElement('canvas')
24
+ const canvasSize = 10
25
+ canvas.width = canvas.height = canvasSize
26
+ const ctx = canvas.getContext('2d')
27
+ if (ctx) {
28
+ const stripeColor1 =
29
+ themeMode === 'light' ? 'rgba(0,0,0,0)' : 'rgba(0,0,0,0.75)'
30
+ const stripeColor2 =
31
+ themeMode === 'light' ? 'rgba(255,255,255,0.25)' : 'rgba(0,0,0,0.50)'
32
+ const gradient =
33
+ direction === 'forward'
34
+ ? ctx.createLinearGradient(0, canvasSize, canvasSize, 0)
35
+ : ctx.createLinearGradient(0, 0, canvasSize, canvasSize)
36
+ gradient.addColorStop(0, stripeColor1)
37
+ gradient.addColorStop(0.25, stripeColor1)
38
+ gradient.addColorStop(0.25, stripeColor2)
39
+ gradient.addColorStop(0.5, stripeColor2)
40
+ gradient.addColorStop(0.5, stripeColor1)
41
+ gradient.addColorStop(0.75, stripeColor1)
42
+ gradient.addColorStop(0.75, stripeColor2)
43
+ gradient.addColorStop(1, stripeColor2)
44
+ ctx.fillStyle = gradient
45
+ ctx.fillRect(0, 0, 10, 10)
46
+ if (direction === 'forward') {
47
+ if (themeMode === 'light') {
48
+ forwardFillLight = ctx.createPattern(canvas, 'repeat')
49
+ } else {
50
+ forwardFillDark = ctx.createPattern(canvas, 'repeat')
51
+ }
52
+ } else {
53
+ if (themeMode === 'light') {
54
+ backwardFillLight = ctx.createPattern(canvas, 'repeat')
55
+ } else {
56
+ backwardFillDark = ctx.createPattern(canvas, 'repeat')
57
+ }
58
+ }
45
59
  }
46
60
  }
47
61
  }
@@ -61,13 +75,34 @@ function draw(
61
75
  const rowHeight = apolloRowHeight
62
76
  const exonHeight = Math.round(0.6 * rowHeight)
63
77
  const cdsHeight = Math.round(0.9 * rowHeight)
64
- const { strand } = feature
65
- const { children } = feature
78
+ const { children, min, strand } = feature
66
79
  if (!children) {
67
80
  return
68
81
  }
69
82
  const { apolloSelectedFeature } = session
70
83
 
84
+ // Draw background for gene
85
+ const topLevelFeatureMinX =
86
+ (lgv.bpToPx({
87
+ refName,
88
+ coord: min,
89
+ regionNumber: displayedRegionIndex,
90
+ })?.offsetPx ?? 0) - offsetPx
91
+ const topLevelFeatureWidthPx = feature.length / bpPerPx
92
+ const topLevelFeatureStartPx = reversed
93
+ ? topLevelFeatureMinX - topLevelFeatureWidthPx
94
+ : topLevelFeatureMinX
95
+ const topLevelFeatureTop = row * rowHeight
96
+ const topLevelFeatureHeight = getRowCount(feature) * rowHeight
97
+
98
+ ctx.fillStyle = alpha(theme?.palette.background.paper ?? '#ffffff', 0.6)
99
+ ctx.fillRect(
100
+ topLevelFeatureStartPx,
101
+ topLevelFeatureTop,
102
+ topLevelFeatureWidthPx,
103
+ topLevelFeatureHeight,
104
+ )
105
+
71
106
  // Draw lines on different rows for each mRNA
72
107
  let currentRow = 0
73
108
  for (const [, mrna] of children) {
@@ -102,6 +137,10 @@ function draw(
102
137
  }
103
138
  }
104
139
 
140
+ const forwardFill =
141
+ theme?.palette.mode === 'dark' ? forwardFillDark : forwardFillLight
142
+ const backwardFill =
143
+ theme?.palette.mode === 'dark' ? backwardFillDark : backwardFillLight
105
144
  // Draw exon and CDS for each mRNA
106
145
  currentRow = 0
107
146
  for (const [, child] of children) {
@@ -289,11 +328,35 @@ function getFeatureFromLayout(
289
328
  bp: number,
290
329
  row: number,
291
330
  ): AnnotationFeature | undefined {
292
- const featureInThisRow: AnnotationFeature[] = featuresForRow(feature)[row]
331
+ const featureInThisRow: AnnotationFeature[] =
332
+ featuresForRow(feature)[row] || []
293
333
  for (const f of featureInThisRow) {
334
+ let featureObj
294
335
  if (bp >= f.min && bp <= f.max && f.parent) {
295
- return f
336
+ featureObj = f
337
+ }
338
+ if (!featureObj) {
339
+ continue
340
+ }
341
+ if (
342
+ featureObj.type === 'CDS' &&
343
+ featureObj.parent &&
344
+ featureObj.parent.type === 'mRNA'
345
+ ) {
346
+ const { cdsLocations } = featureObj.parent
347
+ for (const cdsLoc of cdsLocations) {
348
+ for (const loc of cdsLoc) {
349
+ if (bp >= loc.min && bp <= loc.max) {
350
+ return featureObj
351
+ }
352
+ }
353
+ }
354
+
355
+ // If mouse position is in the intron region, return the mRNA
356
+ return featureObj.parent
296
357
  }
358
+ // If mouse position is in a feature that is not a CDS, return the feature
359
+ return featureObj
297
360
  }
298
361
  return feature
299
362
  }
@@ -1,2 +1,2 @@
1
- export { configSchemaFactory } from './configSchema'
1
+ export { configSchema } from './configSchema'
2
2
  export { stateModelFactory } from './stateModel'
@@ -22,29 +22,27 @@ import { addDisposer, getRoot, types } from 'mobx-state-tree'
22
22
  import { ApolloInternetAccountModel } from '../../ApolloInternetAccount/model'
23
23
  import { ApolloSessionModel } from '../../session'
24
24
  import { ApolloRootModel } from '../../types'
25
- import { TrackHeightMixin } from './trackHeightMixin'
25
+
26
+ const minDisplayHeight = 20
26
27
 
27
28
  export function baseModelFactory(
28
29
  _pluginManager: PluginManager,
29
30
  configSchema: AnyConfigurationSchemaType,
30
31
  ) {
31
- // TODO: Restore this when TRackHeightMixin is in LGV runtime exports
32
-
33
- // const LGVPlugin = pluginManager.getPlugin(
34
- // 'LinearGenomeViewPlugin',
35
- // ) as LinearGenomeViewPlugin
36
- // const { TrackHeightMixin } = LGVPlugin.exports
37
-
38
- return types
39
- .compose(BaseDisplay, TrackHeightMixin)
40
- .named('BaseLinearApolloDisplay')
32
+ return BaseDisplay.named('BaseLinearApolloDisplay')
41
33
  .props({
42
34
  type: types.literal('LinearApolloDisplay'),
43
35
  configuration: ConfigurationReference(configSchema),
36
+ graphical: true,
37
+ table: false,
38
+ heightPreConfig: types.maybe(
39
+ types.refinement(
40
+ 'displayHeight',
41
+ types.number,
42
+ (n) => n >= minDisplayHeight,
43
+ ),
44
+ ),
44
45
  })
45
- .volatile((self) => ({
46
- lgv: getContainingView(self) as unknown as LinearGenomeViewModel,
47
- }))
48
46
  .views((self) => {
49
47
  const { configuration, renderProps: superRenderProps } = self
50
48
  return {
@@ -57,6 +55,26 @@ export function baseModelFactory(
57
55
  },
58
56
  }
59
57
  })
58
+ .volatile(() => ({
59
+ scrollTop: 0,
60
+ }))
61
+ .views((self) => ({
62
+ get lgv() {
63
+ return getContainingView(self) as unknown as LinearGenomeViewModel
64
+ },
65
+ get height() {
66
+ if (self.heightPreConfig) {
67
+ return self.heightPreConfig
68
+ }
69
+ if (self.graphical && self.table) {
70
+ return 500
71
+ }
72
+ if (self.graphical) {
73
+ return 200
74
+ }
75
+ return 300
76
+ },
77
+ }))
60
78
  .views((self) => ({
61
79
  get rendererTypeName() {
62
80
  return self.configuration.renderer.type
@@ -119,6 +137,73 @@ export function baseModelFactory(
119
137
  .apolloSelectedFeature
120
138
  },
121
139
  }))
140
+ .actions((self) => ({
141
+ setScrollTop(scrollTop: number) {
142
+ self.scrollTop = scrollTop
143
+ },
144
+ setHeight(displayHeight: number) {
145
+ self.heightPreConfig = Math.max(displayHeight, minDisplayHeight)
146
+ return self.height
147
+ },
148
+ resizeHeight(distance: number) {
149
+ const oldHeight = self.height
150
+ const newHeight = this.setHeight(self.height + distance)
151
+ return newHeight - oldHeight
152
+ },
153
+ showGraphicalOnly() {
154
+ self.graphical = true
155
+ self.table = false
156
+ },
157
+ showTableOnly() {
158
+ self.graphical = false
159
+ self.table = true
160
+ },
161
+ showGraphicalAndTable() {
162
+ self.graphical = true
163
+ self.table = true
164
+ },
165
+ }))
166
+ .views((self) => {
167
+ const { trackMenuItems: superTrackMenuItems } = self
168
+ return {
169
+ trackMenuItems() {
170
+ const { graphical, table } = self
171
+ return [
172
+ ...superTrackMenuItems(),
173
+ {
174
+ type: 'subMenu',
175
+ label: 'Appearance',
176
+ subMenu: [
177
+ {
178
+ label: 'Show graphical display',
179
+ type: 'radio',
180
+ checked: graphical && !table,
181
+ onClick: () => {
182
+ self.showGraphicalOnly()
183
+ },
184
+ },
185
+ {
186
+ label: 'Show table display',
187
+ type: 'radio',
188
+ checked: table && !graphical,
189
+ onClick: () => {
190
+ self.showTableOnly()
191
+ },
192
+ },
193
+ {
194
+ label: 'Show both graphical and table display',
195
+ type: 'radio',
196
+ checked: table && graphical,
197
+ onClick: () => {
198
+ self.showGraphicalAndTable()
199
+ },
200
+ },
201
+ ],
202
+ },
203
+ ]
204
+ },
205
+ }
206
+ })
122
207
  .actions((self) => ({
123
208
  setSelectedFeature(feature?: AnnotationFeature) {
124
209
  ;(
@@ -136,9 +221,11 @@ export function baseModelFactory(
136
221
  void (
137
222
  self.session as unknown as ApolloSessionModel
138
223
  ).apolloDataStore.loadFeatures(self.regions)
139
- void (
140
- self.session as unknown as ApolloSessionModel
141
- ).apolloDataStore.loadRefSeq(self.regions)
224
+ if (self.lgv.bpPerPx <= 3) {
225
+ void (
226
+ self.session as unknown as ApolloSessionModel
227
+ ).apolloDataStore.loadRefSeq(self.regions)
228
+ }
142
229
  },
143
230
  { name: 'LinearApolloDisplayLoadFeatures', delay: 1000 },
144
231
  ),
@@ -19,6 +19,6 @@ export function stateModelFactory(
19
19
  export type LinearApolloDisplayStateModel = ReturnType<typeof stateModelFactory>
20
20
  // eslint disable because of
21
21
  // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
22
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
22
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
23
23
  export interface LinearApolloDisplay
24
24
  extends Instance<LinearApolloDisplayStateModel> {}
@@ -499,6 +499,6 @@ export type LinearApolloDisplayMouseEventsModel = ReturnType<
499
499
  >
500
500
  // eslint disable because of
501
501
  // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
502
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
502
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
503
503
  export interface LinearApolloDisplayMouseEvents
504
504
  extends Instance<LinearApolloDisplayMouseEventsModel> {}
@@ -445,6 +445,6 @@ export type LinearApolloDisplayRenderingModel = ReturnType<
445
445
  >
446
446
  // eslint disable because of
447
447
  // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
448
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
448
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
449
449
  export interface LinearApolloDisplayRendering
450
450
  extends Instance<LinearApolloDisplayRenderingModel> {}
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-return */
3
3
  // jsonpath triggers this rule for some reason. import { query } from 'jsonpath' does not work
4
4
 
5
- import { checkAbortSignal } from '@jbrowse/core/util'
5
+ import { checkAbortSignal } from '@jbrowse/core/util/aborting'
6
6
  import jsonpath from 'jsonpath'
7
7
 
8
8
  import { stopwords } from './fulltext-stopwords'
@@ -170,7 +170,10 @@ export function elaborateMatch(
170
170
  const sortedWordIndexes = [...queryWordIndexes].sort()
171
171
  const matchedQueryWords = sortedWordIndexes.map((i) => queryWords[i])
172
172
  const queryWordRegexps = matchedQueryWords.map((queryWord) => {
173
- const escaped = queryWord.replaceAll(/[$()*+./?[\\\]^{|}-]/g, '\\$&')
173
+ const escaped = queryWord.replaceAll(
174
+ /[$()*+./?[\\\]^{|}-]/g,
175
+ String.raw`\$&`,
176
+ )
174
177
  return new RegExp(`\\b${escaped}`, 'gi')
175
178
  })
176
179
  // const needle = matchedQueryWords.join(' ')
@@ -5,9 +5,15 @@ import {
5
5
  BlobLocation,
6
6
  LocalPathLocation,
7
7
  UriLocation,
8
+ isLocalPathLocation,
8
9
  isUriLocation,
9
10
  } from '@jbrowse/core/util'
10
- import { IDBPTransaction, IndexNames, StoreNames } from 'idb/with-async-ittr'
11
+ import {
12
+ deleteDB,
13
+ IDBPTransaction,
14
+ IndexNames,
15
+ StoreNames,
16
+ } from 'idb/with-async-ittr'
11
17
 
12
18
  import { textSearch } from './fulltext'
13
19
  import { OntologyDB, OntologyDBEdge, isDeprecated } from './indexeddb-schema'
@@ -38,15 +44,6 @@ export type Transaction<
38
44
  /** the format of the loading data source */
39
45
  type SourceType = 'obo-graph-json' | 'obo' | 'owl'
40
46
 
41
- /**
42
- * @deprecated use the one from jbrowse core when it is published
43
- **/
44
- function isLocalPathLocation(location: unknown): location is LocalPathLocation {
45
- return (
46
- typeof location === 'object' && location !== null && 'localPath' in location
47
- )
48
- }
49
-
50
47
  async function arrayFromAsync<T>(iter: AsyncIterable<T>) {
51
48
  const a = []
52
49
  for await (const i of iter) {
@@ -176,18 +173,24 @@ export default class OntologyStore {
176
173
  return db
177
174
  }
178
175
 
179
- const { sourceLocation, sourceType } = this
180
- if (sourceType === 'obo-graph-json') {
181
- await this.loadOboGraphJson(db)
182
- } else {
183
- throw new Error(
184
- `ontology source file ${JSON.stringify(
185
- sourceLocation,
186
- )} has type ${sourceType}, which is not yet supported`,
187
- )
188
- }
176
+ try {
177
+ const { sourceLocation, sourceType } = this
178
+ if (sourceType === 'obo-graph-json') {
179
+ await this.loadOboGraphJson(db)
180
+ } else {
181
+ throw new Error(
182
+ `ontology source file ${JSON.stringify(
183
+ sourceLocation,
184
+ )} has type ${sourceType}, which is not yet supported`,
185
+ )
186
+ }
189
187
 
190
- return db
188
+ return db
189
+ } catch (error) {
190
+ db.close()
191
+ await deleteDB(this.dbName)
192
+ throw error
193
+ }
191
194
  }
192
195
 
193
196
  async termCount(tx?: Transaction<['nodes']>) {
@@ -497,7 +500,7 @@ export default class OntologyStore {
497
500
 
498
501
  // fetch the full nodes and filter out deprecated ones
499
502
  const terms: OntologyClass[] = []
500
- for await (const termId of termIds) {
503
+ for (const termId of termIds) {
501
504
  const node = await myTx.objectStore('nodes').get(termId)
502
505
  if (node && isOntologyClass(node) && !isDeprecated(node)) {
503
506
  terms.push(node)
@@ -84,9 +84,14 @@ export async function loadOboGraphJson(this: OntologyStore, db: Database) {
84
84
  // TODO: using file streaming along with an event-based json parser
85
85
  // instead of JSON.parse and .readFile could probably make this faster
86
86
  // and less memory intensive
87
- const oboGraph = JSON.parse(
88
- await openLocation(this.sourceLocation).readFile('utf8'),
89
- ) as GraphDocument
87
+ let oboGraph: GraphDocument
88
+ try {
89
+ oboGraph = JSON.parse(
90
+ await openLocation(this.sourceLocation).readFile('utf8'),
91
+ ) as GraphDocument
92
+ } catch {
93
+ throw new Error('Error in loading ontology')
94
+ }
90
95
 
91
96
  const parseTime = Date.now()
92
97
 
@@ -1,15 +1,26 @@
1
- import { ConfigurationSchema } from '@jbrowse/core/configuration'
1
+ import {
2
+ AnyConfigurationModel,
3
+ ConfigurationSchema,
4
+ readConfObject,
5
+ } from '@jbrowse/core/configuration'
2
6
  import {
3
7
  BlobLocation,
4
8
  LocalPathLocation,
5
9
  UriLocation,
6
10
  } from '@jbrowse/core/util/types/mst'
7
11
  import { autorun } from 'mobx'
8
- import { Instance, addDisposer, getSnapshot, types } from 'mobx-state-tree'
9
-
12
+ import {
13
+ Instance,
14
+ addDisposer,
15
+ getRoot,
16
+ getSnapshot,
17
+ types,
18
+ } from 'mobx-state-tree'
10
19
  import OntologyStore, { OntologyStoreOptions } from './OntologyStore'
11
20
  import { OntologyDBNode } from './OntologyStore/indexeddb-schema'
12
21
  import { applyPrefixes, expandPrefixes } from './OntologyStore/prefixes'
22
+ import ApolloPluginConfigurationSchema from '../config'
23
+ import { ApolloRootModel } from '../types'
13
24
 
14
25
  export { isDeprecated } from './OntologyStore/indexeddb-schema'
15
26
 
@@ -55,15 +66,27 @@ export const OntologyManagerType = types
55
66
  'SO:': 'http://purl.obolibrary.org/obo/SO_',
56
67
  }),
57
68
  })
69
+ .views((self) => ({
70
+ get featureTypeOntologyName(): string {
71
+ const jbConfig = getRoot<ApolloRootModel>(self).jbrowse
72
+ .configuration as AnyConfigurationModel
73
+ const pluginConfiguration = jbConfig.ApolloPlugin as Instance<
74
+ typeof ApolloPluginConfigurationSchema
75
+ >
76
+ const featureTypeOntologyName = readConfObject(
77
+ pluginConfiguration,
78
+ 'featureTypeOntologyName',
79
+ ) as string
80
+ return featureTypeOntologyName
81
+ },
82
+ }))
58
83
  .views((self) => ({
59
84
  /**
60
85
  * gets the OntologyRecord for the ontology we should be
61
86
  * using for feature types (e.g. SO or maybe biotypes)
62
87
  **/
63
88
  get featureTypeOntology() {
64
- // TODO: change this to read some configuration for which feature type ontology
65
- // we should be using. currently hardcoded to use SO.
66
- return this.findOntology('Sequence Ontology')
89
+ return this.findOntology(self.featureTypeOntologyName)
67
90
  },
68
91
 
69
92
  findOntology(name: string, version?: string) {
@@ -157,9 +180,9 @@ export const OntologyRecordConfiguration = ConfigurationSchema(
157
180
 
158
181
  // eslint disables because of
159
182
  // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
160
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
183
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
161
184
  export interface OntologyManager extends Instance<typeof OntologyManagerType> {}
162
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
185
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
163
186
  export interface OntologyRecord extends Instance<typeof OntologyRecordType> {}
164
187
 
165
188
  export type OntologyTerm = OntologyDBNode
@@ -425,6 +425,6 @@ export type SixFrameFeatureDisplayStateModel = ReturnType<
425
425
  >
426
426
  // eslint disable because of
427
427
  // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
428
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
428
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
429
429
  export interface SixFrameFeatureDisplay
430
430
  extends Instance<SixFrameFeatureDisplayStateModel> {}
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-call */
1
2
  import { Menu, MenuItem } from '@jbrowse/core/ui'
2
3
  import { useTheme } from '@mui/material'
3
4
  import { observer } from 'mobx-react'
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
1
2
  /* eslint-disable @typescript-eslint/use-unknown-in-catch-callback-variable */
2
3
  import { observer } from 'mobx-react'
3
4
  import React, { useEffect, useState } from 'react'
@@ -41,6 +41,6 @@ export const TabularEditorStateModelType = types
41
41
 
42
42
  // eslint disable because of
43
43
  // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
44
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
44
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
45
45
  export interface TabularEditorStateModel
46
46
  extends Instance<typeof TabularEditorStateModelType> {}
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
1
2
  /* eslint-disable @typescript-eslint/no-misused-promises */
2
3
  import { AnnotationFeature } from '@apollo-annotation/mst'
3
4
  import { AddFeatureChange } from '@apollo-annotation/shared'
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
1
2
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
2
3
  /* eslint-disable @typescript-eslint/no-misused-promises */
3
4
  import { AddFeatureChange } from '@apollo-annotation/shared'
@@ -101,7 +102,6 @@ export function AddFeature({
101
102
  break
102
103
  }
103
104
  default: {
104
- // eslint-disable-next-line unicorn/no-useless-undefined
105
105
  setStrand(undefined)
106
106
  }
107
107
  }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
1
2
  import { ChangeManager } from '../ChangeManager'
2
3
  import { ApolloSessionModel } from '../session'
3
4
  import { Dialog } from './Dialog'
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
1
2
  /* eslint-disable @typescript-eslint/use-unknown-in-catch-callback-variable */
2
3
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
4
  /* eslint-disable @typescript-eslint/no-misused-promises */
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
1
2
  /* eslint-disable @typescript-eslint/no-misused-promises */
2
3
  import { DeleteAssemblyChange } from '@apollo-annotation/shared'
3
4
  import { Assembly } from '@jbrowse/core/assemblyManager/assembly'