@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
@@ -10,29 +10,6 @@ import { ApolloSessionModel } from '../../session'
10
10
  import { getGlyph } from './getGlyph'
11
11
  import { layoutsModelFactory } from './layouts'
12
12
 
13
- export type Frame = 1 | 2 | 3 | -1 | -2 | -3
14
-
15
- export function getFrame(
16
- start: number,
17
- end: number,
18
- strand: 1 | -1,
19
- phase: 0 | 1 | 2,
20
- ): Frame {
21
- return strand === 1
22
- ? ((((start + phase) % 3) + 1) as 1 | 2 | 3)
23
- : ((-1 * ((end - phase) % 3) - 1) as -1 | -2 | -3)
24
- }
25
-
26
- export const frameColors: [
27
- null,
28
- string,
29
- string,
30
- string,
31
- string,
32
- string,
33
- string,
34
- ] = [null, '#FF8080', '#80FF80', '#8080FF', '#8080FF', '#80FF80', '#FF8080']
35
-
36
13
  export function renderingModelIntermediateFactory(
37
14
  pluginManager: PluginManager,
38
15
  configSchema: AnyConfigurationSchemaType,
@@ -169,17 +146,13 @@ function colorCode(letter: string, theme?: Theme) {
169
146
  )
170
147
  }
171
148
 
