@jbrowse/plugin-linear-genome-view 2.4.1 → 2.5.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.
- package/dist/BaseLinearDisplay/components/LinearBlocks.d.ts +1 -4
- package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +8 -43
- package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
- package/dist/BaseLinearDisplay/components/TooLargeMessage.d.ts +3 -4
- package/dist/BaseLinearDisplay/components/TooLargeMessage.js +9 -9
- package/dist/BaseLinearDisplay/components/TooLargeMessage.js.map +1 -1
- package/dist/BaseLinearDisplay/components/Tooltip.d.ts +0 -1
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +81 -35
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +105 -143
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
- package/dist/BaseLinearDisplay/models/configSchema.d.ts +35 -1
- package/dist/BaseLinearDisplay/models/configSchema.js +9 -0
- package/dist/BaseLinearDisplay/models/configSchema.js.map +1 -1
- package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +10 -6
- package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
- package/dist/BaseLinearDisplay/models/util.d.ts +8 -0
- package/dist/BaseLinearDisplay/models/util.js +33 -1
- package/dist/BaseLinearDisplay/models/util.js.map +1 -1
- package/dist/BasicTrack/configSchema.d.ts +73 -1
- package/dist/FeatureTrack/configSchema.d.ts +75 -1
- package/dist/LinearBareDisplay/configSchema.d.ts +28 -1
- package/dist/LinearBareDisplay/index.js +1 -0
- package/dist/LinearBareDisplay/index.js.map +1 -1
- package/dist/LinearBareDisplay/model.d.ts +66 -23
- package/dist/LinearBareDisplay/model.js +2 -2
- package/dist/LinearBareDisplay/model.js.map +1 -1
- package/dist/LinearBasicDisplay/components/SetMaxHeight.d.ts +1 -2
- package/dist/LinearBasicDisplay/components/SetMaxHeight.js +2 -5
- package/dist/LinearBasicDisplay/components/SetMaxHeight.js.map +1 -1
- package/dist/LinearBasicDisplay/configSchema.d.ts +28 -1
- package/dist/LinearBasicDisplay/configSchema.js +0 -9
- package/dist/LinearBasicDisplay/configSchema.js.map +1 -1
- package/dist/LinearBasicDisplay/index.js +1 -1
- package/dist/LinearBasicDisplay/model.d.ts +76 -36
- package/dist/LinearBasicDisplay/model.js.map +1 -1
- package/dist/LinearGenomeView/components/CenterLine.d.ts +0 -1
- package/dist/LinearGenomeView/components/Cytobands.d.ts +22 -23
- package/dist/LinearGenomeView/components/ExportSvgDialog.d.ts +0 -1
- package/dist/LinearGenomeView/components/GetSequenceDialog.d.ts +0 -1
- package/dist/LinearGenomeView/components/GetSequenceDialog.js +14 -16
- package/dist/LinearGenomeView/components/GetSequenceDialog.js.map +1 -1
- package/dist/LinearGenomeView/components/Gridlines.d.ts +0 -1
- package/dist/LinearGenomeView/components/Header.d.ts +0 -1
- package/dist/LinearGenomeView/components/HelpDialog.d.ts +0 -1
- package/dist/LinearGenomeView/components/ImportForm.d.ts +0 -1
- package/dist/LinearGenomeView/components/ImportForm.js +4 -7
- package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.d.ts +0 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.js +0 -4
- package/dist/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/dist/LinearGenomeView/components/MiniControls.d.ts +0 -1
- package/dist/LinearGenomeView/components/OverviewScalebar.js +2 -1
- package/dist/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
- package/dist/LinearGenomeView/components/RefNameAutocomplete.js +53 -52
- package/dist/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
- package/dist/LinearGenomeView/components/RubberbandSpan.d.ts +0 -1
- package/dist/LinearGenomeView/components/SearchBox.d.ts +0 -1
- package/dist/LinearGenomeView/components/SearchResultsDialog.d.ts +5 -3
- package/dist/LinearGenomeView/components/SearchResultsDialog.js +6 -82
- package/dist/LinearGenomeView/components/SearchResultsDialog.js.map +1 -1
- package/dist/LinearGenomeView/components/SearchResultsTable.d.ts +8 -0
- package/dist/LinearGenomeView/components/SearchResultsTable.js +83 -0
- package/dist/LinearGenomeView/components/SearchResultsTable.js.map +1 -0
- package/dist/LinearGenomeView/components/SequenceSearchDialog.d.ts +0 -1
- package/dist/LinearGenomeView/components/TrackContainer.d.ts +0 -1
- package/dist/LinearGenomeView/components/TrackContainer.js +8 -2
- package/dist/LinearGenomeView/components/TrackContainer.js.map +1 -1
- package/dist/LinearGenomeView/components/TracksContainer.js +5 -7
- package/dist/LinearGenomeView/components/TracksContainer.js.map +1 -1
- package/dist/LinearGenomeView/components/VerticalGuide.d.ts +0 -1
- package/dist/LinearGenomeView/components/ZoomControls.d.ts +0 -1
- package/dist/LinearGenomeView/components/util.js +1 -1
- package/dist/LinearGenomeView/components/util.js.map +1 -1
- package/dist/LinearGenomeView/model.d.ts +49 -36
- package/dist/LinearGenomeView/model.js +121 -198
- package/dist/LinearGenomeView/model.js.map +1 -1
- package/dist/LinearGenomeView/svgcomponents/SVGBackground.d.ts +0 -1
- package/dist/LinearGenomeView/svgcomponents/SVGHeader.d.ts +0 -1
- package/dist/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +0 -1
- package/dist/LinearGenomeView/svgcomponents/SVGRuler.d.ts +0 -1
- package/dist/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +0 -1
- package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +0 -1
- package/dist/LinearGenomeView/svgcomponents/SVGTracks.d.ts +0 -1
- package/dist/LinearGenomeView/util.d.ts +29 -0
- package/dist/LinearGenomeView/util.js +79 -1
- package/dist/LinearGenomeView/util.js.map +1 -1
- package/dist/index.d.ts +201 -106
- package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +1 -4
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +8 -20
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
- package/esm/BaseLinearDisplay/components/TooLargeMessage.d.ts +3 -4
- package/esm/BaseLinearDisplay/components/TooLargeMessage.js +9 -9
- package/esm/BaseLinearDisplay/components/TooLargeMessage.js.map +1 -1
- package/esm/BaseLinearDisplay/components/Tooltip.d.ts +0 -1
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +81 -35
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +105 -143
- package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
- package/esm/BaseLinearDisplay/models/configSchema.d.ts +35 -1
- package/esm/BaseLinearDisplay/models/configSchema.js +9 -0
- package/esm/BaseLinearDisplay/models/configSchema.js.map +1 -1
- package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +10 -6
- package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
- package/esm/BaseLinearDisplay/models/util.d.ts +8 -0
- package/esm/BaseLinearDisplay/models/util.js +30 -0
- package/esm/BaseLinearDisplay/models/util.js.map +1 -1
- package/esm/BasicTrack/configSchema.d.ts +73 -1
- package/esm/FeatureTrack/configSchema.d.ts +75 -1
- package/esm/LinearBareDisplay/configSchema.d.ts +28 -1
- package/esm/LinearBareDisplay/index.js +1 -0
- package/esm/LinearBareDisplay/index.js.map +1 -1
- package/esm/LinearBareDisplay/model.d.ts +66 -23
- package/esm/LinearBareDisplay/model.js +1 -1
- package/esm/LinearBareDisplay/model.js.map +1 -1
- package/esm/LinearBasicDisplay/components/SetMaxHeight.d.ts +1 -2
- package/esm/LinearBasicDisplay/components/SetMaxHeight.js +2 -5
- package/esm/LinearBasicDisplay/components/SetMaxHeight.js.map +1 -1
- package/esm/LinearBasicDisplay/configSchema.d.ts +28 -1
- package/esm/LinearBasicDisplay/configSchema.js +0 -9
- package/esm/LinearBasicDisplay/configSchema.js.map +1 -1
- package/esm/LinearBasicDisplay/index.js +1 -1
- package/esm/LinearBasicDisplay/model.d.ts +76 -36
- package/esm/LinearBasicDisplay/model.js.map +1 -1
- package/esm/LinearGenomeView/components/CenterLine.d.ts +0 -1
- package/esm/LinearGenomeView/components/Cytobands.d.ts +22 -23
- package/esm/LinearGenomeView/components/ExportSvgDialog.d.ts +0 -1
- package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +0 -1
- package/esm/LinearGenomeView/components/GetSequenceDialog.js +15 -17
- package/esm/LinearGenomeView/components/GetSequenceDialog.js.map +1 -1
- package/esm/LinearGenomeView/components/Gridlines.d.ts +0 -1
- package/esm/LinearGenomeView/components/Header.d.ts +0 -1
- package/esm/LinearGenomeView/components/HelpDialog.d.ts +0 -1
- package/esm/LinearGenomeView/components/ImportForm.d.ts +0 -1
- package/esm/LinearGenomeView/components/ImportForm.js +5 -8
- package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +0 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.js +0 -4
- package/esm/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/esm/LinearGenomeView/components/MiniControls.d.ts +0 -1
- package/esm/LinearGenomeView/components/OverviewScalebar.js +2 -1
- package/esm/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
- package/esm/LinearGenomeView/components/RefNameAutocomplete.js +53 -52
- package/esm/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
- package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +0 -1
- package/esm/LinearGenomeView/components/SearchBox.d.ts +0 -1
- package/esm/LinearGenomeView/components/SearchResultsDialog.d.ts +5 -3
- package/esm/LinearGenomeView/components/SearchResultsDialog.js +7 -83
- package/esm/LinearGenomeView/components/SearchResultsDialog.js.map +1 -1
- package/esm/LinearGenomeView/components/SearchResultsTable.d.ts +8 -0
- package/esm/LinearGenomeView/components/SearchResultsTable.js +77 -0
- package/esm/LinearGenomeView/components/SearchResultsTable.js.map +1 -0
- package/esm/LinearGenomeView/components/SequenceSearchDialog.d.ts +0 -1
- package/esm/LinearGenomeView/components/TrackContainer.d.ts +0 -1
- package/esm/LinearGenomeView/components/TrackContainer.js +8 -2
- package/esm/LinearGenomeView/components/TrackContainer.js.map +1 -1
- package/esm/LinearGenomeView/components/TracksContainer.js +5 -7
- package/esm/LinearGenomeView/components/TracksContainer.js.map +1 -1
- package/esm/LinearGenomeView/components/VerticalGuide.d.ts +0 -1
- package/esm/LinearGenomeView/components/ZoomControls.d.ts +0 -1
- package/esm/LinearGenomeView/components/util.js +1 -1
- package/esm/LinearGenomeView/components/util.js.map +1 -1
- package/esm/LinearGenomeView/model.d.ts +49 -36
- package/esm/LinearGenomeView/model.js +122 -199
- package/esm/LinearGenomeView/model.js.map +1 -1
- package/esm/LinearGenomeView/svgcomponents/SVGBackground.d.ts +0 -1
- package/esm/LinearGenomeView/svgcomponents/SVGHeader.d.ts +0 -1
- package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +0 -1
- package/esm/LinearGenomeView/svgcomponents/SVGRuler.d.ts +0 -1
- package/esm/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +0 -1
- package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +0 -1
- package/esm/LinearGenomeView/svgcomponents/SVGTracks.d.ts +0 -1
- package/esm/LinearGenomeView/util.d.ts +29 -0
- package/esm/LinearGenomeView/util.js +76 -0
- package/esm/LinearGenomeView/util.js.map +1 -1
- package/esm/index.d.ts +201 -106
- package/package.json +3 -3
- package/src/BaseLinearDisplay/components/ServerSideRenderedBlockContent.tsx +8 -28
- package/src/BaseLinearDisplay/components/TooLargeMessage.tsx +13 -11
- package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +148 -197
- package/src/BaseLinearDisplay/models/configSchema.ts +10 -0
- package/src/BaseLinearDisplay/models/serverSideRenderedBlock.ts +19 -13
- package/src/BaseLinearDisplay/models/util.ts +43 -0
- package/src/LinearBareDisplay/index.ts +1 -0
- package/src/LinearBareDisplay/model.ts +1 -1
- package/src/LinearBasicDisplay/components/SetMaxHeight.tsx +3 -7
- package/src/LinearBasicDisplay/configSchema.ts +0 -10
- package/src/LinearBasicDisplay/index.ts +1 -1
- package/src/LinearBasicDisplay/model.ts +1 -1
- package/src/LinearGenomeView/components/GetSequenceDialog.tsx +15 -25
- package/src/LinearGenomeView/components/ImportForm.tsx +4 -14
- package/src/LinearGenomeView/components/LinearGenomeView.tsx +0 -14
- package/src/LinearGenomeView/components/OverviewScalebar.tsx +2 -1
- package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +122 -82
- package/src/LinearGenomeView/components/SearchResultsDialog.tsx +17 -112
- package/src/LinearGenomeView/components/SearchResultsTable.tsx +121 -0
- package/src/LinearGenomeView/components/TrackContainer.tsx +12 -3
- package/src/LinearGenomeView/components/TracksContainer.tsx +9 -6
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +11 -11
- package/src/LinearGenomeView/components/util.ts +2 -1
- package/src/LinearGenomeView/index.test.ts +10 -12
- package/src/LinearGenomeView/model.ts +163 -236
- package/src/LinearGenomeView/util.ts +98 -0
|
@@ -63,19 +63,25 @@ const blockState = types
|
|
|
63
63
|
},
|
|
64
64
|
afterAttach() {
|
|
65
65
|
const display = getContainingDisplay(self)
|
|
66
|
-
|
|
67
|
-
self
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
if (isAlive(self)) {
|
|
68
|
+
makeAbortableReaction(
|
|
69
|
+
self as any,
|
|
70
|
+
renderBlockData,
|
|
71
|
+
renderBlockEffect, // reaction doesn't expect async here
|
|
72
|
+
{
|
|
73
|
+
name: `${display.id}/${assembleLocString(
|
|
74
|
+
self.region,
|
|
75
|
+
)} rendering`,
|
|
76
|
+
delay: display.renderDelay,
|
|
77
|
+
fireImmediately: true,
|
|
78
|
+
},
|
|
79
|
+
this.setLoading,
|
|
80
|
+
this.setRendered,
|
|
81
|
+
this.setError,
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
}, display.renderDelay)
|
|
79
85
|
},
|
|
80
86
|
setStatus(message: string) {
|
|
81
87
|
self.status = message
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { AnyConfigurationModel } from '@jbrowse/core/configuration'
|
|
2
|
+
import { FeatureDensityStats } from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
3
|
+
import { getContainingView, getSession } from '@jbrowse/core/util'
|
|
4
|
+
import { getRpcSessionId } from '@jbrowse/core/util/tracks'
|
|
5
|
+
import { IAnyStateTreeNode, isAlive } from 'mobx-state-tree'
|
|
6
|
+
import { LinearGenomeViewModel } from '../../LinearGenomeView'
|
|
7
|
+
|
|
1
8
|
export interface RenderProps {
|
|
2
9
|
rendererType: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
3
10
|
renderArgs: { [key: string]: any } // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
@@ -22,3 +29,39 @@ export function getDisplayStr(totalBytes: number) {
|
|
|
22
29
|
}
|
|
23
30
|
return displayBp
|
|
24
31
|
}
|
|
32
|
+
|
|
33
|
+
// stabilize clipid under test for snapshot
|
|
34
|
+
export function getId(id: string, index: number) {
|
|
35
|
+
const isJest = typeof jest === 'undefined'
|
|
36
|
+
return `clip-${isJest ? id : 'jest'}-${index}`
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function getFeatureDensityStatsPre(
|
|
40
|
+
self: IAnyStateTreeNode & {
|
|
41
|
+
adapterConfig?: AnyConfigurationModel
|
|
42
|
+
setMessage: (arg: string) => void
|
|
43
|
+
},
|
|
44
|
+
) {
|
|
45
|
+
const view = getContainingView(self) as LinearGenomeViewModel
|
|
46
|
+
const regions = view.staticBlocks.contentBlocks
|
|
47
|
+
|
|
48
|
+
const { rpcManager } = getSession(self)
|
|
49
|
+
const { adapterConfig } = self
|
|
50
|
+
if (!adapterConfig) {
|
|
51
|
+
// A track extending the base track might not have an adapter config
|
|
52
|
+
// e.g. Apollo tracks don't use adapters
|
|
53
|
+
return {}
|
|
54
|
+
}
|
|
55
|
+
const sessionId = getRpcSessionId(self)
|
|
56
|
+
|
|
57
|
+
return rpcManager.call(sessionId, 'CoreGetFeatureDensityStats', {
|
|
58
|
+
sessionId,
|
|
59
|
+
regions,
|
|
60
|
+
adapterConfig,
|
|
61
|
+
statusCallback: (message: string) => {
|
|
62
|
+
if (isAlive(self)) {
|
|
63
|
+
self.setMessage(message)
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
}) as Promise<FeatureDensityStats>
|
|
67
|
+
}
|
|
@@ -12,6 +12,7 @@ export default (pluginManager: PluginManager) => {
|
|
|
12
12
|
return new DisplayType({
|
|
13
13
|
name: 'LinearBareDisplay',
|
|
14
14
|
configSchema,
|
|
15
|
+
displayName: 'Bare feature display',
|
|
15
16
|
stateModel: stateModelFactory(configSchema),
|
|
16
17
|
trackType: 'BasicTrack',
|
|
17
18
|
viewType: 'LinearGenomeView',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AnyConfigurationSchemaType,
|
|
3
3
|
ConfigurationReference,
|
|
4
|
-
} from '@jbrowse/core/configuration
|
|
4
|
+
} from '@jbrowse/core/configuration'
|
|
5
5
|
import { getParentRenderProps } from '@jbrowse/core/util/tracks'
|
|
6
6
|
import { types } from 'mobx-state-tree'
|
|
7
7
|
import { BaseLinearDisplay } from '../BaseLinearDisplay'
|
|
@@ -10,15 +10,11 @@ import {
|
|
|
10
10
|
} from '@mui/material'
|
|
11
11
|
import { makeStyles } from 'tss-react/mui'
|
|
12
12
|
|
|
13
|
-
const useStyles = makeStyles()(
|
|
13
|
+
const useStyles = makeStyles()({
|
|
14
14
|
root: {
|
|
15
15
|
width: 500,
|
|
16
16
|
},
|
|
17
|
-
|
|
18
|
-
field: {
|
|
19
|
-
margin: theme.spacing(2),
|
|
20
|
-
},
|
|
21
|
-
}))
|
|
17
|
+
})
|
|
22
18
|
|
|
23
19
|
function SetMaxHeightDlg({
|
|
24
20
|
model,
|
|
@@ -26,7 +22,7 @@ function SetMaxHeightDlg({
|
|
|
26
22
|
}: {
|
|
27
23
|
model: {
|
|
28
24
|
maxHeight?: number
|
|
29
|
-
setMaxHeight:
|
|
25
|
+
setMaxHeight: (arg?: number) => void
|
|
30
26
|
}
|
|
31
27
|
handleClose: () => void
|
|
32
28
|
}) {
|
|
@@ -9,16 +9,6 @@ function configSchemaFactory(pluginManager: PluginManager) {
|
|
|
9
9
|
return ConfigurationSchema(
|
|
10
10
|
'LinearBasicDisplay',
|
|
11
11
|
{
|
|
12
|
-
/**
|
|
13
|
-
* #slot
|
|
14
|
-
*/
|
|
15
|
-
mouseover: {
|
|
16
|
-
type: 'string',
|
|
17
|
-
description: 'what to display in a given mouseover',
|
|
18
|
-
defaultValue: `jexl:get(feature,'name')`,
|
|
19
|
-
|
|
20
|
-
contextVariable: ['feature'],
|
|
21
|
-
},
|
|
22
12
|
/**
|
|
23
13
|
* #slot
|
|
24
14
|
*/
|
|
@@ -11,7 +11,7 @@ export default (pluginManager: PluginManager) => {
|
|
|
11
11
|
const config = configSchema(pluginManager)
|
|
12
12
|
return new DisplayType({
|
|
13
13
|
name: 'LinearBasicDisplay',
|
|
14
|
-
displayName: 'Basic
|
|
14
|
+
displayName: 'Basic feature display',
|
|
15
15
|
configSchema: config,
|
|
16
16
|
stateModel: modelFactory(config),
|
|
17
17
|
trackType: 'FeatureTrack',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
2
|
import { makeStyles } from 'tss-react/mui'
|
|
3
3
|
import {
|
|
4
4
|
Button,
|
|
@@ -96,14 +96,6 @@ function SequenceDialog({
|
|
|
96
96
|
const { leftOffset, rightOffset } = model
|
|
97
97
|
const loading = Boolean(sequenceChunks === undefined)
|
|
98
98
|
|
|
99
|
-
// avoid infinite looping of useEffect
|
|
100
|
-
// random note: the current selected region can't be a computed because it
|
|
101
|
-
// uses action on base1dview even though it's on the ephemeral base1dview
|
|
102
|
-
const regionsSelected = useMemo(
|
|
103
|
-
() => model.getSelectedRegions(leftOffset, rightOffset),
|
|
104
|
-
[model, leftOffset, rightOffset],
|
|
105
|
-
)
|
|
106
|
-
|
|
107
99
|
useEffect(() => {
|
|
108
100
|
let active = true
|
|
109
101
|
const controller = new AbortController()
|
|
@@ -111,18 +103,17 @@ function SequenceDialog({
|
|
|
111
103
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
112
104
|
;(async () => {
|
|
113
105
|
try {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)
|
|
120
|
-
if (active) {
|
|
121
|
-
setSequenceChunks(chunks)
|
|
122
|
-
}
|
|
123
|
-
} else {
|
|
106
|
+
// random note: the current selected region can't be a computed because
|
|
107
|
+
// it uses action on base1dview even though it's on the ephemeral
|
|
108
|
+
// base1dview
|
|
109
|
+
const selection = model.getSelectedRegions(leftOffset, rightOffset)
|
|
110
|
+
if (selection.length === 0) {
|
|
124
111
|
throw new Error('Selected region is out of bounds')
|
|
125
112
|
}
|
|
113
|
+
const chunks = await fetchSequence(model, selection, controller.signal)
|
|
114
|
+
if (active) {
|
|
115
|
+
setSequenceChunks(chunks)
|
|
116
|
+
}
|
|
126
117
|
} catch (e) {
|
|
127
118
|
console.error(e)
|
|
128
119
|
if (active) {
|
|
@@ -135,7 +126,7 @@ function SequenceDialog({
|
|
|
135
126
|
controller.abort()
|
|
136
127
|
active = false
|
|
137
128
|
}
|
|
138
|
-
}, [model, session,
|
|
129
|
+
}, [model, session, leftOffset, rightOffset])
|
|
139
130
|
|
|
140
131
|
const sequence = sequenceChunks
|
|
141
132
|
? formatSeqFasta(
|
|
@@ -146,10 +137,10 @@ function SequenceDialog({
|
|
|
146
137
|
const chunkRefName = chunk.get('refName')
|
|
147
138
|
const chunkStart = chunk.get('start') + 1
|
|
148
139
|
const chunkEnd = chunk.get('end')
|
|
149
|
-
const
|
|
140
|
+
const loc = `${chunkRefName}:${chunkStart}-${chunkEnd}`
|
|
150
141
|
if (chunkSeq?.length !== chunkEnd - chunkStart + 1) {
|
|
151
142
|
throw new Error(
|
|
152
|
-
`${
|
|
143
|
+
`${loc} returned ${chunkSeq.length.toLocaleString()} bases, but should have returned ${(
|
|
153
144
|
chunkEnd - chunkStart
|
|
154
145
|
).toLocaleString()}`,
|
|
155
146
|
)
|
|
@@ -162,8 +153,7 @@ function SequenceDialog({
|
|
|
162
153
|
chunkSeq = complement(chunkSeq)
|
|
163
154
|
}
|
|
164
155
|
return {
|
|
165
|
-
header:
|
|
166
|
-
chunkLocstring + (rev ? '-rev' : '') + (comp ? '-comp' : ''),
|
|
156
|
+
header: loc + (rev ? '-rev' : '') + (comp ? '-comp' : ''),
|
|
167
157
|
seq: chunkSeq,
|
|
168
158
|
}
|
|
169
159
|
}),
|
|
@@ -178,7 +168,7 @@ function SequenceDialog({
|
|
|
178
168
|
open
|
|
179
169
|
onClose={() => {
|
|
180
170
|
handleClose()
|
|
181
|
-
model.setOffsets(
|
|
171
|
+
model.setOffsets()
|
|
182
172
|
}}
|
|
183
173
|
title="Reference sequence"
|
|
184
174
|
>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect
|
|
1
|
+
import React, { useState, useEffect } from 'react'
|
|
2
2
|
import { makeStyles } from 'tss-react/mui'
|
|
3
3
|
import { observer } from 'mobx-react'
|
|
4
4
|
import { getSession } from '@jbrowse/core/util'
|
|
@@ -20,9 +20,6 @@ import RefNameAutocomplete from './RefNameAutocomplete'
|
|
|
20
20
|
import { fetchResults, splitLast } from './util'
|
|
21
21
|
import { LinearGenomeViewModel } from '..'
|
|
22
22
|
|
|
23
|
-
// lazies
|
|
24
|
-
const SearchResultsDialog = lazy(() => import('./SearchResultsDialog'))
|
|
25
|
-
|
|
26
23
|
const useStyles = makeStyles()(theme => ({
|
|
27
24
|
importFormContainer: {
|
|
28
25
|
padding: theme.spacing(2),
|
|
@@ -41,7 +38,7 @@ export default observer(function ({ model }: { model: LGV }) {
|
|
|
41
38
|
const { classes } = useStyles()
|
|
42
39
|
const session = getSession(model)
|
|
43
40
|
const { assemblyNames, assemblyManager, textSearchManager } = session
|
|
44
|
-
const { rankSearchResults,
|
|
41
|
+
const { rankSearchResults, error } = model
|
|
45
42
|
const [selectedAsm, setSelectedAsm] = useState(assemblyNames[0])
|
|
46
43
|
const [option, setOption] = useState<BaseResult>()
|
|
47
44
|
const searchScope = model.searchScope(selectedAsm)
|
|
@@ -85,7 +82,7 @@ export default observer(function ({ model }: { model: LGV }) {
|
|
|
85
82
|
if (option?.getDisplayString() === input && option.hasLocation()) {
|
|
86
83
|
await navToOption(option)
|
|
87
84
|
} else if (option?.results?.length) {
|
|
88
|
-
model.setSearchResults(option.results, option.getLabel())
|
|
85
|
+
model.setSearchResults(option.results, option.getLabel(), selectedAsm)
|
|
89
86
|
} else {
|
|
90
87
|
const [ref, rest] = splitLast(input, ':')
|
|
91
88
|
const allRefs = assembly?.allRefNamesWithLowerCase || []
|
|
@@ -105,7 +102,7 @@ export default observer(function ({ model }: { model: LGV }) {
|
|
|
105
102
|
})
|
|
106
103
|
|
|
107
104
|
if (results.length > 1) {
|
|
108
|
-
model.setSearchResults(results, input.toLowerCase())
|
|
105
|
+
model.setSearchResults(results, input.toLowerCase(), selectedAsm)
|
|
109
106
|
} else if (results.length === 1) {
|
|
110
107
|
await navToOption(results[0])
|
|
111
108
|
} else {
|
|
@@ -215,13 +212,6 @@ export default observer(function ({ model }: { model: LGV }) {
|
|
|
215
212
|
</Grid>
|
|
216
213
|
</form>
|
|
217
214
|
</Container>
|
|
218
|
-
{isSearchDialogDisplayed ? (
|
|
219
|
-
<SearchResultsDialog
|
|
220
|
-
model={model}
|
|
221
|
-
optAssemblyName={selectedAsm}
|
|
222
|
-
handleClose={() => model.setSearchResults(undefined, undefined)}
|
|
223
|
-
/>
|
|
224
|
-
) : null}
|
|
225
215
|
</div>
|
|
226
216
|
)
|
|
227
217
|
})
|
|
@@ -10,8 +10,6 @@ import { LinearGenomeViewModel } from '..'
|
|
|
10
10
|
import TrackContainer from './TrackContainer'
|
|
11
11
|
import TracksContainer from './TracksContainer'
|
|
12
12
|
import ImportForm from './ImportForm'
|
|
13
|
-
import GetSequenceDialog from './GetSequenceDialog'
|
|
14
|
-
import SearchResultsDialog from './SearchResultsDialog'
|
|
15
13
|
|
|
16
14
|
type LGV = LinearGenomeViewModel
|
|
17
15
|
|
|
@@ -39,18 +37,6 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
|
|
|
39
37
|
|
|
40
38
|
return (
|
|
41
39
|
<div style={{ position: 'relative' }}>
|
|
42
|
-
{model.seqDialogDisplayed ? (
|
|
43
|
-
<GetSequenceDialog
|
|
44
|
-
model={model}
|
|
45
|
-
handleClose={() => model.setGetSequenceDialogOpen(false)}
|
|
46
|
-
/>
|
|
47
|
-
) : null}
|
|
48
|
-
{model.isSearchDialogDisplayed ? (
|
|
49
|
-
<SearchResultsDialog
|
|
50
|
-
model={model}
|
|
51
|
-
handleClose={() => model.setSearchResults(undefined, undefined)}
|
|
52
|
-
/>
|
|
53
|
-
) : null}
|
|
54
40
|
<HeaderComponent model={model} />
|
|
55
41
|
<MiniControlsComponent model={model} />
|
|
56
42
|
<TracksContainer model={model}>
|
|
@@ -69,6 +69,7 @@ const useStyles = makeStyles()(theme => ({
|
|
|
69
69
|
position: 'relative',
|
|
70
70
|
},
|
|
71
71
|
overviewSvg: {
|
|
72
|
+
pointerEvents: 'none',
|
|
72
73
|
width: '100%',
|
|
73
74
|
position: 'absolute',
|
|
74
75
|
},
|
|
@@ -170,7 +171,7 @@ const OverviewBox = observer(function ({
|
|
|
170
171
|
style={{
|
|
171
172
|
left: block.offsetPx + 3,
|
|
172
173
|
color: canDisplayCytobands
|
|
173
|
-
? theme.palette.primary
|
|
174
|
+
? theme.palette.text.primary
|
|
174
175
|
: refNameColor,
|
|
175
176
|
}}
|
|
176
177
|
className={classes.scalebarRefName}
|
|
@@ -6,6 +6,7 @@ import BaseResult, {
|
|
|
6
6
|
} from '@jbrowse/core/TextSearch/BaseResults'
|
|
7
7
|
import {
|
|
8
8
|
Autocomplete,
|
|
9
|
+
AutocompleteRenderInputParams,
|
|
9
10
|
IconButton,
|
|
10
11
|
InputAdornment,
|
|
11
12
|
TextField,
|
|
@@ -30,13 +31,12 @@ export interface Option {
|
|
|
30
31
|
function aggregateResults(results: BaseResult[]) {
|
|
31
32
|
const m: { [key: string]: BaseResult[] } = {}
|
|
32
33
|
|
|
33
|
-
for (
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
m[d] = []
|
|
34
|
+
for (const result of results) {
|
|
35
|
+
const displayString = result.getDisplayString()
|
|
36
|
+
if (!m[displayString]) {
|
|
37
|
+
m[displayString] = []
|
|
38
38
|
}
|
|
39
|
-
m[
|
|
39
|
+
m[displayString].push(result)
|
|
40
40
|
}
|
|
41
41
|
return m
|
|
42
42
|
}
|
|
@@ -63,13 +63,28 @@ function getDeduplicatedResult(results: BaseResult[]) {
|
|
|
63
63
|
// because they do not have a matchedObject. the trix search results already
|
|
64
64
|
// filter so don't need re-filtering
|
|
65
65
|
function filterOptions(options: Option[], searchQuery: string) {
|
|
66
|
-
return options.filter(
|
|
67
|
-
|
|
68
|
-
return (
|
|
66
|
+
return options.filter(
|
|
67
|
+
({ result }) =>
|
|
69
68
|
result.getLabel().toLowerCase().includes(searchQuery) ||
|
|
70
|
-
result.matchedObject
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
result.matchedObject,
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getFiltered(opts: Option[], inputValue: string) {
|
|
74
|
+
const filtered = filterOptions(opts, inputValue.toLocaleLowerCase())
|
|
75
|
+
return [
|
|
76
|
+
...filtered.slice(0, 100),
|
|
77
|
+
...(filtered.length > 100
|
|
78
|
+
? [
|
|
79
|
+
{
|
|
80
|
+
group: 'limitOption',
|
|
81
|
+
result: new BaseResult({
|
|
82
|
+
label: 'keep typing for more results',
|
|
83
|
+
}),
|
|
84
|
+
},
|
|
85
|
+
]
|
|
86
|
+
: []),
|
|
87
|
+
]
|
|
73
88
|
}
|
|
74
89
|
|
|
75
90
|
function RefNameAutocomplete({
|
|
@@ -101,7 +116,6 @@ function RefNameAutocomplete({
|
|
|
101
116
|
const { assemblyManager } = session
|
|
102
117
|
const [open, setOpen] = useState(false)
|
|
103
118
|
const [loaded, setLoaded] = useState(true)
|
|
104
|
-
const [isHelpDialogDisplayed, setHelpDialogDisplayed] = useState(false)
|
|
105
119
|
const [currentSearch, setCurrentSearch] = useState('')
|
|
106
120
|
const [inputValue, setInputValue] = useState('')
|
|
107
121
|
const [searchOptions, setSearchOptions] = useState<Option[]>()
|
|
@@ -109,18 +123,17 @@ function RefNameAutocomplete({
|
|
|
109
123
|
const assembly = assemblyName ? assemblyManager.get(assemblyName) : undefined
|
|
110
124
|
const { coarseVisibleLocStrings, hasDisplayedRegions } = model
|
|
111
125
|
|
|
112
|
-
|
|
113
|
-
const regions = assembly?.regions || []
|
|
126
|
+
const regions = assembly?.regions
|
|
114
127
|
|
|
115
128
|
const options = useMemo(
|
|
116
129
|
() =>
|
|
117
|
-
regions
|
|
130
|
+
regions?.map(option => ({
|
|
118
131
|
result: new RefSequenceResult({
|
|
119
132
|
refName: option.refName,
|
|
120
133
|
label: option.refName,
|
|
121
134
|
matchedAttribute: 'refName',
|
|
122
135
|
}),
|
|
123
|
-
})),
|
|
136
|
+
})) || [],
|
|
124
137
|
[regions],
|
|
125
138
|
)
|
|
126
139
|
|
|
@@ -155,10 +168,12 @@ function RefNameAutocomplete({
|
|
|
155
168
|
|
|
156
169
|
const inputBoxVal = coarseVisibleLocStrings || value || ''
|
|
157
170
|
|
|
158
|
-
// heuristic, text width +
|
|
171
|
+
// heuristic, text width + 60 accommodates help icon and search
|
|
159
172
|
// icon
|
|
160
|
-
const
|
|
161
|
-
|
|
173
|
+
const width = Math.min(
|
|
174
|
+
Math.max(measureText(inputBoxVal, 14) + 100, minWidth),
|
|
175
|
+
maxWidth,
|
|
176
|
+
)
|
|
162
177
|
|
|
163
178
|
// notes on implementation:
|
|
164
179
|
// The selectOnFocus setting helps highlight the field when clicked
|
|
@@ -205,70 +220,77 @@ function RefNameAutocomplete({
|
|
|
205
220
|
setInputValue(inputBoxVal)
|
|
206
221
|
}}
|
|
207
222
|
options={!searchOptions?.length ? options : searchOptions}
|
|
208
|
-
getOptionDisabled={option => option
|
|
209
|
-
filterOptions={(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}),
|
|
223
|
-
},
|
|
224
|
-
]
|
|
225
|
-
: []),
|
|
226
|
-
]
|
|
227
|
-
}}
|
|
228
|
-
renderInput={params => {
|
|
229
|
-
const { helperText, InputProps = {} } = TextFieldProps
|
|
230
|
-
return (
|
|
231
|
-
<TextField
|
|
232
|
-
onBlur={() =>
|
|
233
|
-
// this is used to restore a refName or the non-user-typed input
|
|
234
|
-
// to the box on blurring
|
|
235
|
-
setInputValue(inputBoxVal)
|
|
236
|
-
}
|
|
237
|
-
{...params}
|
|
238
|
-
{...TextFieldProps}
|
|
239
|
-
helperText={helperText}
|
|
240
|
-
InputProps={{
|
|
241
|
-
...params.InputProps,
|
|
242
|
-
...InputProps,
|
|
243
|
-
|
|
244
|
-
endAdornment: (
|
|
245
|
-
<>
|
|
246
|
-
<InputAdornment position="end" style={{ marginRight: 7 }}>
|
|
247
|
-
<SearchIcon fontSize="small" />
|
|
248
|
-
{showHelp ? (
|
|
249
|
-
<IconButton
|
|
250
|
-
onClick={() => setHelpDialogDisplayed(true)}
|
|
251
|
-
size="small"
|
|
252
|
-
>
|
|
253
|
-
<HelpIcon fontSize="small" />
|
|
254
|
-
</IconButton>
|
|
255
|
-
) : null}
|
|
256
|
-
</InputAdornment>
|
|
257
|
-
{params.InputProps.endAdornment}
|
|
258
|
-
</>
|
|
259
|
-
),
|
|
260
|
-
}}
|
|
261
|
-
placeholder="Search for location"
|
|
262
|
-
onChange={e => setCurrentSearch(e.target.value)}
|
|
263
|
-
/>
|
|
264
|
-
)
|
|
265
|
-
}}
|
|
266
|
-
getOptionLabel={option =>
|
|
267
|
-
(typeof option === 'string'
|
|
268
|
-
? option
|
|
269
|
-
: option.result.getDisplayString()) || ''
|
|
223
|
+
getOptionDisabled={option => option.group === 'limitOption'}
|
|
224
|
+
filterOptions={(opts, { inputValue }) => getFiltered(opts, inputValue)}
|
|
225
|
+
renderInput={params => (
|
|
226
|
+
<AutocompleteTextField
|
|
227
|
+
showHelp={showHelp}
|
|
228
|
+
params={params}
|
|
229
|
+
inputBoxVal={inputBoxVal}
|
|
230
|
+
TextFieldProps={TextFieldProps}
|
|
231
|
+
setCurrentSearch={setCurrentSearch}
|
|
232
|
+
setInputValue={setInputValue}
|
|
233
|
+
/>
|
|
234
|
+
)}
|
|
235
|
+
getOptionLabel={opt =>
|
|
236
|
+
typeof opt === 'string' ? opt : opt.result.getDisplayString()
|
|
270
237
|
}
|
|
271
238
|
/>
|
|
239
|
+
</>
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function AutocompleteTextField({
|
|
244
|
+
TextFieldProps,
|
|
245
|
+
inputBoxVal,
|
|
246
|
+
params,
|
|
247
|
+
showHelp,
|
|
248
|
+
setInputValue,
|
|
249
|
+
setCurrentSearch,
|
|
250
|
+
}: {
|
|
251
|
+
TextFieldProps: TFP
|
|
252
|
+
inputBoxVal: string
|
|
253
|
+
showHelp?: boolean
|
|
254
|
+
params: AutocompleteRenderInputParams
|
|
255
|
+
setInputValue: (arg: string) => void
|
|
256
|
+
setCurrentSearch: (arg: string) => void
|
|
257
|
+
}) {
|
|
258
|
+
const { helperText, InputProps = {} } = TextFieldProps
|
|
259
|
+
return (
|
|
260
|
+
<TextField
|
|
261
|
+
onBlur={() =>
|
|
262
|
+
// this is used to restore a refName or the non-user-typed input
|
|
263
|
+
// to the box on blurring
|
|
264
|
+
setInputValue(inputBoxVal)
|
|
265
|
+
}
|
|
266
|
+
{...params}
|
|
267
|
+
{...TextFieldProps}
|
|
268
|
+
size="small"
|
|
269
|
+
helperText={helperText}
|
|
270
|
+
InputProps={{
|
|
271
|
+
...params.InputProps,
|
|
272
|
+
...InputProps,
|
|
273
|
+
|
|
274
|
+
endAdornment: (
|
|
275
|
+
<EndAdornment
|
|
276
|
+
showHelp={showHelp}
|
|
277
|
+
endAdornment={params.InputProps.endAdornment}
|
|
278
|
+
/>
|
|
279
|
+
),
|
|
280
|
+
}}
|
|
281
|
+
placeholder="Search for location"
|
|
282
|
+
onChange={e => setCurrentSearch(e.target.value)}
|
|
283
|
+
/>
|
|
284
|
+
)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function HelpAdornment() {
|
|
288
|
+
const [isHelpDialogDisplayed, setHelpDialogDisplayed] = useState(false)
|
|
289
|
+
return (
|
|
290
|
+
<>
|
|
291
|
+
<IconButton onClick={() => setHelpDialogDisplayed(true)} size="small">
|
|
292
|
+
<HelpIcon fontSize="small" />
|
|
293
|
+
</IconButton>
|
|
272
294
|
{isHelpDialogDisplayed ? (
|
|
273
295
|
<Suspense fallback={<div />}>
|
|
274
296
|
<HelpDialog handleClose={() => setHelpDialogDisplayed(false)} />
|
|
@@ -278,4 +300,22 @@ function RefNameAutocomplete({
|
|
|
278
300
|
)
|
|
279
301
|
}
|
|
280
302
|
|
|
303
|
+
function EndAdornment({
|
|
304
|
+
showHelp,
|
|
305
|
+
endAdornment,
|
|
306
|
+
}: {
|
|
307
|
+
showHelp?: boolean
|
|
308
|
+
endAdornment: React.ReactNode
|
|
309
|
+
}) {
|
|
310
|
+
return (
|
|
311
|
+
<>
|
|
312
|
+
<InputAdornment position="end" style={{ marginRight: 7 }}>
|
|
313
|
+
<SearchIcon fontSize="small" />
|
|
314
|
+
{showHelp ? <HelpAdornment /> : null}
|
|
315
|
+
</InputAdornment>
|
|
316
|
+
{endAdornment}
|
|
317
|
+
</>
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
|
|
281
321
|
export default observer(RefNameAutocomplete)
|