@teselagen/ove 0.3.11 → 0.3.13
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/index.js +529 -422
- package/index.mjs +530 -423
- package/index.umd.js +532 -402
- package/package.json +2 -2
- package/src/AlignmentView/AlignmentVisibilityTool.js +1 -1
- package/src/AlignmentView/EditTrackNameDialog.js +1 -5
- package/src/AlignmentView/HorizontalPanelDragHandle.js +2 -2
- package/src/AlignmentView/Minimap.js +12 -12
- package/src/AlignmentView/PairwiseAlignmentView.js +1 -1
- package/src/AlignmentView/getGapMap.js +1 -1
- package/src/AlignmentView/getTrackFromEvent.js +1 -1
- package/src/AlignmentView/index.js +32 -37
- package/src/AutoAnnotate.js +48 -48
- package/src/CircularView/Cutsites.js +3 -3
- package/src/CircularView/Labels/index.js +7 -7
- package/src/CircularView/Labels/relaxLabels_DEPRECATED.js +5 -5
- package/src/CircularView/RotateCircularViewSlider.js +1 -1
- package/src/CircularView/SelectionLayer.js +2 -2
- package/src/CircularView/drawAnnotations.js +3 -3
- package/src/CircularView/getAngleForPositionMidpoint.js +1 -1
- package/src/CircularView/index.d.ts +11 -11
- package/src/CircularView/index.js +9 -9
- package/src/CreateAnnotationsPage.js +7 -5
- package/src/CreateCustomEnzyme/index.js +1 -5
- package/src/CutsiteFilter/AdditionalCutsiteInfoDialog.js +11 -11
- package/src/CutsiteFilter/index.js +12 -12
- package/src/DigestTool/AddLaddersDialog.js +1 -1
- package/src/DigestTool/DigestTool.js +3 -3
- package/src/DigestTool/Ladder.js +8 -8
- package/src/DigestTool/ladderDefaults.js +1 -2
- package/src/Editor/CommandHotkeyHandler.js +1 -1
- package/src/Editor/DropHandler.js +2 -2
- package/src/Editor/index.js +15 -15
- package/src/Editor/userDefinedHandlersAndOpts.js +3 -1
- package/src/FindBar/index.js +6 -6
- package/src/GlobalDialogUtils.js +6 -0
- package/src/LinearView/ZoomLinearView.js +1 -1
- package/src/LinearView/index.js +7 -7
- package/src/MenuBar/index.js +1 -1
- package/src/MenuBar/viewSubmenu.js +1 -1
- package/src/PCRTool/PCRTool.js +19 -19
- package/src/Reflex/Browser.js +4 -5
- package/src/Reflex/ReflexContainer.js +3 -3
- package/src/Reflex/ReflexElement.js +2 -2
- package/src/RowItem/Axis.js +1 -1
- package/src/RowItem/Caret/index.js +1 -1
- package/src/RowItem/Chromatograms/Chromatogram.js +3 -3
- package/src/RowItem/CutsiteSelectionLayers.js +1 -1
- package/src/RowItem/Cutsites.js +1 -1
- package/src/RowItem/Labels.js +2 -2
- package/src/RowItem/Orfs.js +2 -2
- package/src/RowItem/Sequence.js +4 -4
- package/src/RowItem/StackedAnnotations/PointedAnnotation.js +3 -3
- package/src/RowItem/StackedAnnotations/getStructuredBases.js +1 -1
- package/src/RowItem/Translations/AASliver.js +71 -75
- package/src/RowItem/Translations/index.js +1 -1
- package/src/RowItem/getCutsiteLabelHeights.js +1 -1
- package/src/RowItem/index.js +14 -8
- package/src/RowView/estimateRowHeight.js +5 -5
- package/src/RowView/index.d.ts +7 -7
- package/src/RowView/index.js +11 -12
- package/src/SimpleCircularOrLinearView.js +6 -6
- package/src/StatusBar/MeltingTemp.js +3 -3
- package/src/StatusBar/index.js +29 -33
- package/src/ToolBar/ToolbarItem.js +2 -2
- package/src/ToolBar/alignmentTool.js +9 -9
- package/src/ToolBar/editTool.js +41 -37
- package/src/ToolBar/findTool.js +2 -2
- package/src/ToolBar/importTool.js +1 -1
- package/src/ToolBar/index.js +2 -2
- package/src/ToolBar/oligoTool.js +1 -1
- package/src/ToolBar/orfTool.js +1 -6
- package/src/ToolBar/printTool.js +2 -2
- package/src/ToolBar/visibilityTool.js +1 -1
- package/src/VersionHistoryView/index.js +2 -2
- package/src/commands/index.js +237 -230
- package/src/createVectorEditor/index.js +4 -4
- package/src/fileUtils.js +18 -18
- package/src/helperComponents/AddOrEditAnnotationDialog/index.js +22 -15
- package/src/helperComponents/AddOrEditFeatureDialog/index.js +2 -2
- package/src/helperComponents/AddOrEditPartDialog/index.js +2 -2
- package/src/helperComponents/AddOrEditPrimerDialog/index.js +5 -5
- package/src/helperComponents/EnzymesDialog/index.js +17 -22
- package/src/helperComponents/GoToDialog.js +5 -1
- package/src/helperComponents/MergeFeaturesDialog/index.js +3 -3
- package/src/helperComponents/PinchHelper/PinchHelper.js +1 -1
- package/src/helperComponents/PrintDialog/index.js +4 -4
- package/src/helperComponents/PropertiesDialog/CutsiteProperties.js +3 -3
- package/src/helperComponents/PropertiesDialog/GenbankView.js +1 -1
- package/src/helperComponents/PropertiesDialog/GeneralProperties.js +10 -8
- package/src/helperComponents/PropertiesDialog/GenericAnnotationProperties.js +136 -138
- package/src/helperComponents/PropertiesDialog/OrfProperties.js +3 -3
- package/src/helperComponents/PropertiesDialog/PrimerProperties.js +1 -1
- package/src/helperComponents/PropertiesDialog/TranslationProperties.js +2 -2
- package/src/helperComponents/PropertiesDialog/index.js +3 -3
- package/src/helperComponents/RemoveDuplicates/index.js +3 -3
- package/src/helperComponents/SelectDialog.js +3 -3
- package/src/helperComponents/UncontrolledSliderWithPlusMinusBtns.js +5 -5
- package/src/helperComponents/createSimpleDialog.js +1 -1
- package/src/helperComponents/partTagSearch.js +2 -5
- package/src/helperComponents/withHover.js +3 -3
- package/src/redux/alignments.js +6 -6
- package/src/redux/annotationVisibility.js +4 -4
- package/src/redux/featureLengthsToHide.js +1 -1
- package/src/redux/frameTranslations.js +3 -3
- package/src/redux/middleware.js +2 -2
- package/src/redux/panelsShown.js +19 -19
- package/src/redux/partLengthsToHide.js +1 -1
- package/src/redux/primerLengthsToHide.js +1 -1
- package/src/redux/readOnly.js +1 -4
- package/src/redux/selectionLayer.js +1 -1
- package/src/redux/sequenceData/features.js +1 -1
- package/src/redux/sequenceData/upsertDeleteActionGenerator.js +1 -1
- package/src/redux/sequenceDataHistory.js +5 -5
- package/src/redux/toolBar.js +2 -4
- package/src/redux/utils/createMetaAction.js +2 -2
- package/src/redux/versionHistory.js +1 -2
- package/src/selectors/annotationSearchSelector.js +4 -4
- package/src/selectors/circularSelector.js +1 -1
- package/src/selectors/cutsiteLabelColorSelector.js +1 -1
- package/src/selectors/filteredCutsitesSelector.js +6 -6
- package/src/selectors/filteredFeaturesSelector.js +4 -4
- package/src/selectors/filteredPartsSelector.js +5 -5
- package/src/selectors/filteredPrimersSelector.js +3 -3
- package/src/selectors/isEnzymeFilterAndSelector.js +1 -1
- package/src/selectors/orfsSelector.js +1 -1
- package/src/selectors/restrictionEnzymesSelector.js +2 -2
- package/src/selectors/searchLayersSelector.js +7 -7
- package/src/selectors/sequenceLengthSelector.js +1 -1
- package/src/selectors/sequenceSelector.js +1 -1
- package/src/selectors/tagsToBoldSelector.js +1 -1
- package/src/selectors/translationsSelector.js +7 -7
- package/src/updateEditor.js +1 -1
- package/src/utils/PassThrough.js +1 -1
- package/src/utils/addWrappedAddons.js +1 -1
- package/src/utils/annotationTypes.js +2 -2
- package/src/utils/combineReducersDontIgnoreKeys.js +1 -1
- package/src/utils/editorUtils.js +2 -2
- package/src/utils/massageTickSpacing.js +1 -1
- package/src/utils/onlyUpdateForKeysDeep.js +1 -1
- package/src/utils/pureNoFunc.js +1 -1
- package/src/utils/shouldRerender.js +1 -1
- package/src/utils/showFileDialog.js +6 -7
- package/src/utils/updateLabelsForInViewFeatures.js +1 -1
- package/src/utils/useAnnotationLimits.js +1 -1
- package/src/withEditorInteractions/Keyboard.js +2 -3
- package/src/withEditorInteractions/createSequenceInputPopup.js +4 -4
- package/src/withEditorInteractions/index.js +93 -55
- package/src/withEditorProps/index.js +39 -37
- package/style.css +138 -138
|
@@ -72,10 +72,10 @@ export default function createVectorEditor(
|
|
|
72
72
|
unmountComponentAtNode(node);
|
|
73
73
|
node.remove();
|
|
74
74
|
};
|
|
75
|
-
editor.updateEditor =
|
|
75
|
+
editor.updateEditor = values => {
|
|
76
76
|
updateEditor(store, editorName, values);
|
|
77
77
|
};
|
|
78
|
-
editor.addAlignment =
|
|
78
|
+
editor.addAlignment = values => {
|
|
79
79
|
addAlignment(store, values);
|
|
80
80
|
};
|
|
81
81
|
editor.getState = () => {
|
|
@@ -98,7 +98,7 @@ export function createVersionHistoryView(
|
|
|
98
98
|
node
|
|
99
99
|
);
|
|
100
100
|
|
|
101
|
-
editor.updateEditor =
|
|
101
|
+
editor.updateEditor = values => {
|
|
102
102
|
updateEditor(store, editorName, values);
|
|
103
103
|
};
|
|
104
104
|
editor.getState = () => {
|
|
@@ -116,7 +116,7 @@ export function createAlignmentView(node, props = {}) {
|
|
|
116
116
|
const editor = {};
|
|
117
117
|
editor.renderResponse = render(<SizedStandaloneAlignment {...props} />, node);
|
|
118
118
|
|
|
119
|
-
editor.updateAlignment =
|
|
119
|
+
editor.updateAlignment = values => {
|
|
120
120
|
addAlignment(store, values);
|
|
121
121
|
};
|
|
122
122
|
editor.updateAlignment(props);
|
package/src/fileUtils.js
CHANGED
|
@@ -3,20 +3,20 @@ import { parse } from "papaparse";
|
|
|
3
3
|
|
|
4
4
|
export const allowedCsvFileTypes = [".csv", ".txt", ".xlsx"];
|
|
5
5
|
|
|
6
|
-
export const isZipFile =
|
|
6
|
+
export const isZipFile = file => {
|
|
7
7
|
const type = file.mimetype || file.type;
|
|
8
8
|
return type === "application/zip" || type === "application/x-zip-compressed";
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
export const getExt =
|
|
12
|
-
export const isExcelFile =
|
|
13
|
-
export const isCsvFile =
|
|
14
|
-
export const isTextFile =
|
|
11
|
+
export const getExt = file => file.name.split(".").pop();
|
|
12
|
+
export const isExcelFile = file => getExt(file) === "xlsx";
|
|
13
|
+
export const isCsvFile = file => getExt(file) === "csv";
|
|
14
|
+
export const isTextFile = file => ["text", "txt"].includes(getExt(file));
|
|
15
15
|
|
|
16
16
|
const defaultCsvParserOptions = {
|
|
17
17
|
header: true,
|
|
18
18
|
skipEmptyLines: "greedy",
|
|
19
|
-
trimHeaders: true
|
|
19
|
+
trimHeaders: true
|
|
20
20
|
// delimiter: ","
|
|
21
21
|
};
|
|
22
22
|
|
|
@@ -24,13 +24,13 @@ export const parseCsvFile = (csvFile, parserOptions = {}) => {
|
|
|
24
24
|
return new Promise((resolve, reject) => {
|
|
25
25
|
parse(csvFile.originFileObj, {
|
|
26
26
|
...defaultCsvParserOptions,
|
|
27
|
-
complete:
|
|
27
|
+
complete: results => {
|
|
28
28
|
if (results && results.errors && results.errors.length) {
|
|
29
29
|
return reject("Error in csv: " + JSON.stringify(results.errors));
|
|
30
30
|
}
|
|
31
31
|
resolve(results);
|
|
32
32
|
},
|
|
33
|
-
error:
|
|
33
|
+
error: error => {
|
|
34
34
|
reject(error);
|
|
35
35
|
},
|
|
36
36
|
...parserOptions
|
|
@@ -42,11 +42,11 @@ export const parseCsvString = (csvString, parserOptions = {}) => {
|
|
|
42
42
|
return parse(csvString, { ...defaultCsvParserOptions, ...parserOptions });
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
export const cleanCommaSeparatedCell =
|
|
45
|
+
export const cleanCommaSeparatedCell = cellData =>
|
|
46
46
|
(cellData || "")
|
|
47
47
|
.split(",")
|
|
48
|
-
.map(
|
|
49
|
-
.filter(
|
|
48
|
+
.map(n => n.trim())
|
|
49
|
+
.filter(n => n);
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Because the csv rows might not have the same header keys in some cases (extended properties)
|
|
@@ -54,17 +54,17 @@ export const cleanCommaSeparatedCell = (cellData) =>
|
|
|
54
54
|
* does not drop fields
|
|
55
55
|
* @param {*} rows
|
|
56
56
|
*/
|
|
57
|
-
export const cleanCsvExport =
|
|
57
|
+
export const cleanCsvExport = rows => {
|
|
58
58
|
const allHeaders = [];
|
|
59
|
-
rows.forEach(
|
|
60
|
-
Object.keys(row).forEach(
|
|
59
|
+
rows.forEach(row => {
|
|
60
|
+
Object.keys(row).forEach(header => {
|
|
61
61
|
if (!allHeaders.includes(header)) {
|
|
62
62
|
allHeaders.push(header);
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
|
-
rows.forEach(
|
|
67
|
-
allHeaders.forEach(
|
|
66
|
+
rows.forEach(row => {
|
|
67
|
+
allHeaders.forEach(header => {
|
|
68
68
|
row[header] = row[header] || "";
|
|
69
69
|
});
|
|
70
70
|
});
|
|
@@ -76,7 +76,7 @@ export const validateCSVRequiredHeaders = (
|
|
|
76
76
|
requiredHeaders,
|
|
77
77
|
filename
|
|
78
78
|
) => {
|
|
79
|
-
const missingRequiredHeaders = requiredHeaders.filter(
|
|
79
|
+
const missingRequiredHeaders = requiredHeaders.filter(field => {
|
|
80
80
|
return !fields.includes(field);
|
|
81
81
|
});
|
|
82
82
|
if (missingRequiredHeaders.length) {
|
|
@@ -88,7 +88,7 @@ export const validateCSVRequiredHeaders = (
|
|
|
88
88
|
};
|
|
89
89
|
|
|
90
90
|
export const validateCSVRow = (row, requiredHeaders, index) => {
|
|
91
|
-
const missingRequiredFields = requiredHeaders.filter(
|
|
91
|
+
const missingRequiredFields = requiredHeaders.filter(field => !row[field]);
|
|
92
92
|
if (missingRequiredFields.length) {
|
|
93
93
|
if (missingRequiredFields.length === 1) {
|
|
94
94
|
return `Row ${index + 1} is missing the required field "${
|
|
@@ -21,7 +21,8 @@ import {
|
|
|
21
21
|
Classes,
|
|
22
22
|
EditableText,
|
|
23
23
|
FormGroup,
|
|
24
|
-
Label
|
|
24
|
+
Label,
|
|
25
|
+
Callout
|
|
25
26
|
} from "@blueprintjs/core";
|
|
26
27
|
import {
|
|
27
28
|
convertRangeTo0Based,
|
|
@@ -47,42 +48,42 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
47
48
|
(this.props.initialValues && this.props.initialValues.notes) || {};
|
|
48
49
|
this.notes = store(
|
|
49
50
|
flatMap(initialNotes, (noteValues, noteType) => {
|
|
50
|
-
return map(noteValues,
|
|
51
|
+
return map(noteValues, value => ({
|
|
51
52
|
key: noteType,
|
|
52
53
|
value: value
|
|
53
54
|
}));
|
|
54
55
|
})
|
|
55
56
|
);
|
|
56
57
|
}
|
|
57
|
-
formatStart =
|
|
58
|
+
formatStart = val => {
|
|
58
59
|
const { isProtein } = this.props.sequenceData || {};
|
|
59
60
|
if (isProtein) {
|
|
60
61
|
return (val + 2) / 3;
|
|
61
62
|
}
|
|
62
63
|
return val;
|
|
63
64
|
};
|
|
64
|
-
formatEnd =
|
|
65
|
+
formatEnd = val => {
|
|
65
66
|
const { isProtein } = this.props.sequenceData || {};
|
|
66
67
|
if (isProtein) {
|
|
67
68
|
return val / 3;
|
|
68
69
|
}
|
|
69
70
|
return val;
|
|
70
71
|
};
|
|
71
|
-
parseStart =
|
|
72
|
+
parseStart = val => {
|
|
72
73
|
const { isProtein } = this.props.sequenceData || {};
|
|
73
74
|
if (isProtein) {
|
|
74
75
|
return val * 3 - 2;
|
|
75
76
|
}
|
|
76
77
|
return val;
|
|
77
78
|
};
|
|
78
|
-
parseEnd =
|
|
79
|
+
parseEnd = val => {
|
|
79
80
|
const { isProtein } = this.props.sequenceData || {};
|
|
80
81
|
if (isProtein) {
|
|
81
82
|
return val * 3;
|
|
82
83
|
}
|
|
83
84
|
return val;
|
|
84
85
|
};
|
|
85
|
-
renderLocations =
|
|
86
|
+
renderLocations = props => {
|
|
86
87
|
const { fields } = props;
|
|
87
88
|
const { sequenceData = { sequence: "" }, start, end } = this.props;
|
|
88
89
|
const sequenceLength = sequenceData.sequence.length;
|
|
@@ -209,6 +210,7 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
209
210
|
overlapsSelf,
|
|
210
211
|
start,
|
|
211
212
|
end,
|
|
213
|
+
readOnly,
|
|
212
214
|
getAdditionalEditAnnotationComps,
|
|
213
215
|
advancedOptions,
|
|
214
216
|
advancedDefaultOpen,
|
|
@@ -228,7 +230,7 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
228
230
|
);
|
|
229
231
|
return (
|
|
230
232
|
<form
|
|
231
|
-
onSubmit={handleSubmit(async
|
|
233
|
+
onSubmit={handleSubmit(async data => {
|
|
232
234
|
let updatedData;
|
|
233
235
|
const forward =
|
|
234
236
|
data.forward !== undefined
|
|
@@ -323,8 +325,13 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
323
325
|
"tg-upsert-annotation"
|
|
324
326
|
)}
|
|
325
327
|
>
|
|
328
|
+
{typeof readOnly === "string" ? (
|
|
329
|
+
<Callout intent="primary" style={{ marginBottom: 10 }}>
|
|
330
|
+
{readOnly}
|
|
331
|
+
</Callout>
|
|
332
|
+
) : null}
|
|
326
333
|
<InputField
|
|
327
|
-
disabled={
|
|
334
|
+
disabled={readOnly}
|
|
328
335
|
inlineLabel
|
|
329
336
|
tooltipError
|
|
330
337
|
autoFocus
|
|
@@ -364,8 +371,8 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
364
371
|
{ label: "Positive", value: "true" },
|
|
365
372
|
{ label: "Negative", value: "false" }
|
|
366
373
|
]}
|
|
367
|
-
normalize={
|
|
368
|
-
format={
|
|
374
|
+
normalize={value => value === "true" || false}
|
|
375
|
+
format={value => (value ? "true" : "false")}
|
|
369
376
|
name="forward"
|
|
370
377
|
label="Strand"
|
|
371
378
|
/>
|
|
@@ -457,7 +464,7 @@ class AddOrEditAnnotationDialog extends React.Component {
|
|
|
457
464
|
>
|
|
458
465
|
<Button
|
|
459
466
|
style={{ marginRight: 15 }}
|
|
460
|
-
onMouseDown={
|
|
467
|
+
onMouseDown={e => {
|
|
461
468
|
//use onMouseDown to prevent issues with redux form errors popping in and stopping the dialog from closing
|
|
462
469
|
e.preventDefault();
|
|
463
470
|
e.stopPropagation();
|
|
@@ -599,7 +606,7 @@ const Notes = view(({ readOnly, notes }) => {
|
|
|
599
606
|
style={{ display: "flex", padding: "4px 2px" }}
|
|
600
607
|
>
|
|
601
608
|
<EditableText
|
|
602
|
-
onConfirm={
|
|
609
|
+
onConfirm={string => {
|
|
603
610
|
if (string === "") {
|
|
604
611
|
if (!note.value) {
|
|
605
612
|
notes.splice(i, 1);
|
|
@@ -614,7 +621,7 @@ const Notes = view(({ readOnly, notes }) => {
|
|
|
614
621
|
multiline
|
|
615
622
|
className="addAnnNoteKey"
|
|
616
623
|
// style={{marginRight: 20}}
|
|
617
|
-
onChange={
|
|
624
|
+
onChange={string => {
|
|
618
625
|
note.key = string.replace(" ", "_").replace(/\n/g, "");
|
|
619
626
|
}}
|
|
620
627
|
value={key}
|
|
@@ -631,7 +638,7 @@ const Notes = view(({ readOnly, notes }) => {
|
|
|
631
638
|
// minWidth: 200,
|
|
632
639
|
// maxWidth: 200,
|
|
633
640
|
// }}
|
|
634
|
-
onChange={
|
|
641
|
+
onChange={string => {
|
|
635
642
|
note.value = string.replace(/\n/g, "");
|
|
636
643
|
}}
|
|
637
644
|
value={value}
|
|
@@ -13,7 +13,7 @@ const renderTypes = ({ readOnly }) => (
|
|
|
13
13
|
tooltipError
|
|
14
14
|
disabled={readOnly}
|
|
15
15
|
defaultValue="misc_feature"
|
|
16
|
-
options={getFeatureTypes().map(
|
|
16
|
+
options={getFeatureTypes().map(type => {
|
|
17
17
|
return {
|
|
18
18
|
label: (
|
|
19
19
|
<div
|
|
@@ -48,7 +48,7 @@ export default AddOrEditAnnotationDialog({
|
|
|
48
48
|
// height: 500,
|
|
49
49
|
width: 400
|
|
50
50
|
},
|
|
51
|
-
getProps:
|
|
51
|
+
getProps: props => ({
|
|
52
52
|
upsertAnnotation: props.upsertFeature,
|
|
53
53
|
// renderLocations: true, //tnw enable this eventually for proteins
|
|
54
54
|
renderLocations: !props.sequenceData.isProtein,
|
|
@@ -15,7 +15,7 @@ const renderTypes = ({ readOnly }) => (
|
|
|
15
15
|
tooltipError
|
|
16
16
|
disabled={readOnly}
|
|
17
17
|
defaultValue="misc_feature"
|
|
18
|
-
options={getFeatureTypes().map(
|
|
18
|
+
options={getFeatureTypes().map(type => {
|
|
19
19
|
return {
|
|
20
20
|
label: type,
|
|
21
21
|
// label: (
|
|
@@ -82,7 +82,7 @@ export default AddOrEditAnnotationDialog({
|
|
|
82
82
|
dialogProps: {
|
|
83
83
|
width: 450
|
|
84
84
|
},
|
|
85
|
-
getProps:
|
|
85
|
+
getProps: props => ({
|
|
86
86
|
upsertAnnotation: props.upsertPart,
|
|
87
87
|
advancedDefaultOpen: get(props, "initialValues.overlapsSelf"),
|
|
88
88
|
advancedOptions: props.allowPartsToOverlapSelf
|
|
@@ -38,13 +38,13 @@ const CustomContentEditable = generateField(function CustomContentEditable({
|
|
|
38
38
|
const inputRef = useRef(null);
|
|
39
39
|
const [caretPosition, setCaretPosition] = useState({ start: 0, end: 0 });
|
|
40
40
|
|
|
41
|
-
const emitChange =
|
|
41
|
+
const emitChange = e => {
|
|
42
42
|
const newVal = e.target.innerText;
|
|
43
43
|
const savedCaretPosition = CaretPositioning.saveSelection(e.currentTarget);
|
|
44
44
|
setCaretPosition(savedCaretPosition);
|
|
45
45
|
const acceptedChars = getAcceptedChars(sequenceData);
|
|
46
46
|
let newBases = "";
|
|
47
|
-
newVal.split("").forEach(
|
|
47
|
+
newVal.split("").forEach(letter => {
|
|
48
48
|
if (acceptedChars.includes(letter.toLowerCase())) {
|
|
49
49
|
newBases += letter;
|
|
50
50
|
}
|
|
@@ -137,7 +137,7 @@ const CustomContentEditable = generateField(function CustomContentEditable({
|
|
|
137
137
|
);
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
-
const RenderBases =
|
|
140
|
+
const RenderBases = props => {
|
|
141
141
|
const {
|
|
142
142
|
sequenceData,
|
|
143
143
|
readOnly,
|
|
@@ -312,14 +312,14 @@ const RenderBases = (props) => {
|
|
|
312
312
|
|
|
313
313
|
export default AddOrEditAnnotationDialog({
|
|
314
314
|
formName: "AddOrEditPrimerDialog",
|
|
315
|
-
getProps:
|
|
315
|
+
getProps: props => ({
|
|
316
316
|
upsertAnnotation: props.upsertPrimer,
|
|
317
317
|
annotationTypePlural: "primers",
|
|
318
318
|
RenderBases
|
|
319
319
|
})
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
-
const InnerWrapperMeltingTemp =
|
|
322
|
+
const InnerWrapperMeltingTemp = p => (
|
|
323
323
|
<div
|
|
324
324
|
className="bp3-text-muted bp3-text-small"
|
|
325
325
|
style={{ marginBottom: 15, marginTop: -5, fontStyle: "italic" }}
|
|
@@ -3,11 +3,7 @@ import React from "react";
|
|
|
3
3
|
|
|
4
4
|
// import { reduxForm, formValues } from "redux-form";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
InfoHelper,
|
|
8
|
-
showConfirmationDialog,
|
|
9
|
-
wrapDialog
|
|
10
|
-
} from "@teselagen/ui";
|
|
6
|
+
import { InfoHelper, showConfirmationDialog, wrapDialog } from "@teselagen/ui";
|
|
11
7
|
import { compose } from "redux";
|
|
12
8
|
import {
|
|
13
9
|
Classes,
|
|
@@ -35,7 +31,7 @@ import {
|
|
|
35
31
|
import { store, view } from "@risingstack/react-easy-state";
|
|
36
32
|
import { showDialog } from "../../GlobalDialogUtils";
|
|
37
33
|
|
|
38
|
-
const upsertLocalEnzymeGroups =
|
|
34
|
+
const upsertLocalEnzymeGroups = newGroups => {
|
|
39
35
|
const existingGroups = window.getExistingEnzymeGroups();
|
|
40
36
|
const toUpsert = omitBy(
|
|
41
37
|
//delete any groups that have a value of null/undefined
|
|
@@ -43,7 +39,7 @@ const upsertLocalEnzymeGroups = (newGroups) => {
|
|
|
43
39
|
...existingGroups,
|
|
44
40
|
...newGroups
|
|
45
41
|
},
|
|
46
|
-
|
|
42
|
+
val => {
|
|
47
43
|
return !val;
|
|
48
44
|
}
|
|
49
45
|
);
|
|
@@ -53,7 +49,7 @@ const upsertLocalEnzymeGroups = (newGroups) => {
|
|
|
53
49
|
|
|
54
50
|
window.createNewEnzymeGroup =
|
|
55
51
|
window.createNewEnzymeGroup ||
|
|
56
|
-
(
|
|
52
|
+
(newName => {
|
|
57
53
|
return upsertLocalEnzymeGroups({
|
|
58
54
|
[newName]: []
|
|
59
55
|
});
|
|
@@ -68,7 +64,7 @@ window.editEnzymeGroupName =
|
|
|
68
64
|
});
|
|
69
65
|
window.deleteEnzymeGroup =
|
|
70
66
|
window.deleteEnzymeGroup ||
|
|
71
|
-
(
|
|
67
|
+
(nameToDelete => {
|
|
72
68
|
return upsertLocalEnzymeGroups({
|
|
73
69
|
[nameToDelete]: null
|
|
74
70
|
});
|
|
@@ -138,7 +134,7 @@ class EnzymesDialog extends React.Component {
|
|
|
138
134
|
.forEach(function (key) {
|
|
139
135
|
const group = existingGroups[key];
|
|
140
136
|
orderedExistingGroups[key] = group;
|
|
141
|
-
group.forEach(
|
|
137
|
+
group.forEach(name => {
|
|
142
138
|
const lowerName = name.toLowerCase();
|
|
143
139
|
groupedEnzymesNameMap[lowerName] =
|
|
144
140
|
aliasedEnzymesByName[lowerName] || additionalEnzymes[lowerName];
|
|
@@ -156,14 +152,14 @@ class EnzymesDialog extends React.Component {
|
|
|
156
152
|
"My Enzymes": {
|
|
157
153
|
protected: true,
|
|
158
154
|
name: "My Enzymes",
|
|
159
|
-
enzymes: map(myEnzymes).sort(
|
|
155
|
+
enzymes: map(myEnzymes).sort(e => e.name)
|
|
160
156
|
},
|
|
161
157
|
Hidden: {
|
|
162
158
|
protected: true,
|
|
163
159
|
name: "Hidden",
|
|
164
160
|
tooltipInfo:
|
|
165
161
|
"These less common enzymes are hidden by default. Adding them to a custom group will make them show up in the cutsite filter dropdown.",
|
|
166
|
-
enzymes: map(hiddenEnzymes).sort(
|
|
162
|
+
enzymes: map(hiddenEnzymes).sort(e => e.name)
|
|
167
163
|
},
|
|
168
164
|
...reduce(
|
|
169
165
|
orderedExistingGroups,
|
|
@@ -209,7 +205,7 @@ class EnzymesDialog extends React.Component {
|
|
|
209
205
|
this.state;
|
|
210
206
|
const selectedEnzymesKey = `selectedEnzymes_${selectedEnzymeGroup}`;
|
|
211
207
|
const selectedEnzymesForGroup = this.state[selectedEnzymesKey] || {};
|
|
212
|
-
const selectedCount = countBy(selectedEnzymesForGroup,
|
|
208
|
+
const selectedCount = countBy(selectedEnzymesForGroup, e => e).true || 0;
|
|
213
209
|
const fullSelectedEnzGroup = this.enzymeGroups[selectedEnzymeGroup] || {};
|
|
214
210
|
|
|
215
211
|
const enzymeList = flatMap(fullSelectedEnzGroup.enzymes, (enz, i) => {
|
|
@@ -458,7 +454,7 @@ class EnzymesDialog extends React.Component {
|
|
|
458
454
|
<InputGroup
|
|
459
455
|
round
|
|
460
456
|
placeholder="Search by name or # of cuts"
|
|
461
|
-
onChange={
|
|
457
|
+
onChange={e => {
|
|
462
458
|
this.setState({
|
|
463
459
|
searchInput: e.target.value
|
|
464
460
|
});
|
|
@@ -470,7 +466,7 @@ class EnzymesDialog extends React.Component {
|
|
|
470
466
|
icon="cross"
|
|
471
467
|
minimal
|
|
472
468
|
intent="danger"
|
|
473
|
-
onClick={
|
|
469
|
+
onClick={e => {
|
|
474
470
|
this.setState({ searchInput: "" });
|
|
475
471
|
e.stopPropagation();
|
|
476
472
|
}}
|
|
@@ -531,7 +527,7 @@ class EnzymesDialog extends React.Component {
|
|
|
531
527
|
selectedCount,
|
|
532
528
|
selectedEnzymesForGroup,
|
|
533
529
|
enzymeGroups: this.enzymeGroups,
|
|
534
|
-
setStateAbove:
|
|
530
|
+
setStateAbove: val => {
|
|
535
531
|
this.setState(val);
|
|
536
532
|
}
|
|
537
533
|
}}
|
|
@@ -563,8 +559,7 @@ class EnzymesDialog extends React.Component {
|
|
|
563
559
|
if (confirm) {
|
|
564
560
|
const enzymes = flatMap(
|
|
565
561
|
fullSelectedEnzGroup.enzymes,
|
|
566
|
-
(e)
|
|
567
|
-
selectedEnzymesForGroup[e.name] ? [] : e.name
|
|
562
|
+
e => (selectedEnzymesForGroup[e.name] ? [] : e.name)
|
|
568
563
|
);
|
|
569
564
|
window.updateEnzymeGroup(
|
|
570
565
|
selectedEnzymeGroup,
|
|
@@ -777,7 +772,7 @@ export default compose(
|
|
|
777
772
|
)(EnzymesDialog);
|
|
778
773
|
|
|
779
774
|
function getEnzymesForNames(names, allEnzymesByName) {
|
|
780
|
-
return names.map(
|
|
775
|
+
return names.map(n => {
|
|
781
776
|
return (n && allEnzymesByName[n.toLowerCase()]) || { name: "Not Found!" };
|
|
782
777
|
});
|
|
783
778
|
}
|
|
@@ -790,7 +785,7 @@ class MoveToInner extends React.Component {
|
|
|
790
785
|
setStateAbove,
|
|
791
786
|
enzymeGroups
|
|
792
787
|
} = this.props;
|
|
793
|
-
const enzymeOpts = flatMap(enzymeGroups,
|
|
788
|
+
const enzymeOpts = flatMap(enzymeGroups, g => {
|
|
794
789
|
if (g.protected || g.name === selectedEnzymeGroup) return [];
|
|
795
790
|
return {
|
|
796
791
|
value: g.name
|
|
@@ -827,7 +822,7 @@ class MoveToInner extends React.Component {
|
|
|
827
822
|
<h5>Copy {selectedCount} Enzyme(s) To:</h5>
|
|
828
823
|
|
|
829
824
|
<HTMLSelect
|
|
830
|
-
onChange={
|
|
825
|
+
onChange={e => {
|
|
831
826
|
setStateAbove({
|
|
832
827
|
enzymeGroupToMoveTo: e.target.value
|
|
833
828
|
});
|
|
@@ -841,7 +836,7 @@ class MoveToInner extends React.Component {
|
|
|
841
836
|
const enzymes = uniq([
|
|
842
837
|
...map(
|
|
843
838
|
enzymeGroups[enzymeGroupToMoveTo].enzymes,
|
|
844
|
-
|
|
839
|
+
e => e.name
|
|
845
840
|
),
|
|
846
841
|
...flatMap(selectedEnzymesForGroup, (selected, name) =>
|
|
847
842
|
selected ? name : []
|
|
@@ -38,7 +38,7 @@ class MergeFeaturesDialog extends React.Component {
|
|
|
38
38
|
const feat2 = features[id2];
|
|
39
39
|
const [id1default, id2default] = flatMap(
|
|
40
40
|
selectedAnnotations.idStack,
|
|
41
|
-
|
|
41
|
+
id => {
|
|
42
42
|
const ann = selectedAnnotations.idMap[id];
|
|
43
43
|
if (ann.annotationTypePlural === "features") {
|
|
44
44
|
return id;
|
|
@@ -115,7 +115,7 @@ class MergeFeaturesDialog extends React.Component {
|
|
|
115
115
|
</div>
|
|
116
116
|
</div>
|
|
117
117
|
}
|
|
118
|
-
options={flatMap(features,
|
|
118
|
+
options={flatMap(features, feat => {
|
|
119
119
|
if (feat.id === (feat2 && feat2.id)) return []; //filter out other feature as an option
|
|
120
120
|
return {
|
|
121
121
|
value: feat.id,
|
|
@@ -168,7 +168,7 @@ class MergeFeaturesDialog extends React.Component {
|
|
|
168
168
|
</div>
|
|
169
169
|
</div>
|
|
170
170
|
}
|
|
171
|
-
options={flatMap(features,
|
|
171
|
+
options={flatMap(features, feat => {
|
|
172
172
|
if (feat.id === (feat1 && feat1.id)) return []; //filter out other feature as an option
|
|
173
173
|
return {
|
|
174
174
|
value: feat.id,
|
|
@@ -68,7 +68,7 @@ class PrintDialog extends React.Component {
|
|
|
68
68
|
fullscreen={this.state && this.state.fullscreen}
|
|
69
69
|
circular={isCirc}
|
|
70
70
|
editorName={editorName || "StandaloneEditor"}
|
|
71
|
-
ref={
|
|
71
|
+
ref={el => (this.componentRef = el)}
|
|
72
72
|
/>
|
|
73
73
|
<br />
|
|
74
74
|
{!hidePrintButton && (
|
|
@@ -157,7 +157,7 @@ class ReactToPrint extends React.Component {
|
|
|
157
157
|
removeWindow(targets) {
|
|
158
158
|
targets &&
|
|
159
159
|
setTimeout(() => {
|
|
160
|
-
(Array.isArray(targets) ? targets : [targets]).forEach(
|
|
160
|
+
(Array.isArray(targets) ? targets : [targets]).forEach(target => {
|
|
161
161
|
target.parentNode.removeChild(target);
|
|
162
162
|
});
|
|
163
163
|
}, 500);
|
|
@@ -336,7 +336,7 @@ class ReactToPrint extends React.Component {
|
|
|
336
336
|
}
|
|
337
337
|
} else {
|
|
338
338
|
const attributes = [...(node.attributes || [])];
|
|
339
|
-
attributes.forEach(
|
|
339
|
+
attributes.forEach(attr => {
|
|
340
340
|
newHeadEl.setAttribute(attr.nodeName, attr.nodeValue);
|
|
341
341
|
});
|
|
342
342
|
|
|
@@ -361,7 +361,7 @@ class ReactToPrint extends React.Component {
|
|
|
361
361
|
|
|
362
362
|
render() {
|
|
363
363
|
return React.cloneElement(this.props.trigger(), {
|
|
364
|
-
ref:
|
|
364
|
+
ref: el => (this.triggerRef = el),
|
|
365
365
|
onClick: this.startPrint
|
|
366
366
|
});
|
|
367
367
|
}
|
|
@@ -24,7 +24,7 @@ class CutsiteProperties extends React.Component {
|
|
|
24
24
|
this.commands = commands(this);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
SubComponent =
|
|
27
|
+
SubComponent = row => {
|
|
28
28
|
return (
|
|
29
29
|
<SingleEnzymeCutsiteInfo
|
|
30
30
|
{...{
|
|
@@ -61,12 +61,12 @@ class CutsiteProperties extends React.Component {
|
|
|
61
61
|
} = this.props;
|
|
62
62
|
|
|
63
63
|
const { cutsitesByName, cutsitesById } = allCutsites;
|
|
64
|
-
const cutsitesToUse = map(cutsitesByName,
|
|
64
|
+
const cutsitesToUse = map(cutsitesByName, cutsiteGroup => {
|
|
65
65
|
const name = cutsiteGroup[0].restrictionEnzyme.name;
|
|
66
66
|
let groups = "";
|
|
67
67
|
const exisitingEnzymeGroups = window.getExistingEnzymeGroups();
|
|
68
68
|
|
|
69
|
-
Object.keys(exisitingEnzymeGroups).forEach(
|
|
69
|
+
Object.keys(exisitingEnzymeGroups).forEach(key => {
|
|
70
70
|
if (exisitingEnzymeGroups[key].includes(name)) groups += key;
|
|
71
71
|
groups += " ";
|
|
72
72
|
});
|
|
@@ -3,9 +3,10 @@ import { InputField, BPSelect, TextareaField } from "@teselagen/ui";
|
|
|
3
3
|
import { reduxForm } from "redux-form";
|
|
4
4
|
import withEditorProps from "../../withEditorProps";
|
|
5
5
|
import { compose } from "recompose";
|
|
6
|
+
import { handleReadOnlyChange } from "../../ToolBar/editTool";
|
|
6
7
|
|
|
7
8
|
class GeneralProperties extends React.Component {
|
|
8
|
-
updateSeqDesc =
|
|
9
|
+
updateSeqDesc = val => {
|
|
9
10
|
return this.props.sequenceDescriptionUpdate(val);
|
|
10
11
|
};
|
|
11
12
|
render() {
|
|
@@ -17,7 +18,6 @@ class GeneralProperties extends React.Component {
|
|
|
17
18
|
disableSetReadOnly,
|
|
18
19
|
updateAvailability,
|
|
19
20
|
sequenceData,
|
|
20
|
-
updateReadOnlyMode,
|
|
21
21
|
onSave,
|
|
22
22
|
showAvailability,
|
|
23
23
|
sequenceNameUpdate
|
|
@@ -39,7 +39,7 @@ class GeneralProperties extends React.Component {
|
|
|
39
39
|
<div className="ve-column-right">
|
|
40
40
|
<InputField
|
|
41
41
|
disabled={readOnly}
|
|
42
|
-
onFieldSubmit={
|
|
42
|
+
onFieldSubmit={val => {
|
|
43
43
|
sequenceNameUpdate(val);
|
|
44
44
|
}}
|
|
45
45
|
name="name"
|
|
@@ -55,7 +55,7 @@ class GeneralProperties extends React.Component {
|
|
|
55
55
|
{" "}
|
|
56
56
|
<BPSelect
|
|
57
57
|
disabled={readOnly}
|
|
58
|
-
onChange={
|
|
58
|
+
onChange={val => {
|
|
59
59
|
updateCircular(val === "circular");
|
|
60
60
|
}}
|
|
61
61
|
value={circular ? "circular" : "linear"}
|
|
@@ -77,7 +77,7 @@ class GeneralProperties extends React.Component {
|
|
|
77
77
|
{" "}
|
|
78
78
|
<BPSelect
|
|
79
79
|
disabled={readOnly}
|
|
80
|
-
onChange={
|
|
80
|
+
onChange={val => {
|
|
81
81
|
updateAvailability(val === "available");
|
|
82
82
|
}}
|
|
83
83
|
value={materiallyAvailable ? "available" : "unavailable"}
|
|
@@ -102,10 +102,12 @@ class GeneralProperties extends React.Component {
|
|
|
102
102
|
<div className="ve-column-right">
|
|
103
103
|
{" "}
|
|
104
104
|
<BPSelect
|
|
105
|
+
className={"veReadOnlySelect"}
|
|
105
106
|
disabled={!onSave || disableSetReadOnly}
|
|
106
|
-
onChange={
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
onChange={val =>
|
|
108
|
+
console.log(`val:`, val) ||
|
|
109
|
+
handleReadOnlyChange(val === "readOnly", this.props)
|
|
110
|
+
}
|
|
109
111
|
value={readOnly ? "readOnly" : "editable"}
|
|
110
112
|
options={[
|
|
111
113
|
{ label: "Read Only", value: "readOnly" },
|