172
- function codonColorCode(letter: string, rowColorCode: string, bpPerPx: number) {
173
- const colorMap: Record<string, string> = {
149
+ function codonColorCode(letter: string) {
150
+ const colorMap: Record<string, string | undefined> = {
174
151
  M: '#33ee33',
175
152
  '*': '#f44336',
176
153
  }
177
154
 
178
- if (colorMap[letter.toUpperCase()] !== undefined) {
179
- return colorMap[letter.toUpperCase()]
180
- }
181
-
182
- return bpPerPx <= 0.1 ? rowColorCode : 'lightgray'
155
+ return colorMap[letter.toUpperCase()]
183
156
  }
184
157
 
185
158
  function reverseCodonSeq(seq: string): string {
@@ -214,7 +187,6 @@ function drawTranslation(
214
187
  seq: string,
215
188
  i: number,
216
189
  reverse: boolean,
217
- rowColorCode: string,
218
190
  ) {
219
191
  let codonSeq: string = seq.slice(i, i + 3).toUpperCase()
220
192
  if (reverse) {
@@ -225,11 +197,13 @@ function drawTranslation(
225
197
  if (!codonLetter) {
226
198
  return
227
199
  }
228
- seqTrackctx.beginPath()
229
- seqTrackctx.fillStyle = codonColorCode(codonLetter, rowColorCode, bpPerPx)
230
- seqTrackctx.rect(trnslStartPx, trnslY, trnslWidthPx, sequenceRowHeight)
231
- seqTrackctx.fill()
200
+ const fillColor = codonColorCode(codonLetter)
201
+ if (fillColor) {
202
+ seqTrackctx.fillStyle = fillColor
203
+ seqTrackctx.fillRect(trnslStartPx, trnslY, trnslWidthPx, sequenceRowHeight)
204
+ }
232
205
  if (bpPerPx <= 0.1) {
206
+ seqTrackctx.rect(trnslStartPx, trnslY, trnslWidthPx, sequenceRowHeight)
233
207
  seqTrackctx.stroke()
234
208
  drawLetter(seqTrackctx, trnslStartPx, trnslWidthPx, codonLetter, trnslY)
235
209
  }
@@ -267,6 +241,24 @@ export function sequenceRenderingModelFactory(
267
241
  self.lgv.dynamicBlocks.totalWidthPx,
268
242
  self.lgv.bpPerPx <= 1 ? 125 : 95,
269
243
  )
244
+ const frames =
245
+ self.lgv.bpPerPx <= 1
246
+ ? [3, 2, 1, 0, 0, -1, -2, -3]
247
+ : [3, 2, 1, -1, -2, -3]
248
+ let height = 0
249
+ for (const frame of frames) {
250
+ const frameColor = self.theme?.palette.framesCDS.at(frame)?.main
251
+ if (frameColor) {
252
+ seqTrackctx.fillStyle = frameColor
253
+ seqTrackctx.fillRect(
254
+ 0,
255
+ height,
256
+ self.lgv.dynamicBlocks.totalWidthPx,
257
+ self.sequenceRowHeight,
258
+ )
259
+ }
260
+ height += self.sequenceRowHeight
261
+ }
270
262
 
271
263
  for (const [idx, region] of self.regions.entries()) {
272
264
  const driver = (
@@ -289,13 +281,12 @@ export function sequenceRenderingModelFactory(
289
281
  regionNumber: idx,
290
282
  })?.offsetPx ?? 0) - self.lgv.offsetPx
291
283
  const trnslWidthPx = 3 / self.lgv.bpPerPx
292
- const trnslStartPx = self.displayedRegions[idx].reversed
284
+ const trnslStartPx = self.lgv.displayedRegions[idx].reversed
293
285
  ? trnslXOffset - trnslWidthPx
294
286
  : trnslXOffset
295
287
 
296
288
  // Draw translation forward
297
289
  for (let j = 2; j >= 0; j--) {
298
- const color = frameColors.at(j + 1) ?? '#ffffff'
299
290
  if ((region.start + i) % 3 === j) {
300
291
  drawTranslation(
301
292
  seqTrackctx,
@@ -307,7 +298,6 @@ export function sequenceRenderingModelFactory(
307
298
  seq,
308
299
  i,
309
300
  false,
310
- color,
311
301
  )
312
302
  }
313
303
  }
@@ -320,7 +310,7 @@ export function sequenceRenderingModelFactory(
320
310
  regionNumber: idx,
321
311
  })?.offsetPx ?? 0) - self.lgv.offsetPx
322
312
  const widthPx = 1 / self.lgv.bpPerPx
323
- const startPx = self.displayedRegions[idx].reversed
313
+ const startPx = self.lgv.displayedRegions[idx].reversed
324
314
  ? xOffset - widthPx
325
315
  : xOffset
326
316
 
@@ -370,7 +360,6 @@ export function sequenceRenderingModelFactory(
370
360
 
371
361
  // Draw translation reverse
372
362
  for (let k = 0; k <= 2; k++) {
373
- const color = frameColors.at(-(k + 1)) ?? '#ffffff'
374
363
  const rowOffset = self.lgv.bpPerPx <= 1 ? 5 : 3
375
364
  if ((region.start + i) % 3 === k) {
376
365
  drawTranslation(
@@ -383,7 +372,6 @@ export function sequenceRenderingModelFactory(
383
372
  seq,
384
373
  i,
385
374
  true,
386
- color,
387
375
  )
388
376
  }
389
377
  }
@@ -412,21 +400,19 @@ export function renderingModelFactory(
412
400
  self,
413
401
  autorun(
414
402
  () => {
415
- if (!self.lgv.initialized || self.regionCannotBeRendered()) {
403
+ const { canvas, featureLayouts, featuresHeight, lgv } = self
404
+ if (!lgv.initialized || self.regionCannotBeRendered()) {
416
405
  return
417
406
  }
418
- const ctx = self.canvas?.getContext('2d')
407
+ const { displayedRegions, dynamicBlocks } = lgv
408
+
409
+ const ctx = canvas?.getContext('2d')
419
410
  if (!ctx) {
420
411
  return
421
412
  }
422
- ctx.clearRect(
423
- 0,
424
- 0,
425
- self.lgv.dynamicBlocks.totalWidthPx,
426
- self.featuresHeight,
427
- )
428
- for (const [idx, featureLayout] of self.featureLayouts.entries()) {
429
- const displayedRegion = self.displayedRegions[idx]
413
+ ctx.clearRect(0, 0, dynamicBlocks.totalWidthPx, featuresHeight)
414
+ for (const [idx, featureLayout] of featureLayouts.entries()) {
415
+ const displayedRegion = displayedRegions[idx]
430
416
  for (const [row, featureLayoutRow] of featureLayout.entries()) {
431
417
  for (const [featureRow, feature] of featureLayoutRow) {
432
418
  if (featureRow > 0) {
@@ -442,20 +428,7 @@ export function renderingModelFactory(
442
428
  ) {
443
429
  continue
444
430
  }
445
- const x =
446
- (self.lgv.bpToPx({
447
- refName: displayedRegion.refName,
448
- coord: feature.min,
449
- regionNumber: idx,
450
- })?.offsetPx ?? 0) - self.lgv.offsetPx
451
- getGlyph(feature, self.lgv.bpPerPx).draw(
452
- self,
453
- ctx,
454
- feature,
455
- x,
456
- row,
457
- displayedRegion.reversed,
458
- )
431
+ getGlyph(feature).draw(ctx, feature, row, self, idx)
459
432
  }
460
433
  }
461
434
  }
@@ -470,5 +443,8 @@ export function renderingModelFactory(
470
443
  export type LinearApolloDisplayRenderingModel = ReturnType<
471
444
  typeof renderingModelIntermediateFactory
472
445
  >
473
- export type LinearApolloDisplayRendering =
474
- Instance<LinearApolloDisplayRenderingModel>
446
+ // eslint disable because of
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
449
+ export interface LinearApolloDisplayRendering
450
+ extends Instance<LinearApolloDisplayRenderingModel> {}
@@ -1,5 +1,5 @@
1
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
1
2
  /* eslint-disable @typescript-eslint/no-unsafe-return */
2
- /* eslint-disable import/no-named-as-default-member */
3
3
  // jsonpath triggers this rule for some reason. import { query } from 'jsonpath' does not work
4
4
 
5
5
  import { checkAbortSignal } from '@jbrowse/core/util'
@@ -1,4 +1,5 @@
1
- /* eslint-disable @typescript-eslint/no-throw-literal */
1
+ /* eslint-disable @typescript-eslint/only-throw-error */
2
+
2
3
  /* eslint-disable unicorn/no-await-expression-member */
3
4
  import {
4
5
  BlobLocation,
@@ -155,8 +155,12 @@ export const OntologyRecordConfiguration = ConfigurationSchema(
155
155
  },
156
156
  )
157
157
 
158
- export type OntologyManager = Instance<typeof OntologyManagerType>
159
- export type OntologyRecord = Instance<typeof OntologyRecordType>
158
+ // eslint disables because of
159
+ // 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
161
+ export interface OntologyManager extends Instance<typeof OntologyManagerType> {}
162
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
163
+ export interface OntologyRecord extends Instance<typeof OntologyRecordType> {}
160
164
 
161
165
  export type OntologyTerm = OntologyDBNode
162
166
 
@@ -1,10 +1,10 @@
1
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
1
+ import { AnnotationFeature } from '@apollo-annotation/mst'
2
2
 
3
3
  import OntologyStore from './OntologyStore'
4
4
  import { isOntologyClass } from '.'
5
5
 
6
6
  export async function fetchValidDescendantTerms(
7
- parentFeature: AnnotationFeatureI | undefined,
7
+ parentFeature: AnnotationFeature | undefined,
8
8
  ontologyStore: OntologyStore,
9
9
  _signal: AbortSignal,
10
10
  ) {
@@ -1,10 +1,11 @@
1
+ /* eslint-disable @typescript-eslint/restrict-plus-operands */
1
2
  /* eslint-disable @typescript-eslint/no-unsafe-return */
2
3
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3
4
  /* eslint-disable @typescript-eslint/no-unnecessary-condition */
4
5
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
5
6
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
6
7
  /* eslint-disable @typescript-eslint/unbound-method */
7
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
8
+ import { AnnotationFeature } from '@apollo-annotation/mst'
8
9
  import { ConfigurationReference } from '@jbrowse/core/configuration'
9
10
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
10
11
  import PluginManager from '@jbrowse/core/PluginManager'
@@ -48,7 +49,7 @@ export function stateModelFactory(
48
49
  showIntronLines: true,
49
50
  })
50
51
  .volatile(() => ({
51
- apolloFeatureUnderMouse: undefined as AnnotationFeatureI | undefined,
52
+ apolloFeatureUnderMouse: undefined as AnnotationFeature | undefined,
52
53
  apolloRowUnderMouse: undefined as number | undefined,
53
54
  }))
54
55
  .views((self) => {
@@ -169,7 +170,7 @@ export function stateModelFactory(
169
170
  get features() {
170
171
  const { regions } = self
171
172
  const session = getSession(self) as ApolloSession
172
- const features = new Map<string, Map<string, AnnotationFeatureI>>()
173
+ const features = new Map<string, Map<string, AnnotationFeature>>()
173
174
  for (const region of regions) {
174
175
  const assembly = session.apolloDataStore.assemblies.get(
175
176
  region.assemblyName,
@@ -177,7 +178,7 @@ export function stateModelFactory(
177
178
  const ref = assembly?.getByRefName(region.refName)
178
179
  let filteredRef = features.get(region.refName)
179
180
  if (!filteredRef) {
180
- filteredRef = new Map<string, AnnotationFeatureI>()
181
+ filteredRef = new Map<string, AnnotationFeature>()
181
182
  features.set(region.refName, filteredRef)
182
183
  }
183
184
  for (const [featureId, feature] of ref?.features.entries() ??
@@ -204,7 +205,7 @@ export function stateModelFactory(
204
205
  if (featureLocation.min < min) {
205
206
  ;({ min } = featureLocation)
206
207
  }
207
- if (featureLocation.end > max) {
208
+ if (featureLocation.max > max) {
208
209
  ;({ max } = featureLocation)
209
210
  }
210
211
  }
@@ -269,7 +270,7 @@ export function stateModelFactory(
269
270
  return codonLayout
270
271
  },
271
272
  get featureLayout() {
272
- const featureLayout = new Map<number, [string, AnnotationFeatureI][]>()
273
+ const featureLayout = new Map<number, [string, AnnotationFeature][]>()
273
274
  for (const [refSeq, featuresForRefSeq] of this.features || []) {
274
275
  if (!featuresForRefSeq) {
275
276
  continue
@@ -342,7 +343,7 @@ export function stateModelFactory(
342
343
  }
343
344
  return assembly.name
344
345
  },
345
- get selectedFeature(): AnnotationFeatureI | undefined {
346
+ get selectedFeature(): AnnotationFeature | undefined {
346
347
  const session = getSession(self) as ApolloSession
347
348
  return session.apolloSelectedFeature
348
349
  },
@@ -352,11 +353,11 @@ export function stateModelFactory(
352
353
  },
353
354
  }))
354
355
  .actions((self) => ({
355
- setSelectedFeature(feature?: AnnotationFeatureI) {
356
+ setSelectedFeature(feature?: AnnotationFeature) {
356
357
  const session = getSession(self) as ApolloSession
357
358
  session.apolloSetSelectedFeature(feature)
358
359
  },
359
- setApolloFeatureUnderMouse(feature?: AnnotationFeatureI) {
360
+ setApolloFeatureUnderMouse(feature?: AnnotationFeature) {
360
361
  self.apolloFeatureUnderMouse = feature
361
362
  },
362
363
  setApolloRowUnderMouse(row?: number) {
@@ -422,4 +423,8 @@ export function stateModelFactory(
422
423
  export type SixFrameFeatureDisplayStateModel = ReturnType<
423
424
  typeof stateModelFactory
424
425
  >
425
- export type SixFrameFeatureDisplay = Instance<SixFrameFeatureDisplayStateModel>
426
+ // eslint disable because of
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
429
+ export interface SixFrameFeatureDisplay
430
+ extends Instance<SixFrameFeatureDisplayStateModel> {}
@@ -1,7 +1,5 @@
1
- import type { AnnotationFeatureI } from '@apollo-annotation/mst'
1
+ import type { AnnotationFeature } from '@apollo-annotation/mst'
2
2
  import {
3
- DiscontinuousLocationEndChange,
4
- DiscontinuousLocationStartChange,
5
3
  LocationEndChange,
6
4
  LocationStartChange,
7
5
  TypeChange,
@@ -11,7 +9,7 @@ import type { ChangeManager } from '../../ChangeManager'
11
9
 
12
10
  export function handleFeatureTypeChange(
13
11
  changeManager: ChangeManager,
14
- feature: AnnotationFeatureI,
12
+ feature: AnnotationFeature,
15
13
  oldType: string,
16
14
  newType: string,
17
15
  ) {
@@ -29,60 +27,37 @@ export function handleFeatureTypeChange(
29
27
 
30
28
  export function handleFeatureStartChange(
31
29
  changeManager: ChangeManager,
32
- feature: AnnotationFeatureI,
30
+ feature: AnnotationFeature,
33
31
  oldStart: number,
34
32
  newStart: number,
35
- index?: number,
36
33
  ) {
37
34
  const featureId = feature._id
38
- const change =
39
- index === undefined
40
- ? new LocationStartChange({
41
- typeName: 'LocationStartChange',
42
- changedIds: [featureId],
43
- featureId,
44
- oldStart,
45
- newStart,
46
- assembly: feature.assemblyId,
47
- })
48
- : new DiscontinuousLocationStartChange({
49
- typeName: 'DiscontinuousLocationStartChange',
50
- changedIds: [featureId],
51
- featureId,
52
- oldStart,
53
- newStart,
54
- assembly: feature.assemblyId,
55
- index,
56
- })
35
+ const change = new LocationStartChange({
36
+ typeName: 'LocationStartChange',
37
+ changedIds: [featureId],
38
+ featureId,
39
+ oldStart,
40
+ newStart,
41
+ assembly: feature.assemblyId,
42
+ })
43
+
57
44
  return changeManager.submit(change)
58
45
  }
59
46
 
60
47
  export function handleFeatureEndChange(
61
48
  changeManager: ChangeManager,
62
- feature: AnnotationFeatureI,
49
+ feature: AnnotationFeature,
63
50
  oldEnd: number,
64
51
  newEnd: number,
65
- index?: number,
66
52
  ) {
67
53
  const featureId = feature._id
68
- const change =
69
- index === undefined
70
- ? new LocationEndChange({
71
- typeName: 'LocationEndChange',
72
- changedIds: [featureId],
73
- featureId,
74
- oldEnd,
75
- newEnd,
76
- assembly: feature.assemblyId,
77
- })
78
- : new DiscontinuousLocationEndChange({
79
- typeName: 'DiscontinuousLocationEndChange',
80
- changedIds: [featureId],
81
- featureId,
82
- oldEnd,
83
- newEnd,
84
- assembly: feature.assemblyId,
85
- index,
86
- })
54
+ const change = new LocationEndChange({
55
+ typeName: 'LocationEndChange',
56
+ changedIds: [featureId],
57
+ featureId,
58
+ oldEnd,
59
+ newEnd,
60
+ assembly: feature.assemblyId,
61
+ })
87
62
  return changeManager.submit(change)
88
63
  }
@@ -1,8 +1,8 @@
1
+ /* eslint-disable @typescript-eslint/use-unknown-in-catch-callback-variable */
2
+ /* eslint-disable unicorn/no-nested-ternary */
1
3
  /* eslint-disable @typescript-eslint/unbound-method */
2
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
4
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
5
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
4
+
5
+ import { AnnotationFeature } from '@apollo-annotation/mst'
6
6
  import { AbstractSessionModel } from '@jbrowse/core/util'
7
7
  import { observer } from 'mobx-react'
8
8
  import React from 'react'
@@ -21,6 +21,7 @@ import { FeatureAttributes } from './FeatureAttributes'
21
21
  import { featureContextMenuItems } from './featureContextMenuItems'
22
22
  import type { ContextMenuState } from './HybridGrid'
23
23
  import { NumberCell } from './NumberCell'
24
+ import { getGlyph } from '../../LinearApolloDisplay/stateModel/getGlyph'
24
25
 
25
26
  const useStyles = makeStyles()((theme) => ({
26
27
  typeContent: {
@@ -59,7 +60,7 @@ const useStyles = makeStyles()((theme) => ({
59
60
 
60
61
  function makeContextMenuItems(
61
62
  display: DisplayStateModel,
62
- feature: AnnotationFeatureI,
63
+ feature: AnnotationFeature,
63
64
  ) {
64
65
  const {
65
66
  changeManager,
@@ -80,7 +81,7 @@ function makeContextMenuItems(
80
81
  )
81
82
  }
82
83
 
83
- function getTopLevelFeature(feature: AnnotationFeatureI): AnnotationFeatureI {
84
+ function getTopLevelFeature(feature: AnnotationFeature): AnnotationFeature {
84
85
  let cur = feature
85
86
  while (cur.parent) {
86
87
  cur = cur.parent
@@ -98,7 +99,7 @@ export const Feature = observer(function Feature({
98
99
  setContextMenu,
99
100
  }: {
100
101
  model: DisplayStateModel
101
- feature: AnnotationFeatureI
102
+ feature: AnnotationFeature
102
103
  depth: number
103
104
  isHovered: boolean
104
105
  isSelected: boolean
@@ -114,16 +115,7 @@ export const Feature = observer(function Feature({
114
115
  tabularEditor: tabularEditorState,
115
116
  } = displayState
116
117
  const { featureCollapsed, filterText } = tabularEditorState
117
- const {
118
- _id,
119
- children,
120
- discontinuousLocations,
121
- end,
122
- phase,
123
- start,
124
- strand,
125
- type,
126
- } = feature
118
+ const { _id, children, max, min, strand, type } = feature
127
119
  const expanded = !featureCollapsed.get(_id)
128
120
  const toggleExpanded = (e: React.MouseEvent) => {
129
121
  e.stopPropagation()
@@ -142,6 +134,7 @@ export const Feature = observer(function Feature({
142
134
  displayState.setApolloHover({
143
135
  feature,
144
136
  topLevelFeature: getTopLevelFeature(feature),
137
+ glyph: getGlyph(getTopLevelFeature(feature)),
145
138
  })
146
139
  }}
147
140
  className={
@@ -222,72 +215,29 @@ export const Feature = observer(function Feature({
222
215
  </div>
223
216
  </td>
224
217
  <td>
225
- {discontinuousLocations && discontinuousLocations.length > 0 ? (
226
- <div style={{ display: 'flex', flexDirection: 'column' }}>
227
- {discontinuousLocations.map((loc, index) => (
228
- <NumberCell
229
- key={`${_id}:${loc.start},${loc.phase}`}
230
- initialValue={loc.start + 1}
231
- notifyError={notifyError}
232
- onChangeCommitted={(newStart) =>
233
- handleFeatureStartChange(
234
- changeManager,
235
- feature,
236
- discontinuousLocations[index].start,
237
- newStart - 1,
238
- index,
239
- )
240
- }
241
- />
242
- ))}
243
- </div>
244
- ) : (
245
- <NumberCell
246
- initialValue={start + 1}
247
- notifyError={notifyError}
248
- onChangeCommitted={(newStart) =>
249
- handleFeatureStartChange(
250
- changeManager,
251
- feature,
252
- start,
253
- newStart - 1,
254
- )
255
- }
256
- />
257
- )}
218
+ <NumberCell
219
+ initialValue={min + 1}
220
+ notifyError={notifyError}
221
+ onChangeCommitted={(newStart) =>
222
+ handleFeatureStartChange(
223
+ changeManager,
224
+ feature,
225
+ min,
226
+ newStart - 1,
227
+ )
228
+ }
229
+ />
258
230
  </td>
259
231
  <td>
260
- {discontinuousLocations && discontinuousLocations.length > 0 ? (
261
- <div style={{ display: 'flex', flexDirection: 'column' }}>
262
- {discontinuousLocations.map((loc, index) => (
263
- <NumberCell
264
- key={`${_id}:${loc.end},${loc.phase}`}
265
- initialValue={loc.end}
266
- notifyError={notifyError}
267
- onChangeCommitted={(newEnd) =>
268
- handleFeatureEndChange(
269
- changeManager,
270
- feature,
271
- discontinuousLocations[index].end,
272
- newEnd,
273
- index,
274
- )
275
- }
276
- />
277
- ))}
278
- </div>
279
- ) : (
280
- <NumberCell
281
- initialValue={end}
282
- notifyError={notifyError}
283
- onChangeCommitted={(newEnd) =>
284
- handleFeatureEndChange(changeManager, feature, end, newEnd)
285
- }
286
- />
287
- )}
232
+ <NumberCell
233
+ initialValue={max}
234
+ notifyError={notifyError}
235
+ onChangeCommitted={(newEnd) =>
236
+ handleFeatureEndChange(changeManager, feature, max, newEnd)
237
+ }
238
+ />
288
239
  </td>
289
240
  <td>{strand === 1 ? '+' : strand === -1 ? '-' : undefined}</td>
290
- <td>{phase}</td>
291
241
  <td>
292
242
  <FeatureAttributes filterText={filterText} feature={feature} />
293
243
  </td>
@@ -304,8 +254,7 @@ export const Feature = observer(function Feature({
304
254
  return text.includes(filterText)
305
255
  })
306
256
  .map(([featureId, childFeature]) => {
307
- const childHovered =
308
- apolloHover?.feature?._id === childFeature._id
257
+ const childHovered = apolloHover?.feature._id === childFeature._id
309
258
  const childSelected = selectedFeature?._id === childFeature._id
310
259
  return (
311
260
  <Feature
@@ -325,7 +274,7 @@ export const Feature = observer(function Feature({
325
274
  )
326
275
  })
327
276
  async function fetchValidTypeTerms(
328
- feature: AnnotationFeatureI,
277
+ feature: AnnotationFeature,
329
278
  ontologyStore: OntologyStore,
330
279
  _signal: AbortSignal,
331
280
  ) {
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/restrict-template-expressions */
2
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
2
+ import { AnnotationFeature } from '@apollo-annotation/mst'
3
3
  import { observer } from 'mobx-react'
4
4
  import { getSnapshot } from 'mobx-state-tree'
5
5
  import React from 'react'
@@ -10,7 +10,7 @@ export const FeatureAttributes = observer(function FeatureAttributes({
10
10
  feature,
11
11
  filterText,
12
12
  }: {
13
- feature: AnnotationFeatureI
13
+ feature: AnnotationFeature
14
14
  filterText: string
15
15
  }) {
16
16
  const attrString = [...feature.attributes.entries()]
@@ -25,6 +25,7 @@ export const FeatureAttributes = observer(function FeatureAttributes({
25
25
  }
26
26
  return [key, getSnapshot(value)]
27
27
  })
28
+ .filter(([key]) => key) // Leave empty keys off
28
29
  .map(
29
30
  ([key, values]) =>
30
31
  `${key}=${Array.isArray(values) ? values.join(', ') : values}`,
@@ -76,7 +76,6 @@ const HybridGrid = observer(function HybridGrid({
76
76
  <th>Start</th>
77
77
  <th>End</th>
78
78
  <th>Strand</th>
79
- <th>Phase</th>
80
79
  <th>Attributes</th>
81
80
  </tr>
82
81
  </thead>
@@ -92,11 +91,11 @@ const HybridGrid = observer(function HybridGrid({
92
91
  return text.includes(filterText)
93
92
  })
94
93
  .sort((a, b) => {
95
- return a[1].start - b[1].start
94
+ return a[1].min - b[1].min
96
95
  })
97
96
  .map(([featureId, feature]) => {
98
97
  const isSelected = selectedFeature?._id === featureId
99
- const isHovered = apolloHover?.feature?._id === featureId
98
+ const isHovered = apolloHover?.feature._id === featureId
100
99
  return (
101
100
  <Feature
102
101
  key={featureId}
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/use-unknown-in-catch-callback-variable */
1
2
  import { observer } from 'mobx-react'
2
3
  import React, { useEffect, useState } from 'react'
3
4
  import { makeStyles } from 'tss-react/mui'