@jbrowse/plugin-linear-comparative-view 2.15.3 → 2.16.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/LaunchLinearSyntenyView.js +41 -11
- package/dist/LinearComparativeDisplay/stateModelFactory.d.ts +14 -9
- package/dist/LinearComparativeDisplay/stateModelFactory.js +8 -9
- package/dist/LinearComparativeView/components/Header.d.ts +2 -3
- package/dist/LinearComparativeView/components/Header.js +72 -62
- package/dist/LinearComparativeView/components/HeaderSearchBoxes.d.ts +6 -0
- package/dist/LinearComparativeView/components/HeaderSearchBoxes.js +34 -0
- package/dist/LinearComparativeView/components/LinearComparativeRenderArea.d.ts +6 -0
- package/dist/LinearComparativeView/components/LinearComparativeRenderArea.js +61 -0
- package/dist/LinearComparativeView/components/LinearComparativeView.d.ts +2 -4
- package/dist/LinearComparativeView/components/LinearComparativeView.js +3 -67
- package/dist/LinearComparativeView/components/Rubberband.js +1 -1
- package/dist/LinearComparativeView/index.js +3 -0
- package/dist/LinearComparativeView/model.d.ts +265 -12
- package/dist/LinearComparativeView/model.js +45 -75
- package/dist/LinearSyntenyDisplay/afterAttach.js +5 -3
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +32 -24
- package/dist/LinearSyntenyDisplay/components/SyntenyContextMenu.js +12 -6
- package/dist/LinearSyntenyDisplay/components/util.d.ts +2 -1
- package/dist/LinearSyntenyDisplay/components/util.js +5 -5
- package/dist/LinearSyntenyDisplay/drawSynteny.d.ts +1 -1
- package/dist/LinearSyntenyDisplay/drawSynteny.js +28 -22
- package/dist/LinearSyntenyDisplay/index.js +1 -1
- package/dist/LinearSyntenyDisplay/model.d.ts +12 -11
- package/dist/LinearSyntenyDisplay/model.js +7 -0
- package/dist/LinearSyntenyView/components/ImportForm/{ImportCustomTrack.d.ts → AddCustomTrack.d.ts} +2 -3
- package/dist/LinearSyntenyView/components/ImportForm/{ImportCustomTrack.js → AddCustomTrack.js} +3 -3
- package/dist/LinearSyntenyView/components/ImportForm/LinearSyntenyImportForm.js +195 -0
- package/dist/LinearSyntenyView/components/ImportForm/Spacer.d.ts +2 -0
- package/dist/LinearSyntenyView/components/ImportForm/Spacer.js +10 -0
- package/dist/LinearSyntenyView/components/ImportForm/TrackSelector.d.ts +10 -0
- package/dist/LinearSyntenyView/components/ImportForm/{ImportSyntenyTrackSelector.js → TrackSelector.js} +15 -20
- package/dist/LinearSyntenyView/components/ImportForm/TrackSelectorUtil.d.ts +14 -0
- package/dist/LinearSyntenyView/components/ImportForm/TrackSelectorUtil.js +52 -0
- package/dist/LinearSyntenyView/components/LinearSyntenyView.js +3 -3
- package/dist/LinearSyntenyView/index.js +1 -1
- package/dist/LinearSyntenyView/model.d.ts +267 -9
- package/dist/LinearSyntenyView/model.js +2 -2
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearGenomeView.d.ts +12 -0
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearGenomeView.js +19 -0
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.d.ts +1 -3
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +36 -27
- package/dist/LinearSyntenyViewHelper/index.d.ts +2 -0
- package/dist/LinearSyntenyViewHelper/index.js +25 -0
- package/dist/LinearSyntenyViewHelper/stateModelFactory.d.ts +30 -0
- package/dist/LinearSyntenyViewHelper/stateModelFactory.js +105 -0
- package/dist/index.js +2 -0
- package/esm/LaunchLinearSyntenyView.js +41 -11
- package/esm/LinearComparativeDisplay/stateModelFactory.d.ts +14 -9
- package/esm/LinearComparativeDisplay/stateModelFactory.js +9 -10
- package/esm/LinearComparativeView/components/Header.d.ts +2 -3
- package/esm/LinearComparativeView/components/Header.js +73 -63
- package/esm/LinearComparativeView/components/HeaderSearchBoxes.d.ts +6 -0
- package/esm/LinearComparativeView/components/HeaderSearchBoxes.js +29 -0
- package/esm/LinearComparativeView/components/LinearComparativeRenderArea.d.ts +6 -0
- package/esm/LinearComparativeView/components/LinearComparativeRenderArea.js +56 -0
- package/esm/LinearComparativeView/components/LinearComparativeView.d.ts +2 -4
- package/esm/LinearComparativeView/components/LinearComparativeView.js +3 -67
- package/esm/LinearComparativeView/components/Rubberband.js +1 -1
- package/esm/LinearComparativeView/index.js +3 -0
- package/esm/LinearComparativeView/model.d.ts +265 -12
- package/esm/LinearComparativeView/model.js +47 -77
- package/esm/LinearSyntenyDisplay/afterAttach.js +6 -4
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +33 -25
- package/esm/LinearSyntenyDisplay/components/SyntenyContextMenu.js +12 -6
- package/esm/LinearSyntenyDisplay/components/util.d.ts +2 -1
- package/esm/LinearSyntenyDisplay/components/util.js +5 -5
- package/esm/LinearSyntenyDisplay/drawSynteny.d.ts +1 -1
- package/esm/LinearSyntenyDisplay/drawSynteny.js +28 -22
- package/esm/LinearSyntenyDisplay/index.js +1 -1
- package/esm/LinearSyntenyDisplay/model.d.ts +12 -11
- package/esm/LinearSyntenyDisplay/model.js +8 -1
- package/esm/LinearSyntenyView/components/ImportForm/{ImportCustomTrack.d.ts → AddCustomTrack.d.ts} +2 -3
- package/esm/LinearSyntenyView/components/ImportForm/{ImportCustomTrack.js → AddCustomTrack.js} +3 -3
- package/esm/LinearSyntenyView/components/ImportForm/LinearSyntenyImportForm.js +167 -0
- package/esm/LinearSyntenyView/components/ImportForm/Spacer.d.ts +2 -0
- package/esm/LinearSyntenyView/components/ImportForm/Spacer.js +4 -0
- package/esm/LinearSyntenyView/components/ImportForm/TrackSelector.d.ts +10 -0
- package/esm/LinearSyntenyView/components/ImportForm/{ImportSyntenyTrackSelector.js → TrackSelector.js} +15 -20
- package/esm/LinearSyntenyView/components/ImportForm/TrackSelectorUtil.d.ts +14 -0
- package/esm/LinearSyntenyView/components/ImportForm/TrackSelectorUtil.js +23 -0
- package/esm/LinearSyntenyView/components/LinearSyntenyView.js +3 -3
- package/esm/LinearSyntenyView/index.js +1 -1
- package/esm/LinearSyntenyView/model.d.ts +267 -9
- package/esm/LinearSyntenyView/model.js +2 -2
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearGenomeView.d.ts +12 -0
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearGenomeView.js +13 -0
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.d.ts +1 -3
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +38 -29
- package/esm/LinearSyntenyViewHelper/index.d.ts +2 -0
- package/esm/LinearSyntenyViewHelper/index.js +19 -0
- package/esm/LinearSyntenyViewHelper/stateModelFactory.d.ts +30 -0
- package/esm/LinearSyntenyViewHelper/stateModelFactory.js +102 -0
- package/esm/index.js +2 -0
- package/package.json +2 -2
- package/dist/LinearSyntenyView/components/ImportForm/ImportSyntenyTrackSelector.d.ts +0 -9
- package/dist/LinearSyntenyView/components/ImportForm/index.js +0 -138
- package/esm/LinearSyntenyView/components/ImportForm/ImportSyntenyTrackSelector.d.ts +0 -9
- package/esm/LinearSyntenyView/components/ImportForm/index.js +0 -110
- /package/dist/LinearSyntenyView/components/ImportForm/{index.d.ts → LinearSyntenyImportForm.d.ts} +0 -0
- /package/esm/LinearSyntenyView/components/ImportForm/{index.d.ts → LinearSyntenyImportForm.d.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const LinearComparativeView_1 = __importDefault(require("./LinearComparativeView
|
|
|
11
11
|
const LinearSyntenyDisplay_1 = __importDefault(require("./LinearSyntenyDisplay"));
|
|
12
12
|
const LGVSyntenyDisplay_1 = __importDefault(require("./LGVSyntenyDisplay"));
|
|
13
13
|
const LinearSyntenyView_1 = __importDefault(require("./LinearSyntenyView"));
|
|
14
|
+
const LinearSyntenyViewHelper_1 = __importDefault(require("./LinearSyntenyViewHelper"));
|
|
14
15
|
const LaunchLinearSyntenyView_1 = __importDefault(require("./LaunchLinearSyntenyView"));
|
|
15
16
|
const SyntenyTrack_1 = __importDefault(require("./SyntenyTrack"));
|
|
16
17
|
const LinearReadVsRef_1 = __importDefault(require("./LinearReadVsRef"));
|
|
@@ -20,6 +21,7 @@ class LinearComparativeViewPlugin extends Plugin_1.default {
|
|
|
20
21
|
this.name = 'LinearComparativeViewPlugin';
|
|
21
22
|
}
|
|
22
23
|
install(pluginManager) {
|
|
24
|
+
(0, LinearSyntenyViewHelper_1.default)(pluginManager);
|
|
23
25
|
(0, LinearComparativeView_1.default)(pluginManager);
|
|
24
26
|
(0, LinearSyntenyView_1.default)(pluginManager);
|
|
25
27
|
(0, LinearComparativeDisplay_1.default)(pluginManager);
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { notEmpty } from '@jbrowse/core/util';
|
|
1
2
|
import { when } from 'mobx';
|
|
3
|
+
function makeMultiDimArray(str) {
|
|
4
|
+
return Array.isArray(str[0]) ? str : [str];
|
|
5
|
+
}
|
|
2
6
|
export default function LaunchLinearSyntenyView(pluginManager) {
|
|
3
7
|
pluginManager.addToExtensionPoint('LaunchView-LinearSyntenyView',
|
|
4
8
|
// @ts-expect-error
|
|
@@ -21,7 +25,7 @@ export default function LaunchLinearSyntenyView(pluginManager) {
|
|
|
21
25
|
};
|
|
22
26
|
})));
|
|
23
27
|
await Promise.all(model.views.map(view => when(() => view.initialized)));
|
|
24
|
-
|
|
28
|
+
let idsNotFound = [];
|
|
25
29
|
await Promise.all(views.map(async (data, idx) => {
|
|
26
30
|
const view = model.views[idx];
|
|
27
31
|
const { assembly, loc, tracks = [] } = data;
|
|
@@ -30,14 +34,23 @@ export default function LaunchLinearSyntenyView(pluginManager) {
|
|
|
30
34
|
throw new Error(`Assembly ${data.assembly} failed to load`);
|
|
31
35
|
}
|
|
32
36
|
await view.navToSearchString({ input: loc, assembly: asm });
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
idsNotFound = [
|
|
38
|
+
...idsNotFound,
|
|
39
|
+
...tracks.map(trackId => tryTrackLGV({
|
|
40
|
+
model: view,
|
|
41
|
+
trackId,
|
|
42
|
+
})),
|
|
43
|
+
];
|
|
36
44
|
}));
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
idsNotFound = [
|
|
46
|
+
...idsNotFound,
|
|
47
|
+
...makeMultiDimArray(tracks).flatMap((trackSet, level) => trackSet.map(trackId => tryTrackSynteny({
|
|
48
|
+
model,
|
|
49
|
+
trackId,
|
|
50
|
+
level,
|
|
51
|
+
}))),
|
|
52
|
+
];
|
|
53
|
+
if (idsNotFound.filter(notEmpty).length) {
|
|
41
54
|
throw new Error(`Could not resolve identifiers: ${idsNotFound.join(',')}`);
|
|
42
55
|
}
|
|
43
56
|
}
|
|
@@ -47,16 +60,33 @@ export default function LaunchLinearSyntenyView(pluginManager) {
|
|
|
47
60
|
}
|
|
48
61
|
});
|
|
49
62
|
}
|
|
50
|
-
function
|
|
63
|
+
function tryTrackLGV({ model, trackId, }) {
|
|
51
64
|
try {
|
|
52
65
|
model.showTrack(trackId);
|
|
53
66
|
}
|
|
54
67
|
catch (e) {
|
|
55
|
-
if (/Could not resolve identifier/.exec(`${e}`)
|
|
56
|
-
|
|
68
|
+
if (/Could not resolve identifier/.exec(`${e}`) ||
|
|
69
|
+
/track not found/.exec(`${e}`)) {
|
|
70
|
+
return trackId;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
function tryTrackSynteny({ model, trackId, level, }) {
|
|
79
|
+
try {
|
|
80
|
+
model.showTrack(trackId, level);
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
if (/Could not resolve identifier/.exec(`${e}`) ||
|
|
84
|
+
/track not found/.exec(`${e}`)) {
|
|
85
|
+
return trackId;
|
|
57
86
|
}
|
|
58
87
|
else {
|
|
59
88
|
throw e;
|
|
60
89
|
}
|
|
61
90
|
}
|
|
91
|
+
return undefined;
|
|
62
92
|
}
|
|
@@ -11,9 +11,14 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
11
11
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
12
12
|
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
13
13
|
} & {
|
|
14
|
+
/**
|
|
15
|
+
* #property
|
|
16
|
+
*/
|
|
14
17
|
type: import("mobx-state-tree").ISimpleType<"LinearComparativeDisplay">;
|
|
18
|
+
/**
|
|
19
|
+
* #property
|
|
20
|
+
*/
|
|
15
21
|
configuration: AnyConfigurationSchemaType;
|
|
16
|
-
height: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
17
22
|
}, {
|
|
18
23
|
rendererTypeName: string;
|
|
19
24
|
error: unknown;
|
|
@@ -24,9 +29,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
24
29
|
id: string;
|
|
25
30
|
type: string;
|
|
26
31
|
rpcDriverName: string | undefined;
|
|
27
|
-
} & import("mobx-state-tree/dist/internal"
|
|
28
|
-
* #property
|
|
29
|
-
*/).NonEmptyObject & {
|
|
32
|
+
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
30
33
|
rendererTypeName: string;
|
|
31
34
|
error: unknown;
|
|
32
35
|
message: string | undefined;
|
|
@@ -99,7 +102,6 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
99
102
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & any & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>);
|
|
100
103
|
} & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>);
|
|
101
104
|
} & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>;
|
|
102
|
-
height: number;
|
|
103
105
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
104
106
|
rendererTypeName: string;
|
|
105
107
|
error: unknown;
|
|
@@ -110,9 +112,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
110
112
|
id: string;
|
|
111
113
|
type: string;
|
|
112
114
|
rpcDriverName: string | undefined;
|
|
113
|
-
} & import("mobx-state-tree/dist/internal"
|
|
114
|
-
* #property
|
|
115
|
-
*/).NonEmptyObject & {
|
|
115
|
+
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
116
116
|
rendererTypeName: string;
|
|
117
117
|
error: unknown;
|
|
118
118
|
message: string | undefined;
|
|
@@ -169,9 +169,14 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
169
169
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
170
170
|
rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
171
171
|
} & {
|
|
172
|
+
/**
|
|
173
|
+
* #property
|
|
174
|
+
*/
|
|
172
175
|
type: import("mobx-state-tree").ISimpleType<"LinearComparativeDisplay">;
|
|
176
|
+
/**
|
|
177
|
+
* #property
|
|
178
|
+
*/
|
|
173
179
|
configuration: AnyConfigurationSchemaType;
|
|
174
|
-
height: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
175
180
|
}, {
|
|
176
181
|
rendererTypeName: string;
|
|
177
182
|
error: unknown;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readConfObject, ConfigurationReference, } from '@jbrowse/core/configuration';
|
|
2
|
-
import { types, getSnapshot } from 'mobx-state-tree';
|
|
2
|
+
import { types, getSnapshot, getParent } from 'mobx-state-tree';
|
|
3
3
|
import { dedupe, getContainingView, getSession, makeAbortableReaction, } from '@jbrowse/core/util';
|
|
4
4
|
import { getRpcSessionId } from '@jbrowse/core/util/tracks';
|
|
5
5
|
import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes/models';
|
|
@@ -19,10 +19,6 @@ function stateModelFactory(configSchema) {
|
|
|
19
19
|
* #property
|
|
20
20
|
*/
|
|
21
21
|
configuration: ConfigurationReference(configSchema),
|
|
22
|
-
/**
|
|
23
|
-
* #property
|
|
24
|
-
*/
|
|
25
|
-
height: 100,
|
|
26
22
|
}))
|
|
27
23
|
.volatile(( /* self */) => ({
|
|
28
24
|
renderInProgress: undefined,
|
|
@@ -131,8 +127,9 @@ function stateModelFactory(configSchema) {
|
|
|
131
127
|
function renderBlockData(self) {
|
|
132
128
|
const { rpcManager } = getSession(self);
|
|
133
129
|
const display = self;
|
|
134
|
-
// Alternative to readConfObject(config) is below used because
|
|
135
|
-
// something under our control. Compare to
|
|
130
|
+
// Alternative to readConfObject(config) is below used because
|
|
131
|
+
// renderProps is something under our control. Compare to
|
|
132
|
+
// serverSideRenderedBlock
|
|
136
133
|
readConfObject(self.configuration);
|
|
137
134
|
const { adapterConfig } = self;
|
|
138
135
|
const parent = getContainingView(self);
|
|
@@ -143,6 +140,8 @@ function renderBlockData(self) {
|
|
|
143
140
|
rpcManager,
|
|
144
141
|
renderProps: {
|
|
145
142
|
...display.renderProps(),
|
|
143
|
+
// @ts-expect-error
|
|
144
|
+
level: getParent(self, 4).level,
|
|
146
145
|
view: parent,
|
|
147
146
|
adapterConfig,
|
|
148
147
|
sessionId,
|
|
@@ -157,10 +156,10 @@ async function renderBlockEffect(props) {
|
|
|
157
156
|
return;
|
|
158
157
|
}
|
|
159
158
|
const { rpcManager, renderProps } = props;
|
|
160
|
-
const { adapterConfig } = renderProps;
|
|
161
|
-
const
|
|
159
|
+
const { adapterConfig, level } = renderProps;
|
|
160
|
+
const view = renderProps.view.views[level];
|
|
162
161
|
const features = (await rpcManager.call('getFeats', 'CoreGetFeatures', {
|
|
163
|
-
regions:
|
|
162
|
+
regions: view.staticBlocks.contentBlocks,
|
|
164
163
|
sessionId: 'getFeats',
|
|
165
164
|
adapterConfig,
|
|
166
165
|
}));
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { LinearComparativeViewModel } from '../model';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
model: LCV;
|
|
3
|
+
declare const Header: ({ model, }: {
|
|
4
|
+
model: LinearComparativeViewModel;
|
|
6
5
|
}) => React.JSX.Element;
|
|
7
6
|
export default Header;
|
|
@@ -1,74 +1,84 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import { IconButton, Typography } from '@mui/material';
|
|
3
|
-
import { makeStyles } from 'tss-react/mui';
|
|
4
|
-
import { SearchBox } from '@jbrowse/plugin-linear-genome-view';
|
|
5
2
|
import { observer } from 'mobx-react';
|
|
6
|
-
import {
|
|
3
|
+
import { FormGroup } from '@mui/material';
|
|
4
|
+
import { makeStyles } from 'tss-react/mui';
|
|
5
|
+
import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton';
|
|
7
6
|
// icons
|
|
8
7
|
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
|
8
|
+
import SearchIcon from '@mui/icons-material/Search';
|
|
9
9
|
import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons';
|
|
10
|
-
import
|
|
11
|
-
const useStyles = makeStyles()(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
display: 'flex',
|
|
15
|
-
},
|
|
16
|
-
spacer: {
|
|
17
|
-
flexGrow: 1,
|
|
18
|
-
},
|
|
19
|
-
iconButton: {
|
|
20
|
-
margin: 5,
|
|
21
|
-
},
|
|
22
|
-
bp: {
|
|
23
|
-
display: 'flex',
|
|
24
|
-
alignItems: 'center',
|
|
25
|
-
marginLeft: 10,
|
|
26
|
-
},
|
|
27
|
-
searchContainer: {
|
|
28
|
-
marginLeft: 5,
|
|
29
|
-
},
|
|
30
|
-
searchBox: {
|
|
31
|
-
display: 'flex',
|
|
10
|
+
import HeaderSearchBoxes from './HeaderSearchBoxes';
|
|
11
|
+
const useStyles = makeStyles()({
|
|
12
|
+
inline: {
|
|
13
|
+
display: 'inline-flex',
|
|
32
14
|
},
|
|
33
|
-
}));
|
|
34
|
-
const TrackSelector = observer(({ model }) => {
|
|
35
|
-
return (React.createElement(CascadingMenuButton, { menuItems: [
|
|
36
|
-
{
|
|
37
|
-
label: 'Synteny track selector',
|
|
38
|
-
onClick: () => model.activateTrackSelector(),
|
|
39
|
-
},
|
|
40
|
-
...model.views.map((view, idx) => ({
|
|
41
|
-
label: `View ${idx + 1} track selector`,
|
|
42
|
-
onClick: () => view.activateTrackSelector(),
|
|
43
|
-
})),
|
|
44
|
-
] },
|
|
45
|
-
React.createElement(TrackSelectorIcon, null)));
|
|
46
15
|
});
|
|
47
|
-
const Header = observer(function ({ model }) {
|
|
16
|
+
const Header = observer(function ({ model, }) {
|
|
48
17
|
const { classes } = useStyles();
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
React.createElement(
|
|
54
|
-
|
|
55
|
-
|
|
18
|
+
const { views } = model;
|
|
19
|
+
const [showSearchBoxes, setShowSearchBoxes] = useState(views.length <= 3);
|
|
20
|
+
const [sideBySide, setSideBySide] = useState(views.length <= 3);
|
|
21
|
+
return (React.createElement(FormGroup, { row: true },
|
|
22
|
+
React.createElement(CascadingMenuButton, { menuItems: [
|
|
23
|
+
{
|
|
24
|
+
label: 'Synteny track selectors',
|
|
25
|
+
type: 'subMenu',
|
|
26
|
+
subMenu: views.slice(0, -1).map((_, idx) => ({
|
|
27
|
+
label: `Row ${idx + 1}->${idx + 2} (${views[idx].assemblyNames.join(',')}->${views[idx + 1].assemblyNames.join(',')})`,
|
|
28
|
+
onClick: () => {
|
|
29
|
+
model.activateTrackSelector(idx);
|
|
30
|
+
},
|
|
31
|
+
})),
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: 'Row track selectors',
|
|
35
|
+
type: 'subMenu',
|
|
36
|
+
subMenu: views.map((view, idx) => ({
|
|
37
|
+
label: `Row ${idx + 1} track selector (${view.assemblyNames.join(',')})`,
|
|
38
|
+
onClick: () => view.activateTrackSelector(),
|
|
39
|
+
})),
|
|
40
|
+
},
|
|
41
|
+
] },
|
|
42
|
+
React.createElement(TrackSelectorIcon, null)),
|
|
43
|
+
React.createElement(CascadingMenuButton, { menuItems: [
|
|
44
|
+
{
|
|
45
|
+
label: 'Row view menus',
|
|
46
|
+
type: 'subMenu',
|
|
47
|
+
subMenu: views.map((view, idx) => ({
|
|
48
|
+
label: `View ${idx + 1} Menu`,
|
|
49
|
+
subMenu: view.menuItems(),
|
|
50
|
+
})),
|
|
51
|
+
},
|
|
52
|
+
...model.headerMenuItems(),
|
|
53
|
+
] },
|
|
56
54
|
React.createElement(MoreVertIcon, null)),
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
55
|
+
React.createElement(CascadingMenuButton, { menuItems: [
|
|
56
|
+
{
|
|
57
|
+
label: 'Show search boxes',
|
|
58
|
+
type: 'checkbox',
|
|
59
|
+
checked: showSearchBoxes,
|
|
60
|
+
onClick: () => {
|
|
61
|
+
setShowSearchBoxes(!showSearchBoxes);
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: 'Orientation - Side-by-side',
|
|
66
|
+
type: 'radio',
|
|
67
|
+
checked: sideBySide,
|
|
68
|
+
onClick: () => {
|
|
69
|
+
setSideBySide(!sideBySide);
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
label: 'Orientation - Vertical',
|
|
74
|
+
type: 'radio',
|
|
75
|
+
checked: !sideBySide,
|
|
76
|
+
onClick: () => {
|
|
77
|
+
setSideBySide(!sideBySide);
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
] },
|
|
81
|
+
React.createElement(SearchIcon, null)),
|
|
82
|
+
showSearchBoxes ? (React.createElement("span", { className: sideBySide ? classes.inline : undefined }, views.map(view => (React.createElement(HeaderSearchBoxes, { key: view.id, view: view }))))) : null));
|
|
73
83
|
});
|
|
74
84
|
export default Header;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { observer } from 'mobx-react';
|
|
3
|
+
import { Typography } from '@mui/material';
|
|
4
|
+
import { makeStyles } from 'tss-react/mui';
|
|
5
|
+
// jbrowse
|
|
6
|
+
import { SearchBox, } from '@jbrowse/plugin-linear-genome-view';
|
|
7
|
+
import { toLocale } from '@jbrowse/core/util';
|
|
8
|
+
const useStyles = makeStyles()(() => ({
|
|
9
|
+
bp: {
|
|
10
|
+
display: 'flex',
|
|
11
|
+
alignItems: 'center',
|
|
12
|
+
marginLeft: 10,
|
|
13
|
+
},
|
|
14
|
+
searchBox: {
|
|
15
|
+
display: 'flex',
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
const HeaderSearchBoxes = observer(function ({ view, }) {
|
|
19
|
+
const { classes } = useStyles();
|
|
20
|
+
const { assemblyNames, coarseTotalBp } = view;
|
|
21
|
+
return (React.createElement("span", { className: classes.searchBox },
|
|
22
|
+
React.createElement(SearchBox, { model: view, showHelp: false }),
|
|
23
|
+
React.createElement(Typography, { variant: "body2", color: "textSecondary", className: classes.bp },
|
|
24
|
+
assemblyNames.join(','),
|
|
25
|
+
" ",
|
|
26
|
+
toLocale(Math.round(coarseTotalBp)),
|
|
27
|
+
" bp")));
|
|
28
|
+
});
|
|
29
|
+
export default HeaderSearchBoxes;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { makeStyles } from 'tss-react/mui';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
4
|
+
import { getEnv } from '@jbrowse/core/util';
|
|
5
|
+
import { ResizeHandle } from '@jbrowse/core/ui';
|
|
6
|
+
import { getConf } from '@jbrowse/core/configuration';
|
|
7
|
+
const useStyles = makeStyles()({
|
|
8
|
+
container: {
|
|
9
|
+
display: 'grid',
|
|
10
|
+
},
|
|
11
|
+
overlay: {
|
|
12
|
+
zIndex: 100,
|
|
13
|
+
gridArea: '1/1',
|
|
14
|
+
},
|
|
15
|
+
resizeHandle: {
|
|
16
|
+
height: 4,
|
|
17
|
+
background: '#ccc',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
function View({ view }) {
|
|
21
|
+
const { pluginManager } = getEnv(view);
|
|
22
|
+
const { ReactComponent } = pluginManager.getViewType(view.type);
|
|
23
|
+
return React.createElement(ReactComponent, { model: view });
|
|
24
|
+
}
|
|
25
|
+
const LinearComparativeRenderArea = observer(function ({ model, }) {
|
|
26
|
+
const { classes } = useStyles();
|
|
27
|
+
const { views, levels } = model;
|
|
28
|
+
const RenderList = [
|
|
29
|
+
React.createElement(View, { key: views[0].id, view: views[0] }),
|
|
30
|
+
];
|
|
31
|
+
for (let i = 1; i < views.length; i++) {
|
|
32
|
+
const view = views[i];
|
|
33
|
+
const level = levels[i - 1];
|
|
34
|
+
RenderList.push(React.createElement(React.Fragment, { key: view.id },
|
|
35
|
+
React.createElement("div", { className: classes.container },
|
|
36
|
+
React.createElement(Overlays, { model: model, level: i - 1 })),
|
|
37
|
+
React.createElement(ResizeHandle, { onDrag: n => level === null || level === void 0 ? void 0 : level.setHeight(level.height + n), className: classes.resizeHandle }),
|
|
38
|
+
React.createElement(View, { view: view })));
|
|
39
|
+
}
|
|
40
|
+
return React.createElement("div", { className: classes.container }, RenderList);
|
|
41
|
+
});
|
|
42
|
+
const Overlays = observer(function ({ model, level, }) {
|
|
43
|
+
var _a;
|
|
44
|
+
const { classes } = useStyles();
|
|
45
|
+
return (React.createElement(React.Fragment, null, (_a = model.levels[level]) === null || _a === void 0 ? void 0 : _a.tracks.map(track => {
|
|
46
|
+
const [display] = track.displays;
|
|
47
|
+
const { RenderingComponent } = display;
|
|
48
|
+
const trackId = getConf(track, 'trackId');
|
|
49
|
+
return RenderingComponent ? (React.createElement("div", { className: classes.overlay, key: trackId, style: {
|
|
50
|
+
height: display.height,
|
|
51
|
+
overflow: 'hidden',
|
|
52
|
+
} },
|
|
53
|
+
React.createElement(RenderingComponent, { model: display }))) : null;
|
|
54
|
+
})));
|
|
55
|
+
});
|
|
56
|
+
export default LinearComparativeRenderArea;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { LinearComparativeViewModel } from '../model';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ExtraButtons?: React.ReactNode;
|
|
6
|
-
model: LCV;
|
|
3
|
+
declare const LinearComparativeView: ({ model, }: {
|
|
4
|
+
model: LinearComparativeViewModel;
|
|
7
5
|
}) => React.JSX.Element;
|
|
8
6
|
export default LinearComparativeView;
|
|
@@ -1,29 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { makeStyles } from 'tss-react/mui';
|
|
3
3
|
import { observer } from 'mobx-react';
|
|
4
|
-
import { getConf } from '@jbrowse/core/configuration';
|
|
5
|
-
import { getEnv } from '@jbrowse/core/util';
|
|
6
|
-
import { ResizeHandle } from '@jbrowse/core/ui';
|
|
7
4
|
import Rubberband from './Rubberband';
|
|
8
5
|
import Header from './Header';
|
|
6
|
+
import LinearComparativeRenderArea from './LinearComparativeRenderArea';
|
|
9
7
|
const useStyles = makeStyles()(theme => ({
|
|
10
|
-
container: {
|
|
11
|
-
display: 'grid',
|
|
12
|
-
},
|
|
13
|
-
overlay: {
|
|
14
|
-
zIndex: 100,
|
|
15
|
-
gridArea: '1/1',
|
|
16
|
-
},
|
|
17
|
-
content: {
|
|
18
|
-
gridArea: '1/1',
|
|
19
|
-
position: 'relative',
|
|
20
|
-
},
|
|
21
|
-
grid: {
|
|
22
|
-
display: 'grid',
|
|
23
|
-
},
|
|
24
|
-
relative: {
|
|
25
|
-
position: 'relative',
|
|
26
|
-
},
|
|
27
8
|
// this helps keep the vertical guide inside the parent view container,
|
|
28
9
|
// similar style exists in the single LGV's trackscontainer
|
|
29
10
|
rubberbandContainer: {
|
|
@@ -39,56 +20,11 @@ const useStyles = makeStyles()(theme => ({
|
|
|
39
20
|
},
|
|
40
21
|
},
|
|
41
22
|
}));
|
|
42
|
-
const
|
|
23
|
+
const LinearComparativeView = observer(function ({ model, }) {
|
|
43
24
|
const { classes } = useStyles();
|
|
44
|
-
return (React.createElement(React.Fragment, null, model.tracks.map(track => {
|
|
45
|
-
const [display] = track.displays;
|
|
46
|
-
const { RenderingComponent } = display;
|
|
47
|
-
const trackId = getConf(track, 'trackId');
|
|
48
|
-
return RenderingComponent ? (React.createElement("div", { className: classes.overlay, key: trackId, style: {
|
|
49
|
-
height: model.middleComparativeHeight,
|
|
50
|
-
overflow: 'hidden',
|
|
51
|
-
} },
|
|
52
|
-
React.createElement(RenderingComponent, { model: display }))) : null;
|
|
53
|
-
})));
|
|
54
|
-
});
|
|
55
|
-
// The comparative is in the middle of the views
|
|
56
|
-
const MiddleComparativeView = observer(({ model }) => {
|
|
57
|
-
const { classes } = useStyles();
|
|
58
|
-
const { views } = model;
|
|
59
|
-
const { pluginManager } = getEnv(model);
|
|
60
|
-
const { ReactComponent } = pluginManager.getViewType(views[0].type);
|
|
61
25
|
return (React.createElement("div", { className: classes.rubberbandContainer },
|
|
62
26
|
React.createElement(Header, { model: model }),
|
|
63
27
|
React.createElement(Rubberband, { model: model, ControlComponent: React.createElement("div", { className: classes.rubberbandDiv }) }),
|
|
64
|
-
React.createElement(
|
|
65
|
-
React.createElement(ReactComponent, { model: views[0] }),
|
|
66
|
-
React.createElement("div", { className: classes.grid },
|
|
67
|
-
React.createElement(Overlays, { model: model })),
|
|
68
|
-
React.createElement(ResizeHandle, { onDrag: n => model.setMiddleComparativeHeight(model.middleComparativeHeight + n), style: {
|
|
69
|
-
height: 4,
|
|
70
|
-
background: '#ccc',
|
|
71
|
-
} }),
|
|
72
|
-
React.createElement(ReactComponent, { model: views[1] }))));
|
|
73
|
-
});
|
|
74
|
-
const OverlayComparativeView = observer(({ model }) => {
|
|
75
|
-
const { classes } = useStyles();
|
|
76
|
-
const { views } = model;
|
|
77
|
-
const { pluginManager } = getEnv(model);
|
|
78
|
-
return (React.createElement("div", { className: classes.rubberbandContainer },
|
|
79
|
-
React.createElement(Header, { model: model }),
|
|
80
|
-
React.createElement(Rubberband, { model: model, ControlComponent: React.createElement("div", { className: classes.rubberbandDiv }) }),
|
|
81
|
-
React.createElement("div", { className: classes.container },
|
|
82
|
-
React.createElement("div", { className: classes.content },
|
|
83
|
-
React.createElement("div", { className: classes.relative }, views.map(view => {
|
|
84
|
-
const { ReactComponent } = pluginManager.getViewType(view.type);
|
|
85
|
-
return React.createElement(ReactComponent, { key: view.id, model: view });
|
|
86
|
-
})),
|
|
87
|
-
React.createElement(Overlays, { model: model })))));
|
|
88
|
-
});
|
|
89
|
-
const LinearComparativeView = observer(function (props) {
|
|
90
|
-
const { model } = props;
|
|
91
|
-
const middle = model.tracks.some(({ displays }) => displays.some((d) => getConf(d, 'middle')));
|
|
92
|
-
return middle ? (React.createElement(MiddleComparativeView, { ...props })) : (React.createElement(OverlayComparativeView, { ...props }));
|
|
28
|
+
React.createElement(LinearComparativeRenderArea, { model: model })));
|
|
93
29
|
});
|
|
94
30
|
export default LinearComparativeView;
|
|
@@ -140,7 +140,7 @@ const LinearComparativeRubberband = observer(function Rubberband({ model, Contro
|
|
|
140
140
|
React.createElement("div", { ref: controlsRef, className: classes.rubberbandControl, onMouseDown: mouseDown, onMouseOut: mouseOut, onMouseMove: mouseMove }, ControlComponent)));
|
|
141
141
|
}
|
|
142
142
|
const right = anchorPosition ? anchorPosition.offsetX : currentX || 0;
|
|
143
|
-
const left = right
|
|
143
|
+
const left = Math.min(right, startX);
|
|
144
144
|
const width = Math.abs(right - startX);
|
|
145
145
|
const { views } = model;
|
|
146
146
|
const leftBpOffset = views.map(view => view.pxToBp(left));
|
|
@@ -5,6 +5,9 @@ export default function LinearComparativeViewF(pluginManager) {
|
|
|
5
5
|
pluginManager.addViewType(() => {
|
|
6
6
|
return new ViewType({
|
|
7
7
|
name: 'LinearComparativeView',
|
|
8
|
+
viewMetadata: {
|
|
9
|
+
hiddenFromGUI: true,
|
|
10
|
+
},
|
|
8
11
|
displayName: 'Linear comparative view',
|
|
9
12
|
stateModel: modelFactory(pluginManager),
|
|
10
13
|
ReactComponent: lazy(() => import('./components/LinearComparativeView')),
|