@jbrowse/core 2.0.0 → 2.1.2
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/BaseFeatureWidget/BaseFeatureDetail.d.ts +9 -3
- package/BaseFeatureWidget/BaseFeatureDetail.js +313 -581
- package/BaseFeatureWidget/SequenceFeatureDetails.js +213 -478
- package/BaseFeatureWidget/index.js +88 -126
- package/BaseFeatureWidget/types.d.ts +1 -0
- package/BaseFeatureWidget/types.js +1 -4
- package/BaseFeatureWidget/util.js +40 -75
- package/CorePlugin.js +55 -94
- package/Plugin.js +9 -34
- package/PluginLoader.js +153 -422
- package/PluginManager.d.ts +28 -33
- package/PluginManager.js +377 -666
- package/ReExports/Attributes.js +3 -10
- package/ReExports/BaseCard.js +3 -10
- package/ReExports/DataGrid.js +5 -12
- package/ReExports/FeatureDetails.js +3 -10
- package/ReExports/index.js +6 -12
- package/ReExports/list.d.ts +5 -0
- package/ReExports/list.js +271 -7
- package/ReExports/material-ui-colors.js +15 -16
- package/ReExports/modules.d.ts +11 -20
- package/ReExports/modules.js +453 -798
- package/TextSearch/BaseResults.js +51 -123
- package/TextSearch/TextSearchManager.js +66 -144
- package/assemblyManager/assembly.js +280 -555
- package/assemblyManager/assemblyConfigSchema.js +47 -64
- package/assemblyManager/assemblyManager.js +126 -272
- package/assemblyManager/index.js +9 -22
- package/configuration/configurationSchema.js +167 -203
- package/configuration/configurationSlot.js +248 -326
- package/configuration/index.js +19 -35
- package/configuration/util.js +131 -173
- package/data_adapters/BaseAdapter.d.ts +2 -2
- package/data_adapters/BaseAdapter.js +132 -521
- package/data_adapters/CytobandAdapter.js +40 -126
- package/data_adapters/dataAdapterCache.js +77 -158
- package/package.json +4 -5
- package/pluggableElementTypes/AdapterType.js +24 -79
- package/pluggableElementTypes/AddTrackWorkflowType.d.ts +17 -0
- package/pluggableElementTypes/AddTrackWorkflowType.js +20 -0
- package/pluggableElementTypes/ConnectionType.js +22 -65
- package/pluggableElementTypes/DisplayType.js +35 -82
- package/pluggableElementTypes/InternetAccountType.js +23 -64
- package/pluggableElementTypes/PluggableElementBase.js +8 -20
- package/pluggableElementTypes/RpcMethodType.js +85 -427
- package/pluggableElementTypes/TextSearchAdapterType.js +16 -55
- package/pluggableElementTypes/TrackType.js +26 -70
- package/pluggableElementTypes/ViewType.js +21 -63
- package/pluggableElementTypes/WidgetType.js +21 -64
- package/pluggableElementTypes/index.d.ts +4 -3
- package/pluggableElementTypes/index.js +42 -125
- package/pluggableElementTypes/models/BaseConnectionModelFactory.js +28 -43
- package/pluggableElementTypes/models/BaseDisplayModel.js +58 -95
- package/pluggableElementTypes/models/BaseTrackModel.js +139 -199
- package/pluggableElementTypes/models/BaseViewModel.js +24 -40
- package/pluggableElementTypes/models/InternetAccountModel.js +116 -263
- package/pluggableElementTypes/models/baseConnectionConfig.js +14 -25
- package/pluggableElementTypes/models/baseInternetAccountConfig.js +29 -38
- package/pluggableElementTypes/models/baseTrackConfig.js +106 -133
- package/pluggableElementTypes/models/index.js +21 -70
- package/pluggableElementTypes/renderers/BoxRendererType.js +132 -291
- package/pluggableElementTypes/renderers/CircularChordRendererType.js +8 -38
- package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.js +60 -192
- package/pluggableElementTypes/renderers/FeatureRendererType.d.ts +0 -2
- package/pluggableElementTypes/renderers/FeatureRendererType.js +89 -255
- package/pluggableElementTypes/renderers/RendererType.js +31 -105
- package/pluggableElementTypes/renderers/ServerSideRenderedContent.js +61 -72
- package/pluggableElementTypes/renderers/ServerSideRendererType.js +112 -265
- package/pluggableElementTypes/renderers/index.js +19 -62
- package/pluggableElementTypes/renderers/util/serializableFilterChain.js +27 -65
- package/rpc/BaseRpcDriver.js +169 -405
- package/rpc/MainThreadRpcDriver.js +27 -150
- package/rpc/RpcManager.js +58 -159
- package/rpc/WebWorkerRpcDriver.js +54 -171
- package/rpc/configSchema.js +25 -49
- package/rpc/coreRpcMethods.d.ts +1 -3
- package/rpc/coreRpcMethods.js +221 -959
- package/rpc/remoteAbortSignals.js +46 -70
- package/tsconfig.build.tsbuildinfo +1 -1
- package/ui/AboutDialog.js +106 -162
- package/ui/App.js +157 -242
- package/ui/AssemblySelector.js +59 -120
- package/ui/CascadingMenu.js +101 -196
- package/ui/ColorPicker.d.ts +16 -0
- package/ui/ColorPicker.js +97 -0
- package/ui/Drawer.js +28 -61
- package/ui/DrawerWidget.js +108 -202
- package/ui/DropDownMenu.js +60 -91
- package/ui/EditableTypography.js +87 -149
- package/ui/ErrorMessage.js +41 -56
- package/ui/FactoryResetDialog.js +24 -57
- package/ui/FatalErrorDialog.js +59 -91
- package/ui/FileSelector/FileSelector.js +123 -189
- package/ui/FileSelector/LocalFileChooser.js +44 -75
- package/ui/FileSelector/UrlChooser.js +17 -38
- package/ui/FileSelector/index.js +6 -12
- package/ui/Icons.js +45 -69
- package/ui/Logo.js +57 -110
- package/ui/Menu.js +232 -354
- package/ui/PrerenderedCanvas.js +63 -87
- package/ui/ResizeHandle.js +87 -116
- package/ui/ReturnToImportFormDialog.js +32 -63
- package/ui/SanitizedHTML.js +64 -47
- package/ui/Snackbar.js +74 -101
- package/ui/SnackbarModel.js +37 -51
- package/ui/Tooltip.js +49 -76
- package/ui/ViewContainer.js +113 -196
- package/ui/colors.d.ts +10 -0
- package/ui/colors.js +78 -0
- package/ui/index.js +51 -181
- package/ui/react-colorful.d.ts +17 -0
- package/ui/react-colorful.js +455 -0
- package/ui/theme.d.ts +23 -1
- package/ui/theme.js +199 -247
- package/util/Base1DUtils.d.ts +32 -0
- package/util/Base1DUtils.js +174 -0
- package/util/Base1DViewModel.d.ts +16 -30
- package/util/Base1DViewModel.js +116 -293
- package/util/QuickLRU.js +84 -332
- package/util/TimeTraveller.d.ts +19 -0
- package/util/TimeTraveller.js +86 -0
- package/util/aborting.js +49 -127
- package/util/analytics.js +91 -154
- package/util/blockTypes.js +106 -240
- package/util/calculateDynamicBlocks.js +98 -128
- package/util/calculateStaticBlocks.js +105 -125
- package/util/color/cssColorsLevel4.js +156 -160
- package/util/color/index.js +33 -55
- package/util/compositeMap.js +49 -333
- package/util/formatFastaStrings.js +9 -14
- package/util/idMaker.js +18 -31
- package/util/index.d.ts +18 -32
- package/util/index.js +747 -1226
- package/util/io/RemoteFileWithRangeCache.js +88 -257
- package/util/io/index.js +95 -169
- package/util/jexl.js +60 -115
- package/util/jexlStrings.js +24 -29
- package/util/layouts/BaseLayout.js +1 -4
- package/util/layouts/GranularRectLayout.js +388 -555
- package/util/layouts/MultiLayout.js +41 -109
- package/util/layouts/PrecomputedLayout.js +56 -112
- package/util/layouts/PrecomputedMultiLayout.js +22 -59
- package/util/layouts/SceneGraph.js +127 -197
- package/util/layouts/index.js +29 -66
- package/util/mst-reflection.js +55 -71
- package/util/offscreenCanvasPonyfill.js +66 -134
- package/util/offscreenCanvasUtils.d.ts +2 -7
- package/util/offscreenCanvasUtils.js +49 -146
- package/util/range.js +29 -40
- package/util/rxjs.js +20 -27
- package/util/simpleFeature.js +88 -152
- package/util/stats.js +91 -151
- package/util/tracks.js +130 -173
- package/util/types/index.js +110 -179
- package/util/types/mst.js +91 -146
- package/util/types/util.js +1 -4
- package/util/when.js +54 -101
- package/BaseFeatureWidget/SequenceFeatureDetails.test.js +0 -122
- package/BaseFeatureWidget/index.test.js +0 -69
- package/TextSearch/BaseResults.test.js +0 -42
- package/configuration/configurationSchema.test.js +0 -266
- package/configuration/configurationSlot.test.js +0 -69
- package/configuration/util.test.js +0 -39
- package/data_adapters/BaseAdapter.test.js +0 -200
- package/declare.d.js +0 -1
- package/pluggableElementTypes/RpcMethodType.test.js +0 -118
- package/pluggableElementTypes/renderers/declare.d.js +0 -1
- package/pluggableElementTypes/renderers/util/serializableFilterChain.test.js +0 -20
- package/rpc/BaseRpcDriver.test.js +0 -540
- package/rpc/declaration.d.js +0 -1
- package/ui/FatalErrorDialog.test.js +0 -82
- package/ui/SanitizedHTML.test.js +0 -36
- package/ui/theme.test.js +0 -92
- package/util/Base1DViewModel.test.js +0 -130
- package/util/calculateDynamicBlocks.test.js +0 -74
- package/util/calculateStaticBlocks.test.js +0 -297
- package/util/declare.d.js +0 -1
- package/util/formatFastaStrings.test.js +0 -40
- package/util/index.test.js +0 -213
- package/util/jexlStrings.test.js +0 -48
- package/util/layouts/GranularRectLayout.test.js +0 -99
- package/util/range.test.js +0 -64
- package/util/simpleFeature.test.js +0 -34
- package/util/stats.test.js +0 -172
|
@@ -1,494 +1,229 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
9
17
|
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
29
|
exports.SequencePanel = void 0;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
22
|
-
|
|
23
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
24
|
-
|
|
25
|
-
var _material = require("@mui/material");
|
|
26
|
-
|
|
27
|
-
var _mui = require("tss-react/mui");
|
|
28
|
-
|
|
29
|
-
var _reactIntersectionObserver = require("react-intersection-observer");
|
|
30
|
-
|
|
31
|
-
var _copyToClipboard = _interopRequireDefault(require("copy-to-clipboard"));
|
|
32
|
-
|
|
33
|
-
var _util = require("../util");
|
|
34
|
-
|
|
35
|
-
var _configuration = require("../configuration");
|
|
36
|
-
|
|
37
|
-
var _util2 = require("./util");
|
|
38
|
-
|
|
39
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
40
|
-
|
|
41
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
42
|
-
|
|
43
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
44
|
-
|
|
45
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
46
|
-
|
|
47
|
-
var useStyles = (0, _mui.makeStyles)()(function (theme) {
|
|
48
|
-
return {
|
|
30
|
+
const react_1 = __importStar(require("react"));
|
|
31
|
+
const material_1 = require("@mui/material");
|
|
32
|
+
const mui_1 = require("tss-react/mui");
|
|
33
|
+
const react_intersection_observer_1 = require("react-intersection-observer");
|
|
34
|
+
const copy_to_clipboard_1 = __importDefault(require("copy-to-clipboard"));
|
|
35
|
+
const util_1 = require("../util");
|
|
36
|
+
const configuration_1 = require("../configuration");
|
|
37
|
+
const util_2 = require("./util");
|
|
38
|
+
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
49
39
|
button: {
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
40
|
+
margin: theme.spacing(1),
|
|
41
|
+
},
|
|
42
|
+
}));
|
|
43
|
+
// note that these are currently put into the style section instead of being
|
|
54
44
|
// defined in classes to aid copy and paste to an external document e.g. word
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
function GeneCDS(_ref) {
|
|
63
|
-
var cds = _ref.cds,
|
|
64
|
-
sequence = _ref.sequence;
|
|
65
|
-
return /*#__PURE__*/_react.default.createElement("span", {
|
|
66
|
-
style: {
|
|
67
|
-
background: cdsColor
|
|
68
|
-
}
|
|
69
|
-
}, (0, _util2.stitch)(cds, sequence));
|
|
45
|
+
const proteinColor = 'rgb(220,160,220)';
|
|
46
|
+
const intronColor = undefined;
|
|
47
|
+
const cdsColor = 'rgb(220,220,180)';
|
|
48
|
+
const updownstreamColor = 'rgba(250,200,200)';
|
|
49
|
+
const utrColor = 'rgb(200,240,240)';
|
|
50
|
+
function GeneCDS({ cds, sequence }) {
|
|
51
|
+
return react_1.default.createElement("span", { style: { background: cdsColor } }, (0, util_2.stitch)(cds, sequence));
|
|
70
52
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
var protein = '';
|
|
78
|
-
|
|
79
|
-
for (var i = 0; i < str.length; i += 3) {
|
|
80
|
-
// use & symbol for undefined codon, or partial slice
|
|
81
|
-
protein += codonTable[str.slice(i, i + 3)] || '&';
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return /*#__PURE__*/_react.default.createElement("span", {
|
|
85
|
-
style: {
|
|
86
|
-
background: proteinColor
|
|
53
|
+
function GeneProtein({ cds, sequence, codonTable, }) {
|
|
54
|
+
const str = (0, util_2.stitch)(cds, sequence);
|
|
55
|
+
let protein = '';
|
|
56
|
+
for (let i = 0; i < str.length; i += 3) {
|
|
57
|
+
// use & symbol for undefined codon, or partial slice
|
|
58
|
+
protein += codonTable[str.slice(i, i + 3)] || '&';
|
|
87
59
|
}
|
|
88
|
-
|
|
60
|
+
return react_1.default.createElement("span", { style: { background: proteinColor } }, protein);
|
|
61
|
+
}
|
|
62
|
+
function GenecDNA({ utr, cds, exons, sequence, upstream, downstream, includeIntrons, collapseIntron, }) {
|
|
63
|
+
const chunks = cds.length
|
|
64
|
+
? [...cds, ...utr].sort((a, b) => a.start - b.start)
|
|
65
|
+
: exons;
|
|
66
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
67
|
+
upstream ? (react_1.default.createElement("span", { style: { background: updownstreamColor } }, upstream)) : null,
|
|
68
|
+
chunks
|
|
69
|
+
.filter(f => f.start !== f.end)
|
|
70
|
+
.map((chunk, index) => {
|
|
71
|
+
var _a;
|
|
72
|
+
const intron = sequence.slice(chunk.end, (_a = chunks[index + 1]) === null || _a === void 0 ? void 0 : _a.start);
|
|
73
|
+
return (react_1.default.createElement(react_1.default.Fragment, { key: JSON.stringify(chunk) },
|
|
74
|
+
react_1.default.createElement("span", { style: {
|
|
75
|
+
background: chunk.type === 'CDS' ? cdsColor : utrColor,
|
|
76
|
+
} }, sequence.slice(chunk.start, chunk.end)),
|
|
77
|
+
includeIntrons && index < chunks.length - 1 ? (react_1.default.createElement("span", { style: { background: intronColor } }, collapseIntron && intron.length > 20
|
|
78
|
+
? `${intron.slice(0, 10)}...${intron.slice(-10)}`
|
|
79
|
+
: intron)) : null));
|
|
80
|
+
}),
|
|
81
|
+
downstream ? (react_1.default.createElement("span", { style: { background: updownstreamColor } }, downstream)) : null));
|
|
89
82
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
sequence = _ref3.sequence,
|
|
96
|
-
upstream = _ref3.upstream,
|
|
97
|
-
downstream = _ref3.downstream,
|
|
98
|
-
includeIntrons = _ref3.includeIntrons,
|
|
99
|
-
collapseIntron = _ref3.collapseIntron;
|
|
100
|
-
var chunks = cds.length ? [].concat((0, _toConsumableArray2.default)(cds), (0, _toConsumableArray2.default)(utr)).sort(function (a, b) {
|
|
101
|
-
return a.start - b.start;
|
|
102
|
-
}) : exons;
|
|
103
|
-
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, upstream ? /*#__PURE__*/_react.default.createElement("span", {
|
|
104
|
-
style: {
|
|
105
|
-
background: updownstreamColor
|
|
83
|
+
exports.SequencePanel = react_1.default.forwardRef(({ feature, mode, sequence: { seq: sequence, upstream = '', downstream = '' }, }, ref) => {
|
|
84
|
+
const { subfeatures } = feature;
|
|
85
|
+
const codonTable = (0, util_1.generateCodonTable)(util_1.defaultCodonTable);
|
|
86
|
+
if (!subfeatures) {
|
|
87
|
+
return null;
|
|
106
88
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
89
|
+
const children = subfeatures
|
|
90
|
+
.sort((a, b) => a.start - b.start)
|
|
91
|
+
.map(sub => ({
|
|
92
|
+
...sub,
|
|
93
|
+
start: sub.start - feature.start,
|
|
94
|
+
end: sub.end - feature.start,
|
|
95
|
+
}));
|
|
96
|
+
// we filter duplicate entries in cds and exon lists duplicate entries may be
|
|
97
|
+
// rare but was seen in Gencode v36 track NCList, likely a bug on GFF3 or
|
|
98
|
+
// probably worth ignoring here (produces broken protein translations if
|
|
99
|
+
// included)
|
|
100
|
+
//
|
|
101
|
+
// position 1:224,800,006..225,203,064 gene ENSG00000185842.15 first
|
|
102
|
+
// transcript ENST00000445597.6
|
|
103
|
+
//
|
|
104
|
+
// http://localhost:3000/?config=test_data%2Fconfig.json&session=share-FUl7G1isvF&password=HXh5Y
|
|
105
|
+
let cds = (0, util_2.dedupe)(children.filter(sub => sub.type === 'CDS'));
|
|
106
|
+
let utr = (0, util_2.dedupe)(children.filter(sub => sub.type.match(/utr/i)));
|
|
107
|
+
let exons = (0, util_2.dedupe)(children.filter(sub => sub.type === 'exon'));
|
|
108
|
+
if (!utr.length && cds.length && exons.length) {
|
|
109
|
+
utr = (0, util_2.calculateUTRs)(cds, exons);
|
|
127
110
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
var subfeatures = feature.subfeatures;
|
|
141
|
-
var codonTable = (0, _util.generateCodonTable)(_util.defaultCodonTable);
|
|
142
|
-
|
|
143
|
-
if (!subfeatures) {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
var children = subfeatures.sort(function (a, b) {
|
|
148
|
-
return a.start - b.start;
|
|
149
|
-
}).map(function (sub) {
|
|
150
|
-
return _objectSpread(_objectSpread({}, sub), {}, {
|
|
151
|
-
start: sub.start - feature.start,
|
|
152
|
-
end: sub.end - feature.start
|
|
153
|
-
});
|
|
154
|
-
}); // we filter duplicate entries in cds and exon lists duplicate entries may be
|
|
155
|
-
// rare but was seen in Gencode v36 track NCList, likely a bug on GFF3 or
|
|
156
|
-
// probably worth ignoring here (produces broken protein translations if
|
|
157
|
-
// included)
|
|
158
|
-
//
|
|
159
|
-
// position 1:224,800,006..225,203,064 gene ENSG00000185842.15 first
|
|
160
|
-
// transcript ENST00000445597.6
|
|
161
|
-
//
|
|
162
|
-
// http://localhost:3000/?config=test_data%2Fconfig.json&session=share-FUl7G1isvF&password=HXh5Y
|
|
163
|
-
|
|
164
|
-
var cds = (0, _util2.dedupe)(children.filter(function (sub) {
|
|
165
|
-
return sub.type === 'CDS';
|
|
166
|
-
}));
|
|
167
|
-
var utr = (0, _util2.dedupe)(children.filter(function (sub) {
|
|
168
|
-
return sub.type.match(/utr/i);
|
|
169
|
-
}));
|
|
170
|
-
var exons = (0, _util2.dedupe)(children.filter(function (sub) {
|
|
171
|
-
return sub.type === 'exon';
|
|
172
|
-
}));
|
|
173
|
-
|
|
174
|
-
if (!utr.length && cds.length && exons.length) {
|
|
175
|
-
utr = (0, _util2.calculateUTRs)(cds, exons);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (feature.strand === -1) {
|
|
179
|
-
// doing this in a single assignment is needed because downstream and
|
|
180
|
-
// upstream are swapped so this avoids a temp variable
|
|
181
|
-
;
|
|
182
|
-
var _ref5 = [(0, _util.revcom)(sequence), (0, _util.revcom)(downstream), (0, _util.revcom)(upstream)];
|
|
183
|
-
sequence = _ref5[0];
|
|
184
|
-
upstream = _ref5[1];
|
|
185
|
-
downstream = _ref5[2];
|
|
186
|
-
cds = (0, _util2.revlist)(cds, sequence.length);
|
|
187
|
-
exons = (0, _util2.revlist)(exons, sequence.length);
|
|
188
|
-
utr = (0, _util2.revlist)(utr, sequence.length);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return /*#__PURE__*/_react.default.createElement("div", {
|
|
192
|
-
ref: ref,
|
|
193
|
-
"data-testid": "sequence_panel"
|
|
194
|
-
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
195
|
-
style: {
|
|
196
|
-
fontFamily: 'monospace',
|
|
197
|
-
wordWrap: 'break-word',
|
|
198
|
-
maxWidth: 600
|
|
111
|
+
if (feature.strand === -1) {
|
|
112
|
+
// doing this in a single assignment is needed because downstream and
|
|
113
|
+
// upstream are swapped so this avoids a temp variable
|
|
114
|
+
;
|
|
115
|
+
[sequence, upstream, downstream] = [
|
|
116
|
+
(0, util_1.revcom)(sequence),
|
|
117
|
+
(0, util_1.revcom)(downstream),
|
|
118
|
+
(0, util_1.revcom)(upstream),
|
|
119
|
+
];
|
|
120
|
+
cds = (0, util_2.revlist)(cds, sequence.length);
|
|
121
|
+
exons = (0, util_2.revlist)(exons, sequence.length);
|
|
122
|
+
utr = (0, util_2.revlist)(utr, sequence.length);
|
|
199
123
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
sequence: sequence
|
|
212
|
-
}) : mode === 'gene' ? /*#__PURE__*/_react.default.createElement(GenecDNA, {
|
|
213
|
-
exons: exons,
|
|
214
|
-
cds: cds,
|
|
215
|
-
utr: utr,
|
|
216
|
-
sequence: sequence,
|
|
217
|
-
includeIntrons: true
|
|
218
|
-
}) : mode === 'gene_collapsed_intron' ? /*#__PURE__*/_react.default.createElement(GenecDNA, {
|
|
219
|
-
exons: exons,
|
|
220
|
-
cds: cds,
|
|
221
|
-
sequence: sequence,
|
|
222
|
-
utr: utr,
|
|
223
|
-
includeIntrons: true,
|
|
224
|
-
collapseIntron: true
|
|
225
|
-
}) : mode === 'gene_updownstream' ? /*#__PURE__*/_react.default.createElement(GenecDNA, {
|
|
226
|
-
exons: exons,
|
|
227
|
-
cds: cds,
|
|
228
|
-
sequence: sequence,
|
|
229
|
-
utr: utr,
|
|
230
|
-
upstream: upstream,
|
|
231
|
-
downstream: downstream,
|
|
232
|
-
includeIntrons: true
|
|
233
|
-
}) : mode === 'gene_updownstream_collapsed_intron' ? /*#__PURE__*/_react.default.createElement(GenecDNA, {
|
|
234
|
-
exons: exons,
|
|
235
|
-
cds: cds,
|
|
236
|
-
sequence: sequence,
|
|
237
|
-
utr: utr,
|
|
238
|
-
upstream: upstream,
|
|
239
|
-
downstream: downstream,
|
|
240
|
-
includeIntrons: true,
|
|
241
|
-
collapseIntron: true
|
|
242
|
-
}) : /*#__PURE__*/_react.default.createElement("div", null, "Unknown type")));
|
|
243
|
-
}); // display the stitched-together sequence of a gene's CDS, cDNA, or protein
|
|
124
|
+
return (react_1.default.createElement("div", { ref: ref, "data-testid": "sequence_panel" },
|
|
125
|
+
react_1.default.createElement("div", { style: {
|
|
126
|
+
fontFamily: 'monospace',
|
|
127
|
+
wordWrap: 'break-word',
|
|
128
|
+
fontSize: 12,
|
|
129
|
+
maxWidth: 600,
|
|
130
|
+
} },
|
|
131
|
+
`>${feature.name || feature.id || 'unknown'}-${mode}\n`,
|
|
132
|
+
mode === 'cds' ? (react_1.default.createElement(GeneCDS, { cds: cds, sequence: sequence })) : mode === 'cdna' ? (react_1.default.createElement(GenecDNA, { exons: exons, cds: cds, utr: utr, sequence: sequence })) : mode === 'protein' ? (react_1.default.createElement(GeneProtein, { cds: cds, codonTable: codonTable, sequence: sequence })) : mode === 'gene' ? (react_1.default.createElement(GenecDNA, { exons: exons, cds: cds, utr: utr, sequence: sequence, includeIntrons: true })) : mode === 'gene_collapsed_intron' ? (react_1.default.createElement(GenecDNA, { exons: exons, cds: cds, sequence: sequence, utr: utr, includeIntrons: true, collapseIntron: true })) : mode === 'gene_updownstream' ? (react_1.default.createElement(GenecDNA, { exons: exons, cds: cds, sequence: sequence, utr: utr, upstream: upstream, downstream: downstream, includeIntrons: true })) : mode === 'gene_updownstream_collapsed_intron' ? (react_1.default.createElement(GenecDNA, { exons: exons, cds: cds, sequence: sequence, utr: utr, upstream: upstream, downstream: downstream, includeIntrons: true, collapseIntron: true })) : (react_1.default.createElement("div", null, "Unknown type")))));
|
|
133
|
+
});
|
|
134
|
+
// display the stitched-together sequence of a gene's CDS, cDNA, or protein
|
|
244
135
|
// sequence. this is a best effort and weird genomic phenomena could lead these
|
|
245
136
|
// to not be 100% accurate
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
var _useState = (0, _react.useState)(),
|
|
270
|
-
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
271
|
-
sequence = _useState2[0],
|
|
272
|
-
setSequence = _useState2[1];
|
|
273
|
-
|
|
274
|
-
var _useState3 = (0, _react.useState)(),
|
|
275
|
-
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
276
|
-
error = _useState4[0],
|
|
277
|
-
setError = _useState4[1];
|
|
278
|
-
|
|
279
|
-
var _useState5 = (0, _react.useState)(hasCDS ? 'cds' : 'cdna'),
|
|
280
|
-
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
|
|
281
|
-
mode = _useState6[0],
|
|
282
|
-
setMode = _useState6[1];
|
|
283
|
-
|
|
284
|
-
var _useState7 = (0, _react.useState)(false),
|
|
285
|
-
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
|
|
286
|
-
copied = _useState8[0],
|
|
287
|
-
setCopied = _useState8[1];
|
|
288
|
-
|
|
289
|
-
var _useState9 = (0, _react.useState)(false),
|
|
290
|
-
_useState10 = (0, _slicedToArray2.default)(_useState9, 2),
|
|
291
|
-
copiedHtml = _useState10[0],
|
|
292
|
-
setCopiedHtml = _useState10[1];
|
|
293
|
-
|
|
294
|
-
(0, _react.useEffect)(function () {
|
|
295
|
-
var _model$view;
|
|
296
|
-
|
|
297
|
-
var finished = false;
|
|
298
|
-
|
|
299
|
-
if (!model || !inView) {
|
|
300
|
-
return function () {};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
var _getSession = (0, _util.getSession)(model),
|
|
304
|
-
assemblyManager = _getSession.assemblyManager,
|
|
305
|
-
rpcManager = _getSession.rpcManager;
|
|
306
|
-
|
|
307
|
-
var _ref7 = ((_model$view = model.view) === null || _model$view === void 0 ? void 0 : _model$view.assemblyNames) || [],
|
|
308
|
-
_ref8 = (0, _slicedToArray2.default)(_ref7, 1),
|
|
309
|
-
assemblyName = _ref8[0];
|
|
310
|
-
|
|
311
|
-
function fetchSeq(_x, _x2, _x3) {
|
|
312
|
-
return _fetchSeq.apply(this, arguments);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function _fetchSeq() {
|
|
316
|
-
_fetchSeq = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(start, end, refName) {
|
|
317
|
-
var assembly, sessionId, feats, _ref11, _ref12, feat;
|
|
318
|
-
|
|
319
|
-
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
320
|
-
while (1) {
|
|
321
|
-
switch (_context2.prev = _context2.next) {
|
|
322
|
-
case 0:
|
|
323
|
-
_context2.next = 2;
|
|
324
|
-
return assemblyManager.waitForAssembly(assemblyName);
|
|
325
|
-
|
|
326
|
-
case 2:
|
|
327
|
-
assembly = _context2.sent;
|
|
328
|
-
|
|
329
|
-
if (assembly) {
|
|
330
|
-
_context2.next = 5;
|
|
331
|
-
break;
|
|
332
|
-
}
|
|
333
|
-
|
|
137
|
+
function SequenceFeatureDetails({ model, feature }) {
|
|
138
|
+
var _a;
|
|
139
|
+
const { classes } = useStyles();
|
|
140
|
+
const parentFeature = feature;
|
|
141
|
+
const hasCDS = (_a = parentFeature.subfeatures) === null || _a === void 0 ? void 0 : _a.find(sub => sub.type === 'CDS');
|
|
142
|
+
const seqPanelRef = (0, react_1.useRef)(null);
|
|
143
|
+
const { ref, inView } = (0, react_intersection_observer_1.useInView)();
|
|
144
|
+
const [sequence, setSequence] = (0, react_1.useState)();
|
|
145
|
+
const [error, setError] = (0, react_1.useState)();
|
|
146
|
+
const [mode, setMode] = (0, react_1.useState)(hasCDS ? 'cds' : 'cdna');
|
|
147
|
+
const [copied, setCopied] = (0, react_1.useState)(false);
|
|
148
|
+
const [copiedHtml, setCopiedHtml] = (0, react_1.useState)(false);
|
|
149
|
+
(0, react_1.useEffect)(() => {
|
|
150
|
+
var _a;
|
|
151
|
+
let finished = false;
|
|
152
|
+
if (!model || !inView) {
|
|
153
|
+
return () => { };
|
|
154
|
+
}
|
|
155
|
+
const { assemblyManager, rpcManager } = (0, util_1.getSession)(model);
|
|
156
|
+
const [assemblyName] = ((_a = model.view) === null || _a === void 0 ? void 0 : _a.assemblyNames) || [];
|
|
157
|
+
async function fetchSeq(start, end, refName) {
|
|
158
|
+
const assembly = await assemblyManager.waitForAssembly(assemblyName);
|
|
159
|
+
if (!assembly) {
|
|
334
160
|
throw new Error('assembly not found');
|
|
335
|
-
|
|
336
|
-
case 5:
|
|
337
|
-
sessionId = 'getSequence';
|
|
338
|
-
_context2.next = 8;
|
|
339
|
-
return rpcManager.call(sessionId, 'CoreGetFeatures', {
|
|
340
|
-
adapterConfig: (0, _configuration.getConf)(assembly, ['sequence', 'adapter']),
|
|
341
|
-
sessionId: sessionId,
|
|
342
|
-
regions: [{
|
|
343
|
-
start: start,
|
|
344
|
-
end: end,
|
|
345
|
-
refName: assembly.getCanonicalRefName(refName)
|
|
346
|
-
}]
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
case 8:
|
|
350
|
-
feats = _context2.sent;
|
|
351
|
-
_ref11 = feats, _ref12 = (0, _slicedToArray2.default)(_ref11, 1), feat = _ref12[0];
|
|
352
|
-
|
|
353
|
-
if (feat) {
|
|
354
|
-
_context2.next = 12;
|
|
355
|
-
break;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
throw new Error("sequence not found for feature with refName:".concat(refName));
|
|
359
|
-
|
|
360
|
-
case 12:
|
|
361
|
-
return _context2.abrupt("return", feat.get('seq'));
|
|
362
|
-
|
|
363
|
-
case 13:
|
|
364
|
-
case "end":
|
|
365
|
-
return _context2.stop();
|
|
366
161
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return fetchSeq(start, end, refName);
|
|
385
|
-
|
|
386
|
-
case 4:
|
|
387
|
-
seq = _context.sent;
|
|
388
|
-
_context.next = 7;
|
|
389
|
-
return fetchSeq(Math.max(0, start - 500), start, refName);
|
|
390
|
-
|
|
391
|
-
case 7:
|
|
392
|
-
up = _context.sent;
|
|
393
|
-
_context.next = 10;
|
|
394
|
-
return fetchSeq(end, end + 500, refName);
|
|
395
|
-
|
|
396
|
-
case 10:
|
|
397
|
-
down = _context.sent;
|
|
398
|
-
|
|
399
|
-
if (!finished) {
|
|
400
|
-
setSequence({
|
|
401
|
-
seq: seq,
|
|
402
|
-
upstream: up,
|
|
403
|
-
downstream: down
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
_context.next = 17;
|
|
408
|
-
break;
|
|
409
|
-
|
|
410
|
-
case 14:
|
|
411
|
-
_context.prev = 14;
|
|
412
|
-
_context.t0 = _context["catch"](0);
|
|
413
|
-
setError(_context.t0);
|
|
414
|
-
|
|
415
|
-
case 17:
|
|
416
|
-
case "end":
|
|
417
|
-
return _context.stop();
|
|
418
|
-
}
|
|
162
|
+
const sessionId = 'getSequence';
|
|
163
|
+
const feats = await rpcManager.call(sessionId, 'CoreGetFeatures', {
|
|
164
|
+
adapterConfig: (0, configuration_1.getConf)(assembly, ['sequence', 'adapter']),
|
|
165
|
+
sessionId,
|
|
166
|
+
regions: [
|
|
167
|
+
{
|
|
168
|
+
start,
|
|
169
|
+
end,
|
|
170
|
+
refName: assembly.getCanonicalRefName(refName),
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
});
|
|
174
|
+
const [feat] = feats;
|
|
175
|
+
if (!feat) {
|
|
176
|
+
throw new Error(`sequence not found for feature with refName:${refName}`);
|
|
177
|
+
}
|
|
178
|
+
return feat.get('seq');
|
|
419
179
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
variant: "contained",
|
|
471
|
-
onClick: function onClick() {
|
|
472
|
-
var ref = seqPanelRef.current;
|
|
473
|
-
|
|
474
|
-
if (ref) {
|
|
475
|
-
(0, _copyToClipboard.default)(ref.innerHTML, {
|
|
476
|
-
format: 'text/html'
|
|
477
|
-
});
|
|
478
|
-
setCopiedHtml(true);
|
|
479
|
-
setTimeout(function () {
|
|
480
|
-
return setCopiedHtml(false);
|
|
481
|
-
}, 1000);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}, copiedHtml ? 'Copied to clipboard!' : 'Copy as HTML')), /*#__PURE__*/_react.default.createElement("div", {
|
|
485
|
-
"data-testid": "feature_sequence"
|
|
486
|
-
}, error ? /*#__PURE__*/_react.default.createElement(_material.Typography, {
|
|
487
|
-
color: "error"
|
|
488
|
-
}, "".concat(error)) : loading ? /*#__PURE__*/_react.default.createElement("div", null, "Loading gene sequence...") : sequence ? /*#__PURE__*/_react.default.createElement(SequencePanel, {
|
|
489
|
-
ref: seqPanelRef,
|
|
490
|
-
feature: parentFeature,
|
|
491
|
-
mode: mode,
|
|
492
|
-
sequence: sequence
|
|
493
|
-
}) : /*#__PURE__*/_react.default.createElement("div", null, "No sequence found")));
|
|
494
|
-
}
|
|
180
|
+
;
|
|
181
|
+
(async () => {
|
|
182
|
+
try {
|
|
183
|
+
const { start, end, refName } = feature;
|
|
184
|
+
const seq = await fetchSeq(start, end, refName);
|
|
185
|
+
const up = await fetchSeq(Math.max(0, start - 500), start, refName);
|
|
186
|
+
const down = await fetchSeq(end, end + 500, refName);
|
|
187
|
+
if (!finished) {
|
|
188
|
+
setSequence({ seq, upstream: up, downstream: down });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
setError(e);
|
|
193
|
+
}
|
|
194
|
+
})();
|
|
195
|
+
return () => {
|
|
196
|
+
finished = true;
|
|
197
|
+
};
|
|
198
|
+
}, [feature, inView, model]);
|
|
199
|
+
const loading = !sequence;
|
|
200
|
+
return (react_1.default.createElement("div", { ref: ref },
|
|
201
|
+
react_1.default.createElement(material_1.FormControl, null,
|
|
202
|
+
react_1.default.createElement(material_1.Select, { value: mode, onChange: event => setMode(event.target.value) },
|
|
203
|
+
hasCDS ? react_1.default.createElement(material_1.MenuItem, { value: "cds" }, "CDS") : null,
|
|
204
|
+
hasCDS ? react_1.default.createElement(material_1.MenuItem, { value: "protein" }, "Protein") : null,
|
|
205
|
+
react_1.default.createElement(material_1.MenuItem, { value: "gene" }, "Gene w/ introns"),
|
|
206
|
+
react_1.default.createElement(material_1.MenuItem, { value: "gene_collapsed_intron" }, "Gene w/ 10bp of intron"),
|
|
207
|
+
react_1.default.createElement(material_1.MenuItem, { value: "gene_updownstream" }, "Gene w/ 500bp up+down stream"),
|
|
208
|
+
react_1.default.createElement(material_1.MenuItem, { value: "gene_updownstream_collapsed_intron" }, "Gene w/ 500bp up+down stream w/ 10bp intron"),
|
|
209
|
+
react_1.default.createElement(material_1.MenuItem, { value: "cdna" }, "cDNA"))),
|
|
210
|
+
react_1.default.createElement(material_1.Button, { className: classes.button, type: "button", variant: "contained", onClick: () => {
|
|
211
|
+
const ref = seqPanelRef.current;
|
|
212
|
+
if (ref) {
|
|
213
|
+
(0, copy_to_clipboard_1.default)(ref.textContent || '', { format: 'text/plain' });
|
|
214
|
+
setCopied(true);
|
|
215
|
+
setTimeout(() => setCopied(false), 1000);
|
|
216
|
+
}
|
|
217
|
+
} }, copied ? 'Copied to clipboard!' : 'Copy as plaintext'),
|
|
218
|
+
react_1.default.createElement(material_1.Tooltip, { title: "Note that 'Copy as HTML' can retain the colors but cannot be pasted into some programs like notepad that only expect plain text" },
|
|
219
|
+
react_1.default.createElement(material_1.Button, { className: classes.button, type: "button", variant: "contained", onClick: () => {
|
|
220
|
+
const ref = seqPanelRef.current;
|
|
221
|
+
if (ref) {
|
|
222
|
+
(0, copy_to_clipboard_1.default)(ref.innerHTML, { format: 'text/html' });
|
|
223
|
+
setCopiedHtml(true);
|
|
224
|
+
setTimeout(() => setCopiedHtml(false), 1000);
|
|
225
|
+
}
|
|
226
|
+
} }, copiedHtml ? 'Copied to clipboard!' : 'Copy as HTML')),
|
|
227
|
+
react_1.default.createElement("div", { "data-testid": "feature_sequence" }, error ? (react_1.default.createElement(material_1.Typography, { color: "error" }, `${error}`)) : loading ? (react_1.default.createElement("div", null, "Loading gene sequence...")) : sequence ? (react_1.default.createElement(exports.SequencePanel, { ref: seqPanelRef, feature: parentFeature, mode: mode, sequence: sequence })) : (react_1.default.createElement("div", null, "No sequence found")))));
|
|
228
|
+
}
|
|
229
|
+
exports.default = SequenceFeatureDetails;
|