@teselagen/ove 0.6.1-beta.1 → 0.7.3-beta.1
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/DigestTool/DigestTool.d.ts +1 -9
- package/helperComponents/PropertiesDialog/utils.d.ts +5 -5
- package/index.cjs.js +50666 -51131
- package/index.es.js +50697 -51162
- package/index.umd.js +57822 -58187
- package/package.json +5 -6
- package/src/CutsiteFilter/index.js +51 -55
- package/src/DigestTool/DigestTool.js +176 -174
- package/src/PCRTool/PCRTool.js +8 -2
- package/src/helperComponents/AddOrEditAnnotationDialog/index.js +8 -4
- package/src/helperComponents/AddOrEditFeatureDialog/index.js +9 -7
- package/src/helperComponents/AddOrEditPartDialog/index.js +3 -3
- package/src/helperComponents/AddOrEditPrimerDialog/index.js +3 -7
- package/src/helperComponents/PropertiesDialog/GenericAnnotationProperties.js +52 -50
- package/src/helperComponents/PropertiesDialog/OrfProperties.js +1 -1
- package/src/helperComponents/PropertiesDialog/utils.js +5 -5
- package/src/helperComponents/RemoveDuplicates/index.js +24 -24
- package/style.css +252 -252
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teselagen/ove",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.3-beta.1",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@teselagen/sequence-utils": "0.3.27",
|
|
14
14
|
"@teselagen/range-utils": "0.3.7",
|
|
15
|
-
"@teselagen/ui": "0.
|
|
15
|
+
"@teselagen/ui": "0.7.3-beta.1",
|
|
16
16
|
"@teselagen/file-utils": "0.3.16",
|
|
17
17
|
"@teselagen/bounce-loader": "0.3.11",
|
|
18
18
|
"@teselagen/bio-parsers": "0.4.22",
|
|
@@ -58,7 +58,6 @@
|
|
|
58
58
|
"lodash-es": "^4.17.21",
|
|
59
59
|
"math-expression-evaluator": "^1.3.7",
|
|
60
60
|
"mobx": "^6.10.2",
|
|
61
|
-
"mobx-react": "^9.0.1",
|
|
62
61
|
"mock-fs": "5.2.0",
|
|
63
62
|
"nanoid": "^4.0.0",
|
|
64
63
|
"node-interval-tree": "^1.3.3",
|
|
@@ -68,16 +67,16 @@
|
|
|
68
67
|
"popper.js": "^1.16.1",
|
|
69
68
|
"prop-types": "^15.6.2",
|
|
70
69
|
"qs": "^6.9.6",
|
|
71
|
-
"react": "^18.
|
|
70
|
+
"react": "^18.3.1",
|
|
72
71
|
"react-color": "^2.19.3",
|
|
73
|
-
"react-dom": "^18.
|
|
72
|
+
"react-dom": "^18.3.1",
|
|
74
73
|
"react-draggable": "4.4.5",
|
|
75
74
|
"react-dropzone": "^11.4.2",
|
|
76
75
|
"react-markdown": "9.0.1",
|
|
77
76
|
"react-measure": "^2.5.2",
|
|
78
77
|
"react-redux": "^8.0.5",
|
|
79
78
|
"react-rnd": "^10.2.4",
|
|
80
|
-
"react-router-dom": "
|
|
79
|
+
"react-router-dom": "4",
|
|
81
80
|
"react-sizeme": "^2.6.12",
|
|
82
81
|
"react-transition-group": "^2.4.0",
|
|
83
82
|
"recompose": "npm:react-recompose@0.31.1",
|
|
@@ -152,48 +152,46 @@ export function CutsiteFilter(props) {
|
|
|
152
152
|
filteredRestrictionEnzymes.length > 1;
|
|
153
153
|
const [queryTracker, setQueryTracker] = useState("");
|
|
154
154
|
|
|
155
|
-
const renderOptions = (
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
const renderOptions = (
|
|
156
|
+
{ label, value, canBeHidden },
|
|
157
|
+
{ filteredRestrictionEnzymes, filteredRestrictionEnzymesUpdate }
|
|
158
|
+
) => (
|
|
159
|
+
<div
|
|
160
|
+
style={{
|
|
161
|
+
display: "flex",
|
|
162
|
+
justifyContent: "space-between",
|
|
163
|
+
width: "100%"
|
|
164
|
+
}}
|
|
165
|
+
>
|
|
166
|
+
{label}{" "}
|
|
167
|
+
{canBeHidden && (
|
|
168
|
+
<Icon
|
|
169
|
+
onClick={e => {
|
|
170
|
+
e.stopPropagation();
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
isHidden: true,
|
|
183
|
-
canBeHidden
|
|
184
|
-
})
|
|
185
|
-
);
|
|
186
|
-
}}
|
|
187
|
-
htmlTitle="Hide this enzyme"
|
|
188
|
-
className="veHideEnzymeBtn"
|
|
189
|
-
style={{ paddingTop: 5 }}
|
|
190
|
-
iconSize={14}
|
|
191
|
-
icon="eye-off"
|
|
192
|
-
></Icon>
|
|
193
|
-
)}
|
|
194
|
-
</div>
|
|
195
|
-
);
|
|
196
|
-
};
|
|
172
|
+
filteredRestrictionEnzymesUpdate(
|
|
173
|
+
flatMap(filteredRestrictionEnzymes, e => {
|
|
174
|
+
if (e.value === value) return [];
|
|
175
|
+
return e;
|
|
176
|
+
}).concat({
|
|
177
|
+
label,
|
|
178
|
+
className: "veHiddenEnzyme",
|
|
179
|
+
value,
|
|
180
|
+
// hiddenEnzyme: true,
|
|
181
|
+
isHidden: true,
|
|
182
|
+
canBeHidden
|
|
183
|
+
})
|
|
184
|
+
);
|
|
185
|
+
}}
|
|
186
|
+
htmlTitle="Hide this enzyme"
|
|
187
|
+
className="veHideEnzymeBtn"
|
|
188
|
+
style={{ paddingTop: 5 }}
|
|
189
|
+
iconSize={14}
|
|
190
|
+
icon="eye-off"
|
|
191
|
+
/>
|
|
192
|
+
)}
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
197
195
|
const filteredRestrictionEnzymesUpdate = enzymes => {
|
|
198
196
|
_filteredRestrictionEnzymesUpdate(enzymes);
|
|
199
197
|
if (sequenceData?.id) {
|
|
@@ -285,7 +283,7 @@ export function CutsiteFilter(props) {
|
|
|
285
283
|
data-tip="Manage Enzymes"
|
|
286
284
|
onClick={onManageClick}
|
|
287
285
|
icon="cog"
|
|
288
|
-
|
|
286
|
+
/>
|
|
289
287
|
)}
|
|
290
288
|
<div
|
|
291
289
|
style={{
|
|
@@ -345,19 +343,17 @@ export function CutsiteFilter(props) {
|
|
|
345
343
|
wrapperStyle={{ zIndex: 11 }}
|
|
346
344
|
noResultsText={
|
|
347
345
|
<NoResults
|
|
348
|
-
{
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}}
|
|
360
|
-
></NoResults>
|
|
346
|
+
inputSequenceToTestAgainst={sequenceData.sequence}
|
|
347
|
+
manageEnzymesLink={manageEnzymesLink}
|
|
348
|
+
closeDropDown={closeDropDown}
|
|
349
|
+
onHiddenEnzymeAdd={onHiddenEnzymeAdd}
|
|
350
|
+
queryString={queryTracker}
|
|
351
|
+
additionalEnzymes={additionalEnzymes}
|
|
352
|
+
enzymeGroupsOverride={enzymeGroupsOverride}
|
|
353
|
+
cutsitesByNameActive={filteredCutsites.cutsitesByName}
|
|
354
|
+
cutsitesByName={allCutsites.cutsitesByName}
|
|
355
|
+
editorName={editorName}
|
|
356
|
+
/>
|
|
361
357
|
}
|
|
362
358
|
onInputChange={queryTracker => {
|
|
363
359
|
setQueryTracker(queryTracker);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// import Ladder from "./Ladder";
|
|
3
3
|
import { compose, withProps } from "recompose";
|
|
4
4
|
// import selectionLayer from "../redux/selectionLayer";
|
|
5
|
-
import React from "react";
|
|
5
|
+
import React, { useState } from "react";
|
|
6
6
|
import { DataTable } from "@teselagen/ui";
|
|
7
7
|
import { getCutsiteType, getVirtualDigest } from "@teselagen/sequence-utils";
|
|
8
8
|
import CutsiteFilter from "../CutsiteFilter";
|
|
@@ -18,153 +18,154 @@ import {
|
|
|
18
18
|
} from "@blueprintjs/core";
|
|
19
19
|
import withEditorInteractions from "../withEditorInteractions";
|
|
20
20
|
import { userDefinedHandlersAndOpts } from "../Editor/userDefinedHandlersAndOpts";
|
|
21
|
-
import {
|
|
21
|
+
import { pick } from "lodash-es";
|
|
22
22
|
|
|
23
23
|
const MAX_DIGEST_CUTSITES = 50;
|
|
24
24
|
const MAX_PARTIAL_DIGEST_CUTSITES = 10;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
style={{ marginLeft: 5 }}
|
|
58
|
-
>
|
|
59
|
-
{" "}
|
|
60
|
-
Save
|
|
61
|
-
</Button>
|
|
62
|
-
</div>
|
|
63
|
-
)}
|
|
64
|
-
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
|
65
|
-
<Checkbox
|
|
66
|
-
onChange={() => {
|
|
67
|
-
updateComputePartialDigest(!computePartialDigest);
|
|
25
|
+
|
|
26
|
+
export const DigestTool = props => {
|
|
27
|
+
const [selectedTab, setSelectedTab] = useState("virtualDigest");
|
|
28
|
+
const {
|
|
29
|
+
editorName,
|
|
30
|
+
// height = 100,
|
|
31
|
+
dimensions = {},
|
|
32
|
+
lanes,
|
|
33
|
+
digestTool: { selectedFragment, computePartialDigest },
|
|
34
|
+
onDigestSave,
|
|
35
|
+
computePartialDigestDisabled,
|
|
36
|
+
computeDigestDisabled,
|
|
37
|
+
updateComputePartialDigest,
|
|
38
|
+
boxHeight,
|
|
39
|
+
digestLaneRightClicked,
|
|
40
|
+
ladders
|
|
41
|
+
} = props;
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
style={{
|
|
45
|
+
height: typeof dimensions.height === "string" ? 100 : dimensions.height,
|
|
46
|
+
overflowY: "auto",
|
|
47
|
+
padding: 10
|
|
48
|
+
}}
|
|
49
|
+
>
|
|
50
|
+
{onDigestSave && (
|
|
51
|
+
<div style={{ display: "flex", marginBottom: 10 }}>
|
|
52
|
+
<InputGroup placeholder="My Digest" />
|
|
53
|
+
<Button
|
|
54
|
+
intent={Intent.PRIMARY}
|
|
55
|
+
onClick={() => {
|
|
56
|
+
onDigestSave({});
|
|
68
57
|
}}
|
|
69
|
-
|
|
70
|
-
label={
|
|
71
|
-
<span>
|
|
72
|
-
Show Partial Digests{" "}
|
|
73
|
-
{computePartialDigestDisabled ? (
|
|
74
|
-
<span style={{ fontSize: 10 }}>
|
|
75
|
-
{" "}
|
|
76
|
-
-- Disabled (only supports {MAX_PARTIAL_DIGEST_CUTSITES} or
|
|
77
|
-
fewer cut sites){" "}
|
|
78
|
-
</span>
|
|
79
|
-
) : null}
|
|
80
|
-
</span>
|
|
81
|
-
}
|
|
82
|
-
disabled={computePartialDigestDisabled}
|
|
83
|
-
></Checkbox>
|
|
84
|
-
<a
|
|
85
|
-
target="_blank"
|
|
86
|
-
rel="noopener noreferrer"
|
|
87
|
-
href="http://docs.teselagen.com/en/articles/5489322-restriction-digest-in-the-vector-editor"
|
|
58
|
+
style={{ marginLeft: 5 }}
|
|
88
59
|
>
|
|
89
|
-
|
|
90
|
-
|
|
60
|
+
{" "}
|
|
61
|
+
Save
|
|
62
|
+
</Button>
|
|
91
63
|
</div>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
<br />
|
|
98
|
-
{computeDigestDisabled && (
|
|
99
|
-
<div
|
|
100
|
-
style={{
|
|
101
|
-
color: "red",
|
|
102
|
-
marginBottom: "6px",
|
|
103
|
-
fontSize: "15px"
|
|
104
|
-
}}
|
|
105
|
-
>
|
|
106
|
-
{`>${MAX_DIGEST_CUTSITES} cut sites detected. Filter out additional
|
|
107
|
-
restriction enzymes to visualize digest results`}
|
|
108
|
-
</div>
|
|
109
|
-
)}
|
|
110
|
-
<Tabs
|
|
111
|
-
selectedTabId={selectedTab}
|
|
112
|
-
onChange={id => {
|
|
113
|
-
this.setState({ selectedTab: id });
|
|
64
|
+
)}
|
|
65
|
+
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
|
66
|
+
<Checkbox
|
|
67
|
+
onChange={() => {
|
|
68
|
+
updateComputePartialDigest(!computePartialDigest);
|
|
114
69
|
}}
|
|
70
|
+
checked={computePartialDigest}
|
|
71
|
+
label={
|
|
72
|
+
<span>
|
|
73
|
+
Show Partial Digests{" "}
|
|
74
|
+
{computePartialDigestDisabled ? (
|
|
75
|
+
<span style={{ fontSize: 10 }}>
|
|
76
|
+
{" "}
|
|
77
|
+
-- Disabled (only supports {MAX_PARTIAL_DIGEST_CUTSITES} or
|
|
78
|
+
fewer cut sites){" "}
|
|
79
|
+
</span>
|
|
80
|
+
) : null}
|
|
81
|
+
</span>
|
|
82
|
+
}
|
|
83
|
+
disabled={computePartialDigestDisabled}
|
|
84
|
+
/>
|
|
85
|
+
<a
|
|
86
|
+
target="_blank"
|
|
87
|
+
rel="noopener noreferrer"
|
|
88
|
+
href="http://docs.teselagen.com/en/articles/5489322-restriction-digest-in-the-vector-editor"
|
|
115
89
|
>
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
id="virtualDigest"
|
|
119
|
-
panel={<Ladder {...this.props} editorName={editorName} />}
|
|
120
|
-
/>
|
|
121
|
-
<Tab
|
|
122
|
-
title="Digest Info"
|
|
123
|
-
id="table"
|
|
124
|
-
panel={
|
|
125
|
-
<DataTable
|
|
126
|
-
noRouter
|
|
127
|
-
isSimple
|
|
128
|
-
maxHeight={400}
|
|
129
|
-
// noFooter
|
|
130
|
-
withSearch={false}
|
|
131
|
-
onSingleRowSelect={({ onFragmentSelect }) => {
|
|
132
|
-
onFragmentSelect();
|
|
133
|
-
}}
|
|
134
|
-
reduxFormSelectedEntityIdMap={{
|
|
135
|
-
input: {
|
|
136
|
-
value: {
|
|
137
|
-
[selectedFragment]: true
|
|
138
|
-
},
|
|
139
|
-
onChange: noop
|
|
140
|
-
}
|
|
141
|
-
}}
|
|
142
|
-
formName="digestInfoTable"
|
|
143
|
-
entities={lanes[0].map(
|
|
144
|
-
({ id, cut1, cut2, start, end, size, ...rest }) => {
|
|
145
|
-
return {
|
|
146
|
-
...rest,
|
|
147
|
-
id,
|
|
148
|
-
start,
|
|
149
|
-
end,
|
|
150
|
-
length: size,
|
|
151
|
-
leftCutter: cut1.restrictionEnzyme.name,
|
|
152
|
-
rightCutter: cut2.restrictionEnzyme.name,
|
|
153
|
-
leftOverhang: getCutsiteType(cut1.restrictionEnzyme),
|
|
154
|
-
rightOverhang: getCutsiteType(cut2.restrictionEnzyme)
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
)}
|
|
158
|
-
schema={schema}
|
|
159
|
-
/>
|
|
160
|
-
}
|
|
161
|
-
/>
|
|
162
|
-
</Tabs>
|
|
163
|
-
<br />
|
|
90
|
+
Read the docs
|
|
91
|
+
</a>
|
|
164
92
|
</div>
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
93
|
+
Choose your enzymes:
|
|
94
|
+
<CutsiteFilter
|
|
95
|
+
{...pick(props, userDefinedHandlersAndOpts)}
|
|
96
|
+
editorName={editorName}
|
|
97
|
+
/>
|
|
98
|
+
<br />
|
|
99
|
+
{computeDigestDisabled && (
|
|
100
|
+
<div
|
|
101
|
+
style={{
|
|
102
|
+
color: "red",
|
|
103
|
+
marginBottom: "6px",
|
|
104
|
+
fontSize: "15px"
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
{`>${MAX_DIGEST_CUTSITES} cut sites detected. Filter out additional
|
|
108
|
+
restriction enzymes to visualize digest results`}
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
<Tabs
|
|
112
|
+
selectedTabId={selectedTab}
|
|
113
|
+
onChange={id => {
|
|
114
|
+
setSelectedTab(id);
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
<Tab
|
|
118
|
+
title="Virtual Digest"
|
|
119
|
+
id="virtualDigest"
|
|
120
|
+
panel={
|
|
121
|
+
<Ladder
|
|
122
|
+
boxHeight={boxHeight}
|
|
123
|
+
lanes={lanes}
|
|
124
|
+
digestLaneRightClicked={digestLaneRightClicked}
|
|
125
|
+
selectedFragment={selectedFragment}
|
|
126
|
+
ladders={ladders}
|
|
127
|
+
/>
|
|
128
|
+
}
|
|
129
|
+
/>
|
|
130
|
+
<Tab
|
|
131
|
+
title="Digest Info"
|
|
132
|
+
id="table"
|
|
133
|
+
panel={
|
|
134
|
+
<DataTable
|
|
135
|
+
noRouter
|
|
136
|
+
isSimple
|
|
137
|
+
maxHeight={400}
|
|
138
|
+
// noFooter
|
|
139
|
+
withSearch={false}
|
|
140
|
+
onSingleRowSelect={({ onFragmentSelect }) => {
|
|
141
|
+
onFragmentSelect();
|
|
142
|
+
}}
|
|
143
|
+
formName="digestInfoTable"
|
|
144
|
+
entities={lanes[0].map(
|
|
145
|
+
({ id, cut1, cut2, start, end, size, ...rest }) => {
|
|
146
|
+
return {
|
|
147
|
+
...rest,
|
|
148
|
+
id,
|
|
149
|
+
start,
|
|
150
|
+
end,
|
|
151
|
+
length: size,
|
|
152
|
+
leftCutter: cut1.restrictionEnzyme.name,
|
|
153
|
+
rightCutter: cut2.restrictionEnzyme.name,
|
|
154
|
+
leftOverhang: getCutsiteType(cut1.restrictionEnzyme),
|
|
155
|
+
rightOverhang: getCutsiteType(cut2.restrictionEnzyme)
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
)}
|
|
159
|
+
schema={schema}
|
|
160
|
+
/>
|
|
161
|
+
}
|
|
162
|
+
/>
|
|
163
|
+
</Tabs>
|
|
164
|
+
<br />
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
|
|
168
169
|
const schema = {
|
|
169
170
|
fields: [
|
|
170
171
|
{ width: 60, path: "start", displayName: "Start", type: "string" },
|
|
@@ -179,45 +180,46 @@ const schema = {
|
|
|
179
180
|
|
|
180
181
|
export default compose(
|
|
181
182
|
withEditorInteractions,
|
|
182
|
-
withProps(
|
|
183
|
-
|
|
183
|
+
withProps(
|
|
184
|
+
({
|
|
184
185
|
sequenceData,
|
|
185
186
|
sequenceLength,
|
|
186
187
|
selectionLayerUpdate,
|
|
187
188
|
updateSelectedFragment,
|
|
188
189
|
digestTool: { computePartialDigest }
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
190
|
+
}) => {
|
|
191
|
+
const isCircular = sequenceData.circular;
|
|
192
|
+
const cutsites = sequenceData.cutsites;
|
|
193
|
+
const computePartialDigestDisabled =
|
|
194
|
+
cutsites.length > MAX_PARTIAL_DIGEST_CUTSITES;
|
|
195
|
+
const computeDigestDisabled = cutsites.length > MAX_DIGEST_CUTSITES;
|
|
195
196
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
197
|
+
const { fragments, overlappingEnzymes } = getVirtualDigest({
|
|
198
|
+
cutsites,
|
|
199
|
+
sequenceLength,
|
|
200
|
+
isCircular,
|
|
201
|
+
computePartialDigest,
|
|
202
|
+
computePartialDigestDisabled,
|
|
203
|
+
computeDigestDisabled
|
|
204
|
+
});
|
|
205
|
+
return {
|
|
206
|
+
computePartialDigestDisabled,
|
|
207
|
+
computeDigestDisabled,
|
|
208
|
+
lanes: [
|
|
209
|
+
fragments.map(f => ({
|
|
210
|
+
...f,
|
|
211
|
+
onFragmentSelect: () => {
|
|
212
|
+
selectionLayerUpdate({
|
|
213
|
+
start: f.start,
|
|
214
|
+
end: f.end,
|
|
215
|
+
name: f.name
|
|
216
|
+
});
|
|
217
|
+
updateSelectedFragment(f.Intentid);
|
|
218
|
+
}
|
|
219
|
+
}))
|
|
220
|
+
],
|
|
221
|
+
overlappingEnzymes
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
)
|
|
223
225
|
)(DigestTool);
|
package/src/PCRTool/PCRTool.js
CHANGED
|
@@ -123,7 +123,10 @@ function PCRTool(props) {
|
|
|
123
123
|
inlineLabel
|
|
124
124
|
tooltipError
|
|
125
125
|
options={forwardPrimers}
|
|
126
|
-
defaultValue={
|
|
126
|
+
defaultValue={
|
|
127
|
+
forwardPrimer ??
|
|
128
|
+
(forwardPrimers[0] ? forwardPrimers[0].value : undefined)
|
|
129
|
+
}
|
|
127
130
|
name="forwardPrimer"
|
|
128
131
|
label="Forward Primer:"
|
|
129
132
|
/>
|
|
@@ -132,7 +135,10 @@ function PCRTool(props) {
|
|
|
132
135
|
inlineLabel
|
|
133
136
|
tooltipError
|
|
134
137
|
options={reversePrimers}
|
|
135
|
-
defaultValue={
|
|
138
|
+
defaultValue={
|
|
139
|
+
reversePrimer ??
|
|
140
|
+
(reversePrimers[0] ? reversePrimers[0].value : undefined)
|
|
141
|
+
}
|
|
136
142
|
name="reversePrimer"
|
|
137
143
|
label="Reverse Primer:"
|
|
138
144
|
/>
|
|
@@ -190,7 +190,7 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
190
190
|
sequenceData = { sequence: "" },
|
|
191
191
|
handleSubmit,
|
|
192
192
|
beforeAnnotationCreate,
|
|
193
|
-
|
|
193
|
+
RenderTypes,
|
|
194
194
|
renderTags,
|
|
195
195
|
RenderBases,
|
|
196
196
|
allowMultipleFeatureDirections,
|
|
@@ -210,6 +210,7 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
210
210
|
overlapsSelf,
|
|
211
211
|
start,
|
|
212
212
|
end,
|
|
213
|
+
type,
|
|
213
214
|
readOnly,
|
|
214
215
|
getAdditionalEditAnnotationComps,
|
|
215
216
|
advancedOptions,
|
|
@@ -370,7 +371,9 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
370
371
|
/>
|
|
371
372
|
))}
|
|
372
373
|
|
|
373
|
-
{
|
|
374
|
+
{RenderTypes && (
|
|
375
|
+
<RenderTypes readOnly={this.props.readOnly} type={type}></RenderTypes>
|
|
376
|
+
)}
|
|
374
377
|
{renderTags || null}
|
|
375
378
|
|
|
376
379
|
{/* {allowPrimerBasesToBeEdited && RenderBases ? null : !renderLocations || */}
|
|
@@ -387,7 +390,7 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
387
390
|
format={this.formatStart}
|
|
388
391
|
parse={this.parseStart}
|
|
389
392
|
tooltipError
|
|
390
|
-
defaultValue={1}
|
|
393
|
+
defaultValue={start ?? 1}
|
|
391
394
|
min={1}
|
|
392
395
|
max={sequenceLength || 1}
|
|
393
396
|
name="start"
|
|
@@ -401,7 +404,7 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
401
404
|
parse={this.parseEnd}
|
|
402
405
|
inlineLabel
|
|
403
406
|
tooltipError
|
|
404
|
-
defaultValue={sequenceData.isProtein ? 3 : 1}
|
|
407
|
+
defaultValue={end ?? (sequenceData.isProtein ? 3 : 1)}
|
|
405
408
|
min={1}
|
|
406
409
|
max={sequenceLength || 1}
|
|
407
410
|
name="end"
|
|
@@ -569,6 +572,7 @@ export default ({ formName, getProps, dialogProps }) => {
|
|
|
569
572
|
tgFormValues(
|
|
570
573
|
"start",
|
|
571
574
|
"end",
|
|
575
|
+
"type",
|
|
572
576
|
"overlapsSelf",
|
|
573
577
|
"locations",
|
|
574
578
|
"bases",
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
import AddOrEditAnnotationDialog from "../AddOrEditAnnotationDialog";
|
|
8
8
|
import { ReactSelectField } from "@teselagen/ui";
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const RenderTypes = ({ readOnly, type }) => (
|
|
11
11
|
<ReactSelectField
|
|
12
12
|
inlineLabel
|
|
13
13
|
tooltipError
|
|
14
14
|
disabled={readOnly}
|
|
15
|
-
defaultValue="misc_feature"
|
|
16
|
-
options={getFeatureTypes().map(
|
|
15
|
+
defaultValue={type ?? "misc_feature"}
|
|
16
|
+
options={getFeatureTypes().map(featureType => {
|
|
17
17
|
return {
|
|
18
18
|
label: (
|
|
19
19
|
<div
|
|
@@ -25,16 +25,18 @@ const renderTypes = ({ readOnly }) => (
|
|
|
25
25
|
>
|
|
26
26
|
<div
|
|
27
27
|
style={{
|
|
28
|
-
background: getFeatureToColorMap({ includeHidden: true })[
|
|
28
|
+
background: getFeatureToColorMap({ includeHidden: true })[
|
|
29
|
+
featureType
|
|
30
|
+
],
|
|
29
31
|
height: 15,
|
|
30
32
|
width: 15,
|
|
31
33
|
marginRight: 5
|
|
32
34
|
}}
|
|
33
35
|
/>
|
|
34
|
-
{
|
|
36
|
+
{featureType}
|
|
35
37
|
</div>
|
|
36
38
|
),
|
|
37
|
-
value:
|
|
39
|
+
value: featureType
|
|
38
40
|
};
|
|
39
41
|
})}
|
|
40
42
|
name="type"
|
|
@@ -52,7 +54,7 @@ export default AddOrEditAnnotationDialog({
|
|
|
52
54
|
upsertAnnotation: props.upsertFeature,
|
|
53
55
|
// renderLocations: true, //tnw enable this eventually for proteins
|
|
54
56
|
renderLocations: !props.sequenceData.isProtein,
|
|
55
|
-
|
|
57
|
+
RenderTypes,
|
|
56
58
|
annotationTypePlural: "features"
|
|
57
59
|
})
|
|
58
60
|
});
|