@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
package/src/commands/index.js
CHANGED
|
@@ -36,12 +36,13 @@ import {
|
|
|
36
36
|
showDialog
|
|
37
37
|
} from "../GlobalDialogUtils";
|
|
38
38
|
import { partsSubmenu } from "../MenuBar/viewSubmenu";
|
|
39
|
+
import { handleReadOnlyChange } from "../ToolBar/editTool";
|
|
39
40
|
|
|
40
|
-
const isProtein =
|
|
41
|
-
const isOligo =
|
|
42
|
-
const isRna =
|
|
41
|
+
const isProtein = props => props.sequenceData && props.sequenceData.isProtein;
|
|
42
|
+
const isOligo = props => props.sequenceData && props.sequenceData.isOligo;
|
|
43
|
+
const isRna = props => props.sequenceData && props.sequenceData.isRna;
|
|
43
44
|
const partsPrimersFeatures = ["Parts", "Features", "Primers"];
|
|
44
|
-
const getNewTranslationHandler =
|
|
45
|
+
const getNewTranslationHandler = isReverse => ({
|
|
45
46
|
handler: (props, state, ctxInfo) => {
|
|
46
47
|
const annotation =
|
|
47
48
|
get(ctxInfo, "context.annotation") || props.selectionLayer;
|
|
@@ -55,31 +56,31 @@ const getNewTranslationHandler = (isReverse) => ({
|
|
|
55
56
|
});
|
|
56
57
|
props.annotationVisibilityShow("translations");
|
|
57
58
|
},
|
|
58
|
-
isHidden:
|
|
59
|
+
isHidden: props =>
|
|
59
60
|
isProtein(props) ||
|
|
60
61
|
!props.annotationsToSupport ||
|
|
61
62
|
// props.readOnly ||
|
|
62
63
|
!props.annotationsToSupport.translations,
|
|
63
|
-
isDisabled:
|
|
64
|
+
isDisabled: props =>
|
|
64
65
|
/* (props.readOnly && readOnlyDisabledTooltip) || */ props.sequenceLength ===
|
|
65
66
|
0 || noSelection(props)
|
|
66
67
|
});
|
|
67
68
|
|
|
68
69
|
const fileCommandDefs = {
|
|
69
70
|
newSequence: {
|
|
70
|
-
isHidden:
|
|
71
|
+
isHidden: props => !props.onNew,
|
|
71
72
|
handler: (props, ...rest) => props.onNew(props, ...rest)
|
|
72
73
|
},
|
|
73
74
|
|
|
74
75
|
renameSequence: {
|
|
75
|
-
isHidden:
|
|
76
|
-
isDisabled:
|
|
77
|
-
handler:
|
|
76
|
+
isHidden: props => props.readOnly,
|
|
77
|
+
isDisabled: props => props.readOnly && readOnlyDisabledTooltip,
|
|
78
|
+
handler: props => {
|
|
78
79
|
showDialog({
|
|
79
80
|
dialogType: "RenameSequenceDialog",
|
|
80
81
|
props: {
|
|
81
82
|
initialValues: { newName: props.sequenceData.name },
|
|
82
|
-
onSubmit:
|
|
83
|
+
onSubmit: values => {
|
|
83
84
|
props.sequenceNameUpdate(values.newName);
|
|
84
85
|
props.onRename && props.onRename(values.newName, props);
|
|
85
86
|
}
|
|
@@ -90,15 +91,15 @@ const fileCommandDefs = {
|
|
|
90
91
|
|
|
91
92
|
saveSequence: {
|
|
92
93
|
name: "Save",
|
|
93
|
-
isDisabled:
|
|
94
|
+
isDisabled: props =>
|
|
94
95
|
props.alwaysAllowSave
|
|
95
96
|
? false
|
|
96
97
|
: (props.readOnly && readOnlyDisabledTooltip) ||
|
|
97
98
|
!props.sequenceData ||
|
|
98
99
|
props.sequenceData.stateTrackingId === "initialLoadId" ||
|
|
99
100
|
props.sequenceData.stateTrackingId === props.lastSavedId,
|
|
100
|
-
isHidden:
|
|
101
|
-
handler:
|
|
101
|
+
isHidden: props => props.readOnly || !props.handleSave,
|
|
102
|
+
handler: props => props.handleSave(),
|
|
102
103
|
hotkey: "mod+s"
|
|
103
104
|
},
|
|
104
105
|
saveSequenceAs: {
|
|
@@ -108,8 +109,8 @@ const fileCommandDefs = {
|
|
|
108
109
|
// !props.sequenceData ||
|
|
109
110
|
// (props.sequenceData.stateTrackingId === "initialLoadId" ||
|
|
110
111
|
// props.sequenceData.stateTrackingId === props.lastSavedId),
|
|
111
|
-
isHidden:
|
|
112
|
-
handler:
|
|
112
|
+
isHidden: props => !props.onSaveAs,
|
|
113
|
+
handler: props => props.handleSave({ isSaveAs: true }),
|
|
113
114
|
hotkey: "mod+shift+s"
|
|
114
115
|
},
|
|
115
116
|
toolsCmd: {
|
|
@@ -118,15 +119,17 @@ const fileCommandDefs = {
|
|
|
118
119
|
},
|
|
119
120
|
|
|
120
121
|
deleteSequence: {
|
|
121
|
-
isDisabled:
|
|
122
|
-
(props.
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
isDisabled: props =>
|
|
123
|
+
(props.disableBpEditing && bpEditingDisabledTooltip) ||
|
|
124
|
+
(props.readOnly && readOnlyDisabledTooltip) ||
|
|
125
|
+
!props.onDelete,
|
|
126
|
+
isHidden: props => !props.onDelete,
|
|
127
|
+
handler: props => props.onDelete(props.sequenceData)
|
|
125
128
|
},
|
|
126
129
|
|
|
127
130
|
duplicateSequence: {
|
|
128
|
-
isDisabled:
|
|
129
|
-
isHidden:
|
|
131
|
+
isDisabled: props => !props.onDuplicate,
|
|
132
|
+
isHidden: props => !props.onDuplicate,
|
|
130
133
|
handler: (props, ...rest) =>
|
|
131
134
|
props.onDuplicate(props.sequenceData, props, ...rest),
|
|
132
135
|
hotkey: "alt+shift+d"
|
|
@@ -134,28 +137,28 @@ const fileCommandDefs = {
|
|
|
134
137
|
|
|
135
138
|
toggleReadOnlyMode: {
|
|
136
139
|
toggle: [],
|
|
137
|
-
isDisabled:
|
|
138
|
-
isHidden:
|
|
139
|
-
isActive:
|
|
140
|
-
handler:
|
|
140
|
+
isDisabled: props => props.disableSetReadOnly || !props.onSave,
|
|
141
|
+
isHidden: props => !props.toggleReadOnlyMode,
|
|
142
|
+
isActive: props => props.readOnly,
|
|
143
|
+
handler: props => handleReadOnlyChange(!props.readOnly, props)
|
|
141
144
|
},
|
|
142
145
|
|
|
143
146
|
importSequence: {
|
|
144
|
-
isHidden:
|
|
145
|
-
isDisabled:
|
|
146
|
-
handler:
|
|
147
|
+
isHidden: props => props.hideSingleImport,
|
|
148
|
+
isDisabled: props => props.readOnly,
|
|
149
|
+
handler: props => {
|
|
147
150
|
showFileDialog({
|
|
148
151
|
multiple: false,
|
|
149
|
-
onSelect:
|
|
152
|
+
onSelect: files => {
|
|
150
153
|
props.importSequenceFromFile(files[0]);
|
|
151
154
|
}
|
|
152
155
|
});
|
|
153
156
|
}
|
|
154
157
|
},
|
|
155
158
|
filterPartsByTagCmd: {
|
|
156
|
-
isHidden:
|
|
159
|
+
isHidden: props => !props.allPartTags,
|
|
157
160
|
name: "Search Parts By Tag",
|
|
158
|
-
component:
|
|
161
|
+
component: props => () => {
|
|
159
162
|
return (
|
|
160
163
|
// eslint-disable-next-line jsx-a11y/anchor-is-valid
|
|
161
164
|
<div
|
|
@@ -176,7 +179,7 @@ const fileCommandDefs = {
|
|
|
176
179
|
filterPartLengthsCmd: getFilterByLengthCmd("part"),
|
|
177
180
|
filterPrimerLengthsCmd: getFilterByLengthCmd("primer"),
|
|
178
181
|
featureTypesCmd: {
|
|
179
|
-
name:
|
|
182
|
+
name: props => {
|
|
180
183
|
const total = Object.keys(
|
|
181
184
|
reduce(
|
|
182
185
|
props.sequenceData.features,
|
|
@@ -199,9 +202,9 @@ const fileCommandDefs = {
|
|
|
199
202
|
</span>
|
|
200
203
|
);
|
|
201
204
|
},
|
|
202
|
-
submenu:
|
|
205
|
+
submenu: props => {
|
|
203
206
|
const types = {};
|
|
204
|
-
forEach(props.sequenceData.features,
|
|
207
|
+
forEach(props.sequenceData.features, feat => {
|
|
205
208
|
if (!feat.type) return;
|
|
206
209
|
const checked =
|
|
207
210
|
!props.annotationVisibility.featureTypesToHide[feat.type];
|
|
@@ -256,31 +259,31 @@ const fileCommandDefs = {
|
|
|
256
259
|
partFilterIndividualCmd: getFilterIndividualCmd("part"),
|
|
257
260
|
primerFilterIndividualCmd: getFilterIndividualCmd("primer"),
|
|
258
261
|
exportSequenceAsGenbank: {
|
|
259
|
-
name:
|
|
262
|
+
name: props =>
|
|
260
263
|
isProtein(props) ? "Download GenPept File" : "Download Genbank File",
|
|
261
|
-
handler:
|
|
264
|
+
handler: props =>
|
|
262
265
|
props.exportSequenceToFile(isProtein(props) ? "genpept" : "genbank")
|
|
263
266
|
},
|
|
264
267
|
exportSequenceAsFasta: {
|
|
265
268
|
name: "Download FASTA File",
|
|
266
|
-
handler:
|
|
269
|
+
handler: props => props.exportSequenceToFile("fasta")
|
|
267
270
|
},
|
|
268
271
|
exportSequenceAsTeselagenJson: {
|
|
269
272
|
name: "Download Teselagen JSON File",
|
|
270
|
-
handler:
|
|
273
|
+
handler: props => props.exportSequenceToFile("teselagenJson")
|
|
271
274
|
},
|
|
272
275
|
|
|
273
276
|
viewProperties: {
|
|
274
|
-
handler:
|
|
277
|
+
handler: props => props.propertiesViewOpen()
|
|
275
278
|
},
|
|
276
279
|
viewRevisionHistory: {
|
|
277
|
-
handler:
|
|
278
|
-
isHidden:
|
|
280
|
+
handler: props => props.toggleViewVersionHistory(),
|
|
281
|
+
isHidden: props => !props.getVersionList || !props.getSequenceAtVersion
|
|
279
282
|
},
|
|
280
283
|
|
|
281
284
|
print: {
|
|
282
285
|
hotkeyProps: { preventDefault: true },
|
|
283
|
-
handler:
|
|
286
|
+
handler: props =>
|
|
284
287
|
showDialog({
|
|
285
288
|
dialogType: "PrintDialog",
|
|
286
289
|
props
|
|
@@ -291,8 +294,8 @@ const fileCommandDefs = {
|
|
|
291
294
|
//showRemoveDuplicatesDialogFeatures showRemoveDuplicatesDialogParts showRemoveDuplicatesDialogPrimers
|
|
292
295
|
acc[`showRemoveDuplicatesDialog${type}`] = {
|
|
293
296
|
name: `Remove Duplicate ${startCase(type)}`,
|
|
294
|
-
isDisabled:
|
|
295
|
-
handler:
|
|
297
|
+
isDisabled: props => props.readOnly,
|
|
298
|
+
handler: props =>
|
|
296
299
|
showDialog({
|
|
297
300
|
dialogType: "RemoveDuplicates",
|
|
298
301
|
props: {
|
|
@@ -307,21 +310,21 @@ const fileCommandDefs = {
|
|
|
307
310
|
return acc;
|
|
308
311
|
}, {}),
|
|
309
312
|
autoAnnotateHolder: {
|
|
310
|
-
isHidden:
|
|
311
|
-
!some(partsPrimersFeatures,
|
|
313
|
+
isHidden: props =>
|
|
314
|
+
!some(partsPrimersFeatures, type => props[`autoAnnotate${type}`])
|
|
312
315
|
},
|
|
313
316
|
onConfigureFeatureTypesClick: {
|
|
314
317
|
name: "Configure Feature Types",
|
|
315
|
-
handler:
|
|
316
|
-
isHidden:
|
|
318
|
+
handler: p => p.onConfigureFeatureTypesClick(),
|
|
319
|
+
isHidden: props => !props.onConfigureFeatureTypesClick
|
|
317
320
|
},
|
|
318
321
|
...partsPrimersFeatures.reduce((acc, type) => {
|
|
319
322
|
const handlerName = `autoAnnotate${type}`;
|
|
320
323
|
acc[handlerName] = {
|
|
321
324
|
name: `Auto Annotate ${type}`,
|
|
322
|
-
isDisabled:
|
|
323
|
-
isHidden:
|
|
324
|
-
handler: async
|
|
325
|
+
isDisabled: props => props.readOnly,
|
|
326
|
+
isHidden: props => !props[handlerName],
|
|
327
|
+
handler: async props => {
|
|
325
328
|
if (props[handlerName]) {
|
|
326
329
|
const lowerType = type.toLowerCase();
|
|
327
330
|
const toAdd = await props[handlerName](props);
|
|
@@ -339,22 +342,23 @@ const fileCommandDefs = {
|
|
|
339
342
|
};
|
|
340
343
|
//copy options
|
|
341
344
|
const toggleCopyOptionCommandDefs = {};
|
|
342
|
-
Object.keys(defaultCopyOptions).forEach(
|
|
345
|
+
Object.keys(defaultCopyOptions).forEach(type => {
|
|
343
346
|
const cmdId = `toggleCopy${upperFirst(type)}`;
|
|
344
347
|
toggleCopyOptionCommandDefs[cmdId] = {
|
|
345
348
|
name: `Include ${startCase(type)}`,
|
|
346
|
-
handler:
|
|
347
|
-
isActive:
|
|
349
|
+
handler: props => props.toggleCopyOption(type),
|
|
350
|
+
isActive: props => props.copyOptions && props.copyOptions[type]
|
|
348
351
|
};
|
|
349
352
|
});
|
|
350
353
|
|
|
351
354
|
const readOnlyDisabledTooltip =
|
|
352
355
|
"Sorry this function is not allowed in Read-Only Mode";
|
|
356
|
+
const bpEditingDisabledTooltip = "Sequence Editing Disabled";
|
|
353
357
|
const noSelection = ({ selectionLayer = {} }) =>
|
|
354
358
|
!(selectionLayer.start > -1 && selectionLayer.end > -1) &&
|
|
355
359
|
"Selection Required";
|
|
356
360
|
|
|
357
|
-
const triggerClipboardCommand =
|
|
361
|
+
const triggerClipboardCommand = type => {
|
|
358
362
|
const wrapper = document.querySelector(".veVectorInteractionWrapper");
|
|
359
363
|
if (!wrapper) {
|
|
360
364
|
return window.toastr.info(`Cannot trigger a ${type} in the current view`);
|
|
@@ -382,13 +386,15 @@ const editCommandDefs = {
|
|
|
382
386
|
handler: noop
|
|
383
387
|
},
|
|
384
388
|
changeCircularityCmd: {
|
|
385
|
-
isHidden:
|
|
389
|
+
isHidden: p => p.readOnly || isProtein(p) || isOligo(p) || isRna(p),
|
|
386
390
|
handler: noop
|
|
387
391
|
},
|
|
388
392
|
cut: {
|
|
389
|
-
isDisabled:
|
|
390
|
-
(props.
|
|
391
|
-
|
|
393
|
+
isDisabled: props =>
|
|
394
|
+
(props.disableBpEditing && bpEditingDisabledTooltip) ||
|
|
395
|
+
(props.readOnly && readOnlyDisabledTooltip) ||
|
|
396
|
+
props.sequenceLength === 0,
|
|
397
|
+
isHidden: props => props.readOnly || props.disableBpEditing,
|
|
392
398
|
handler: () => {
|
|
393
399
|
triggerClipboardCommand("cut");
|
|
394
400
|
},
|
|
@@ -396,10 +402,10 @@ const editCommandDefs = {
|
|
|
396
402
|
},
|
|
397
403
|
createNewFromSubsequence: {
|
|
398
404
|
name: "New Sequence From Selected Range",
|
|
399
|
-
isDisabled:
|
|
405
|
+
isDisabled: props =>
|
|
400
406
|
props.sequenceLength === 0 || props.selectionLayer.start === -1,
|
|
401
|
-
isHidden:
|
|
402
|
-
handler:
|
|
407
|
+
isHidden: props => !props.onCreateNewFromSubsequence,
|
|
408
|
+
handler: props => {
|
|
403
409
|
props.onCreateNewFromSubsequence(
|
|
404
410
|
getSequenceDataBetweenRange(props.sequenceData, props.selectionLayer),
|
|
405
411
|
props
|
|
@@ -409,51 +415,51 @@ const editCommandDefs = {
|
|
|
409
415
|
},
|
|
410
416
|
|
|
411
417
|
copy: {
|
|
412
|
-
isDisabled:
|
|
418
|
+
isDisabled: props => props.sequenceLength === 0,
|
|
413
419
|
|
|
414
420
|
handler: () => triggerClipboardCommand("copy"),
|
|
415
421
|
hotkey: "mod+c"
|
|
416
422
|
},
|
|
417
423
|
|
|
418
424
|
paste: {
|
|
419
|
-
isDisabled:
|
|
420
|
-
isHidden:
|
|
425
|
+
isDisabled: props => props.readOnly && readOnlyDisabledTooltip,
|
|
426
|
+
isHidden: props => props.readOnly || props.disableBpEditing,
|
|
421
427
|
|
|
422
428
|
handler: () => triggerClipboardCommand("paste"),
|
|
423
429
|
hotkey: "mod+v"
|
|
424
430
|
},
|
|
425
431
|
|
|
426
432
|
undo: {
|
|
427
|
-
isHidden:
|
|
433
|
+
isHidden: props => props.readOnly,
|
|
428
434
|
|
|
429
|
-
isDisabled:
|
|
435
|
+
isDisabled: props =>
|
|
430
436
|
props.readOnly ||
|
|
431
437
|
!(
|
|
432
438
|
props.sequenceDataHistory &&
|
|
433
439
|
props.sequenceDataHistory.past &&
|
|
434
440
|
props.sequenceDataHistory.past.length
|
|
435
441
|
),
|
|
436
|
-
handler:
|
|
442
|
+
handler: props => props.undo(),
|
|
437
443
|
hotkey: "mod+z"
|
|
438
444
|
},
|
|
439
445
|
|
|
440
446
|
redo: {
|
|
441
|
-
isHidden:
|
|
447
|
+
isHidden: props => props.readOnly,
|
|
442
448
|
|
|
443
|
-
isDisabled:
|
|
449
|
+
isDisabled: props =>
|
|
444
450
|
props.readOnly ||
|
|
445
451
|
!(
|
|
446
452
|
props.sequenceDataHistory &&
|
|
447
453
|
props.sequenceDataHistory.future &&
|
|
448
454
|
props.sequenceDataHistory.future.length
|
|
449
455
|
),
|
|
450
|
-
handler:
|
|
456
|
+
handler: props => props.redo(),
|
|
451
457
|
hotkey: "mod+shift+z"
|
|
452
458
|
},
|
|
453
459
|
find: {
|
|
454
|
-
isDisabled:
|
|
460
|
+
isDisabled: props => props.sequenceLength === 0,
|
|
455
461
|
name: "Find...",
|
|
456
|
-
handler:
|
|
462
|
+
handler: props => {
|
|
457
463
|
if (props.findTool.isOpen) {
|
|
458
464
|
const inputEl =
|
|
459
465
|
document.querySelector("textarea.tg-find-tool-input") ||
|
|
@@ -469,7 +475,7 @@ const editCommandDefs = {
|
|
|
469
475
|
hotkeyProps: { preventDefault: true }
|
|
470
476
|
},
|
|
471
477
|
about: {
|
|
472
|
-
isDisabled:
|
|
478
|
+
isDisabled: props => props.sequenceLength === 0,
|
|
473
479
|
name: "About",
|
|
474
480
|
handler: () =>
|
|
475
481
|
showConfirmationDialog({
|
|
@@ -502,9 +508,9 @@ const editCommandDefs = {
|
|
|
502
508
|
},
|
|
503
509
|
|
|
504
510
|
goTo: {
|
|
505
|
-
isDisabled:
|
|
511
|
+
isDisabled: props => props.sequenceLength === 0,
|
|
506
512
|
name: "Go To...",
|
|
507
|
-
handler:
|
|
513
|
+
handler: props => {
|
|
508
514
|
showDialog({
|
|
509
515
|
dialogType: "GoToDialog",
|
|
510
516
|
props: {
|
|
@@ -520,7 +526,7 @@ const editCommandDefs = {
|
|
|
520
526
|
isProtein(props)
|
|
521
527
|
)
|
|
522
528
|
},
|
|
523
|
-
onSubmit:
|
|
529
|
+
onSubmit: values =>
|
|
524
530
|
props.caretPositionUpdate(
|
|
525
531
|
values.sequencePosition * (isProtein(props) ? 3 : 1)
|
|
526
532
|
)
|
|
@@ -532,9 +538,9 @@ const editCommandDefs = {
|
|
|
532
538
|
},
|
|
533
539
|
|
|
534
540
|
select: {
|
|
535
|
-
isDisabled:
|
|
541
|
+
isDisabled: props => props.sequenceLength === 0,
|
|
536
542
|
name: "Select...",
|
|
537
|
-
handler:
|
|
543
|
+
handler: props => {
|
|
538
544
|
let { start, end } = props.selectionLayer;
|
|
539
545
|
if (!(start > -1)) {
|
|
540
546
|
start = props.caretPosition;
|
|
@@ -569,7 +575,7 @@ const editCommandDefs = {
|
|
|
569
575
|
props.sequenceLength || 1,
|
|
570
576
|
isProtein(props)
|
|
571
577
|
),
|
|
572
|
-
onSubmit:
|
|
578
|
+
onSubmit: values => {
|
|
573
579
|
const newRange = convertRangeTo0Based({
|
|
574
580
|
start: isProtein(props) ? values.from * 3 : values.from,
|
|
575
581
|
end: isProtein(props) ? values.to * 3 : values.to
|
|
@@ -593,46 +599,48 @@ const editCommandDefs = {
|
|
|
593
599
|
}
|
|
594
600
|
props.selectAll();
|
|
595
601
|
},
|
|
596
|
-
isDisabled:
|
|
602
|
+
isDisabled: props => props.sequenceLength === 0,
|
|
597
603
|
hotkey: "mod+a"
|
|
598
604
|
//tnr: we can't pass the following because it will block inputs
|
|
599
605
|
// hotkeyProps: { preventDefault: true, stopPropagation: true }
|
|
600
606
|
},
|
|
601
607
|
|
|
602
608
|
selectInverse: {
|
|
603
|
-
isDisabled:
|
|
604
|
-
handler:
|
|
609
|
+
isDisabled: props => noSelection(props),
|
|
610
|
+
handler: props => props.handleInverse(),
|
|
605
611
|
hotkey: "mod+i"
|
|
606
612
|
},
|
|
607
613
|
|
|
608
614
|
complementSelection: {
|
|
609
|
-
isHidden:
|
|
615
|
+
isHidden: props =>
|
|
616
|
+
props.readOnly || isProtein(props) || props.disableBpEditing,
|
|
610
617
|
|
|
611
|
-
isDisabled:
|
|
618
|
+
isDisabled: props =>
|
|
612
619
|
(props.readOnly && readOnlyDisabledTooltip) || noSelection(props),
|
|
613
|
-
handler:
|
|
620
|
+
handler: props => props.handleComplementSelection()
|
|
614
621
|
},
|
|
615
622
|
|
|
616
623
|
complementEntireSequence: {
|
|
617
|
-
isHidden:
|
|
624
|
+
isHidden: props =>
|
|
625
|
+
props.readOnly || isProtein(props) || props.disableBpEditing,
|
|
618
626
|
|
|
619
|
-
isDisabled:
|
|
627
|
+
isDisabled: props =>
|
|
620
628
|
(props.readOnly && readOnlyDisabledTooltip) || props.sequenceLength === 0,
|
|
621
629
|
|
|
622
|
-
handler:
|
|
630
|
+
handler: props => props.handleComplementSequence()
|
|
623
631
|
},
|
|
624
632
|
sequenceCase: {
|
|
625
633
|
isHidden: isProtein
|
|
626
634
|
},
|
|
627
635
|
toggleCircular: {
|
|
628
636
|
name: "Circular",
|
|
629
|
-
isActive:
|
|
630
|
-
handler:
|
|
637
|
+
isActive: props => props.sequenceData.circular,
|
|
638
|
+
handler: props => props.updateCircular(true)
|
|
631
639
|
},
|
|
632
640
|
toggleLinear: {
|
|
633
641
|
name: "Linear",
|
|
634
|
-
isActive:
|
|
635
|
-
handler:
|
|
642
|
+
isActive: props => !props.sequenceData.circular,
|
|
643
|
+
handler: props => props.updateCircular(false)
|
|
636
644
|
},
|
|
637
645
|
...[
|
|
638
646
|
{ hotkey: "option + =", type: "flipCaseSequence" },
|
|
@@ -645,7 +653,7 @@ const editCommandDefs = {
|
|
|
645
653
|
|
|
646
654
|
acc[type] = {
|
|
647
655
|
isHidden: isProtein,
|
|
648
|
-
isDisabled:
|
|
656
|
+
isDisabled: props => {
|
|
649
657
|
if (props.readOnly) {
|
|
650
658
|
return "The sequence is read only. Try changing 'View > Sequence > Case'";
|
|
651
659
|
}
|
|
@@ -655,7 +663,7 @@ const editCommandDefs = {
|
|
|
655
663
|
},
|
|
656
664
|
name: startCase(type),
|
|
657
665
|
hotkey,
|
|
658
|
-
handler:
|
|
666
|
+
handler: props => {
|
|
659
667
|
const { sequence } = props.sequenceData;
|
|
660
668
|
const { selectionLayer } = props;
|
|
661
669
|
let toastFired;
|
|
@@ -701,31 +709,31 @@ const editCommandDefs = {
|
|
|
701
709
|
}, {}),
|
|
702
710
|
|
|
703
711
|
toggleShowGCContent: {
|
|
704
|
-
isActive:
|
|
705
|
-
handler:
|
|
712
|
+
isActive: props => props.showGCContent,
|
|
713
|
+
handler: props => {
|
|
706
714
|
props.toggleShowGCContent(!props.showGCContent);
|
|
707
715
|
}
|
|
708
716
|
},
|
|
709
717
|
|
|
710
718
|
toggleSequenceMapFontUpper: {
|
|
711
|
-
isActive:
|
|
712
|
-
handler:
|
|
719
|
+
isActive: props => props.uppercaseSequenceMapFont === "uppercase",
|
|
720
|
+
handler: props => {
|
|
713
721
|
props.updateSequenceCase("uppercase");
|
|
714
722
|
window.toastr.success(`Sequence Case View Changed`);
|
|
715
723
|
},
|
|
716
724
|
hotkey: "ctrl+option+plus"
|
|
717
725
|
},
|
|
718
726
|
toggleSequenceMapFontRaw: {
|
|
719
|
-
isActive:
|
|
720
|
-
handler:
|
|
727
|
+
isActive: props => props.uppercaseSequenceMapFont === "noPreference",
|
|
728
|
+
handler: props => {
|
|
721
729
|
props.updateSequenceCase("noPreference");
|
|
722
730
|
window.toastr.success(`Sequence Case View Changed`);
|
|
723
731
|
},
|
|
724
732
|
hotkey: "ctrl+option+="
|
|
725
733
|
},
|
|
726
734
|
toggleSequenceMapFontLower: {
|
|
727
|
-
isActive:
|
|
728
|
-
handler:
|
|
735
|
+
isActive: props => props.uppercaseSequenceMapFont === "lowercase",
|
|
736
|
+
handler: props => {
|
|
729
737
|
props.updateSequenceCase("lowercase");
|
|
730
738
|
window.toastr.success(`Sequence Case View Changed`);
|
|
731
739
|
},
|
|
@@ -733,14 +741,14 @@ const editCommandDefs = {
|
|
|
733
741
|
},
|
|
734
742
|
setRowViewSequenceSpacing: {
|
|
735
743
|
handler: noop,
|
|
736
|
-
name:
|
|
744
|
+
name: props => {
|
|
737
745
|
return (
|
|
738
746
|
<div data-test="setRowViewSequenceSpacing">
|
|
739
747
|
Spacing (in Sequence Map)
|
|
740
748
|
<div style={{ paddingLeft: 11, paddingRight: 11, paddingTop: 3 }}>
|
|
741
749
|
<Slider
|
|
742
750
|
stepSize={1}
|
|
743
|
-
onChange={
|
|
751
|
+
onChange={v => {
|
|
744
752
|
props.updateSequenceSpacing(v);
|
|
745
753
|
}}
|
|
746
754
|
value={Number(props.charWidth)}
|
|
@@ -755,9 +763,9 @@ const editCommandDefs = {
|
|
|
755
763
|
},
|
|
756
764
|
createMenuHolder: {
|
|
757
765
|
name: "Create",
|
|
758
|
-
isHidden:
|
|
766
|
+
isHidden: props => isProtein(props) && props.readOnly,
|
|
759
767
|
handler: noop,
|
|
760
|
-
submenu:
|
|
768
|
+
submenu: props => {
|
|
761
769
|
return [
|
|
762
770
|
"newFeature",
|
|
763
771
|
"newPart",
|
|
@@ -780,31 +788,34 @@ const editCommandDefs = {
|
|
|
780
788
|
// }
|
|
781
789
|
// },
|
|
782
790
|
reverseComplementSelection: {
|
|
783
|
-
isDisabled:
|
|
784
|
-
(props.readOnly && readOnlyDisabledTooltip) ||
|
|
785
|
-
|
|
791
|
+
isDisabled: props =>
|
|
792
|
+
(props.readOnly && readOnlyDisabledTooltip) ||
|
|
793
|
+
noSelection(props) ||
|
|
794
|
+
props.disableBpEditing,
|
|
795
|
+
isHidden: props => props.readOnly || isProtein(props),
|
|
786
796
|
|
|
787
|
-
handler:
|
|
797
|
+
handler: props => props.handleReverseComplementSelection(),
|
|
788
798
|
hotkey: "mod+e"
|
|
789
799
|
},
|
|
790
800
|
|
|
791
801
|
reverseComplementEntireSequence: {
|
|
792
|
-
isHidden:
|
|
802
|
+
isHidden: props =>
|
|
803
|
+
props.readOnly || isProtein(props) || props.disableBpEditing,
|
|
793
804
|
|
|
794
|
-
isDisabled:
|
|
805
|
+
isDisabled: props =>
|
|
795
806
|
(props.readOnly && readOnlyDisabledTooltip) || props.sequenceLength === 0,
|
|
796
|
-
handler:
|
|
807
|
+
handler: props => props.handleReverseComplementSequence()
|
|
797
808
|
},
|
|
798
809
|
fullSequenceTranslations: {
|
|
799
810
|
isHidden: isProtein,
|
|
800
811
|
handler: noop
|
|
801
812
|
},
|
|
802
813
|
sequenceAA_allFrames: {
|
|
803
|
-
isActive:
|
|
814
|
+
isActive: props =>
|
|
804
815
|
props.frameTranslations["1"] &&
|
|
805
816
|
props.frameTranslations["2"] &&
|
|
806
817
|
props.frameTranslations["3"],
|
|
807
|
-
handler:
|
|
818
|
+
handler: props => {
|
|
808
819
|
if (
|
|
809
820
|
props.frameTranslations["1"] &&
|
|
810
821
|
props.frameTranslations["2"] &&
|
|
@@ -824,11 +835,11 @@ const editCommandDefs = {
|
|
|
824
835
|
sequenceAAReverse_allFrames: {
|
|
825
836
|
isHidden: isProtein,
|
|
826
837
|
|
|
827
|
-
isActive:
|
|
838
|
+
isActive: props =>
|
|
828
839
|
props.frameTranslations["-1"] &&
|
|
829
840
|
props.frameTranslations["-2"] &&
|
|
830
841
|
props.frameTranslations["-3"],
|
|
831
|
-
handler:
|
|
842
|
+
handler: props => {
|
|
832
843
|
if (
|
|
833
844
|
props.frameTranslations["-1"] &&
|
|
834
845
|
props.frameTranslations["-2"] &&
|
|
@@ -846,8 +857,8 @@ const editCommandDefs = {
|
|
|
846
857
|
}
|
|
847
858
|
},
|
|
848
859
|
sequenceAA_frame1: {
|
|
849
|
-
isActive:
|
|
850
|
-
handler:
|
|
860
|
+
isActive: props => props.frameTranslations["1"],
|
|
861
|
+
handler: props => {
|
|
851
862
|
if (!props.frameTranslations["1"]) {
|
|
852
863
|
props.annotationVisibilityShow("translations");
|
|
853
864
|
}
|
|
@@ -855,8 +866,8 @@ const editCommandDefs = {
|
|
|
855
866
|
}
|
|
856
867
|
},
|
|
857
868
|
sequenceAA_frame2: {
|
|
858
|
-
isActive:
|
|
859
|
-
handler:
|
|
869
|
+
isActive: props => props.frameTranslations["2"],
|
|
870
|
+
handler: props => {
|
|
860
871
|
if (!props.frameTranslations["2"]) {
|
|
861
872
|
props.annotationVisibilityShow("translations");
|
|
862
873
|
}
|
|
@@ -864,8 +875,8 @@ const editCommandDefs = {
|
|
|
864
875
|
}
|
|
865
876
|
},
|
|
866
877
|
sequenceAA_frame3: {
|
|
867
|
-
isActive:
|
|
868
|
-
handler:
|
|
878
|
+
isActive: props => props.frameTranslations["3"],
|
|
879
|
+
handler: props => {
|
|
869
880
|
if (!props.frameTranslations["3"]) {
|
|
870
881
|
props.annotationVisibilityShow("translations");
|
|
871
882
|
}
|
|
@@ -873,8 +884,8 @@ const editCommandDefs = {
|
|
|
873
884
|
}
|
|
874
885
|
},
|
|
875
886
|
sequenceAAReverse_frame1: {
|
|
876
|
-
isActive:
|
|
877
|
-
handler:
|
|
887
|
+
isActive: props => props.frameTranslations["-1"],
|
|
888
|
+
handler: props => {
|
|
878
889
|
if (!props.frameTranslations["-1"]) {
|
|
879
890
|
props.annotationVisibilityShow("translations");
|
|
880
891
|
}
|
|
@@ -882,8 +893,8 @@ const editCommandDefs = {
|
|
|
882
893
|
}
|
|
883
894
|
},
|
|
884
895
|
sequenceAAReverse_frame2: {
|
|
885
|
-
isActive:
|
|
886
|
-
handler:
|
|
896
|
+
isActive: props => props.frameTranslations["-2"],
|
|
897
|
+
handler: props => {
|
|
887
898
|
if (!props.frameTranslations["-2"]) {
|
|
888
899
|
props.annotationVisibilityShow("translations");
|
|
889
900
|
}
|
|
@@ -892,8 +903,8 @@ const editCommandDefs = {
|
|
|
892
903
|
},
|
|
893
904
|
|
|
894
905
|
sequenceAAReverse_frame3: {
|
|
895
|
-
isActive:
|
|
896
|
-
handler:
|
|
906
|
+
isActive: props => props.frameTranslations["-3"],
|
|
907
|
+
handler: props => {
|
|
897
908
|
if (!props.frameTranslations["-3"]) {
|
|
898
909
|
props.annotationVisibilityShow("translations");
|
|
899
910
|
}
|
|
@@ -907,11 +918,11 @@ const editCommandDefs = {
|
|
|
907
918
|
handler: (props /* state, ctxInfo */) => {
|
|
908
919
|
props.handleNewFeature();
|
|
909
920
|
},
|
|
910
|
-
isHidden:
|
|
921
|
+
isHidden: props =>
|
|
911
922
|
props.readOnly ||
|
|
912
923
|
!props.annotationsToSupport ||
|
|
913
924
|
!props.annotationsToSupport.features,
|
|
914
|
-
isDisabled:
|
|
925
|
+
isDisabled: props =>
|
|
915
926
|
(props.readOnly && readOnlyDisabledTooltip) || props.sequenceLength === 0,
|
|
916
927
|
hotkey: "mod+k",
|
|
917
928
|
hotkeyProps: { preventDefault: true }
|
|
@@ -920,11 +931,11 @@ const editCommandDefs = {
|
|
|
920
931
|
isHidden: isProtein,
|
|
921
932
|
|
|
922
933
|
name: "Use GTG And CTG As Start Codons",
|
|
923
|
-
isActive:
|
|
924
|
-
handler:
|
|
934
|
+
isActive: props => props.useAdditionalOrfStartCodons,
|
|
935
|
+
handler: props => props.useAdditionalOrfStartCodonsToggle()
|
|
925
936
|
},
|
|
926
937
|
minOrfSizeCmd: {
|
|
927
|
-
name:
|
|
938
|
+
name: props => {
|
|
928
939
|
return (
|
|
929
940
|
<div data-test="min-orf-size" style={{ display: "flex" }}>
|
|
930
941
|
Minimum ORF Size:
|
|
@@ -949,39 +960,40 @@ const editCommandDefs = {
|
|
|
949
960
|
},
|
|
950
961
|
hotkeyDialog: {
|
|
951
962
|
name: "View Editor Hotkeys",
|
|
952
|
-
handler:
|
|
963
|
+
handler: props => props.openHotkeyDialog()
|
|
953
964
|
},
|
|
954
965
|
|
|
955
966
|
newPart: {
|
|
956
|
-
handler:
|
|
957
|
-
isHidden:
|
|
967
|
+
handler: props => props.handleNewPart(),
|
|
968
|
+
isHidden: props =>
|
|
958
969
|
props.readOnly ||
|
|
959
970
|
!props.annotationsToSupport ||
|
|
960
971
|
!props.annotationsToSupport.parts,
|
|
961
972
|
|
|
962
|
-
isDisabled:
|
|
973
|
+
isDisabled: props =>
|
|
963
974
|
(props.readOnly && readOnlyDisabledTooltip) || props.sequenceLength === 0,
|
|
964
975
|
hotkey: "mod+l",
|
|
965
976
|
hotkeyProps: { preventDefault: true }
|
|
966
977
|
},
|
|
967
978
|
newPrimer: {
|
|
968
|
-
handler:
|
|
969
|
-
isHidden:
|
|
979
|
+
handler: props => props.handleNewPrimer(),
|
|
980
|
+
isHidden: props =>
|
|
970
981
|
props.readOnly ||
|
|
971
982
|
!props.annotationsToSupport ||
|
|
972
983
|
!props.annotationsToSupport.primers,
|
|
973
|
-
isDisabled:
|
|
984
|
+
isDisabled: props =>
|
|
974
985
|
(props.readOnly && readOnlyDisabledTooltip) || props.sequenceLength === 0
|
|
975
986
|
},
|
|
976
987
|
|
|
977
988
|
rotateToCaretPosition: {
|
|
978
|
-
isHidden:
|
|
979
|
-
|
|
989
|
+
isHidden: props =>
|
|
990
|
+
props.readOnly || isProtein(props) || props.disableBpEditing,
|
|
991
|
+
isDisabled: props =>
|
|
980
992
|
(props.readOnly && readOnlyDisabledTooltip) ||
|
|
981
993
|
(props.caretPosition === -1 && "You must first place cursor") ||
|
|
982
994
|
(!props.sequenceData.circular && "Disabled for Linear Sequences") ||
|
|
983
995
|
props.sequenceLength === 0,
|
|
984
|
-
handler:
|
|
996
|
+
handler: props => props.handleRotateToCaretPosition(),
|
|
985
997
|
hotkey: "mod+b"
|
|
986
998
|
},
|
|
987
999
|
...toggleCopyOptionCommandDefs
|
|
@@ -989,72 +1001,67 @@ const editCommandDefs = {
|
|
|
989
1001
|
|
|
990
1002
|
const cirularityCommandDefs = {
|
|
991
1003
|
circular: {
|
|
992
|
-
isHidden:
|
|
993
|
-
|
|
994
|
-
isDisabled:
|
|
995
|
-
handler:
|
|
996
|
-
isActive:
|
|
1004
|
+
isHidden: props =>
|
|
1005
|
+
props.readOnly || isProtein(props) || props.disableBpEditing,
|
|
1006
|
+
isDisabled: props => props.readOnly && readOnlyDisabledTooltip,
|
|
1007
|
+
handler: props => props.updateCircular(true),
|
|
1008
|
+
isActive: props => props && props.sequenceData.circular
|
|
997
1009
|
},
|
|
998
1010
|
linear: {
|
|
999
|
-
isHidden:
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
isActive: (props) => props && !props.sequenceData.circular
|
|
1011
|
+
isHidden: props => props.readOnly || props.disableBpEditing,
|
|
1012
|
+
isDisabled: props => props.readOnly && readOnlyDisabledTooltip,
|
|
1013
|
+
handler: props => props.updateCircular(false),
|
|
1014
|
+
isActive: props => props && !props.sequenceData.circular
|
|
1004
1015
|
}
|
|
1005
1016
|
};
|
|
1006
1017
|
|
|
1007
1018
|
const nicheAnnotations = [
|
|
1008
1019
|
{
|
|
1009
1020
|
type: "warnings",
|
|
1010
|
-
isHidden:
|
|
1021
|
+
isHidden: p => {
|
|
1011
1022
|
return !map(p.sequenceData["warnings"]).length;
|
|
1012
1023
|
}
|
|
1013
1024
|
},
|
|
1014
1025
|
{
|
|
1015
1026
|
type: "assemblyPieces",
|
|
1016
|
-
isHidden:
|
|
1027
|
+
isHidden: p => {
|
|
1017
1028
|
return !map(p.sequenceData["assemblyPieces"]).length;
|
|
1018
1029
|
}
|
|
1019
1030
|
},
|
|
1020
1031
|
{
|
|
1021
1032
|
type: "lineageAnnotations",
|
|
1022
|
-
isHidden:
|
|
1033
|
+
isHidden: p => {
|
|
1023
1034
|
return !map(p.sequenceData["lineageAnnotations"]).length;
|
|
1024
1035
|
}
|
|
1025
1036
|
}
|
|
1026
1037
|
];
|
|
1027
1038
|
const labelToggleCommandDefs = {};
|
|
1028
|
-
["feature", "part", "cutsite", "primer", ...nicheAnnotations].forEach(
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
rest = _type;
|
|
1035
|
-
}
|
|
1036
|
-
const cmdId = `toggle${upperFirst(type)}Labels`;
|
|
1037
|
-
const plural = type + "s";
|
|
1038
|
-
labelToggleCommandDefs[cmdId] = {
|
|
1039
|
-
toggle: ["show", "hide"],
|
|
1040
|
-
handler: (props) => props.annotationLabelVisibilityToggle(plural),
|
|
1041
|
-
isHidden: (props) => {
|
|
1042
|
-
return (
|
|
1043
|
-
props && props.typesToOmit && props.typesToOmit[plural] === false
|
|
1044
|
-
);
|
|
1045
|
-
},
|
|
1046
|
-
...rest,
|
|
1047
|
-
isActive: (props) => {
|
|
1048
|
-
return props && props.annotationLabelVisibility[plural];
|
|
1049
|
-
}
|
|
1050
|
-
};
|
|
1039
|
+
["feature", "part", "cutsite", "primer", ...nicheAnnotations].forEach(_type => {
|
|
1040
|
+
let rest = {};
|
|
1041
|
+
let type = _type;
|
|
1042
|
+
if (_type.type) {
|
|
1043
|
+
type = _type.type.slice(0, -1);
|
|
1044
|
+
rest = _type;
|
|
1051
1045
|
}
|
|
1052
|
-
)
|
|
1046
|
+
const cmdId = `toggle${upperFirst(type)}Labels`;
|
|
1047
|
+
const plural = type + "s";
|
|
1048
|
+
labelToggleCommandDefs[cmdId] = {
|
|
1049
|
+
toggle: ["show", "hide"],
|
|
1050
|
+
handler: props => props.annotationLabelVisibilityToggle(plural),
|
|
1051
|
+
isHidden: props => {
|
|
1052
|
+
return props && props.typesToOmit && props.typesToOmit[plural] === false;
|
|
1053
|
+
},
|
|
1054
|
+
...rest,
|
|
1055
|
+
isActive: props => {
|
|
1056
|
+
return props && props.annotationLabelVisibility[plural];
|
|
1057
|
+
}
|
|
1058
|
+
};
|
|
1059
|
+
});
|
|
1053
1060
|
|
|
1054
1061
|
const editAnnotationCommandDefs = ["feature", "part", "primer"].reduce(
|
|
1055
1062
|
(acc, key) => {
|
|
1056
1063
|
acc[`edit${upperFirst(key)}`] = {
|
|
1057
|
-
name:
|
|
1064
|
+
name: props =>
|
|
1058
1065
|
props.readOnly
|
|
1059
1066
|
? `View ${upperFirst(key)} Details`
|
|
1060
1067
|
: `Edit ${upperFirst(key)}`,
|
|
@@ -1081,7 +1088,7 @@ const deleteAnnotationCommandDefs = [
|
|
|
1081
1088
|
const annotation = get(ctxInfo, "context.annotation");
|
|
1082
1089
|
props[`delete${upperFirst(key)}`](annotation);
|
|
1083
1090
|
},
|
|
1084
|
-
isHidden:
|
|
1091
|
+
isHidden: props => props.readOnly
|
|
1085
1092
|
};
|
|
1086
1093
|
return acc;
|
|
1087
1094
|
}, {});
|
|
@@ -1134,14 +1141,14 @@ const annotationToggleCommandDefs = {};
|
|
|
1134
1141
|
"axis",
|
|
1135
1142
|
{ type: "orfs", text: "ORFs", isHidden: isProtein },
|
|
1136
1143
|
{ type: "primers", isHidden: isProtein },
|
|
1137
|
-
{ type: "chromatogram", isHidden:
|
|
1144
|
+
{ type: "chromatogram", isHidden: p => !p.sequenceData.chromatogramData },
|
|
1138
1145
|
"translations",
|
|
1139
1146
|
|
|
1140
1147
|
{
|
|
1141
1148
|
type: "orfTranslations",
|
|
1142
1149
|
text: "ORF Translations",
|
|
1143
1150
|
isHidden: isProtein,
|
|
1144
|
-
isDisabled:
|
|
1151
|
+
isDisabled: props => {
|
|
1145
1152
|
return (
|
|
1146
1153
|
(!props.annotationVisibility.orfs &&
|
|
1147
1154
|
"ORFs must be visible to view their translations") ||
|
|
@@ -1154,7 +1161,7 @@ const annotationToggleCommandDefs = {};
|
|
|
1154
1161
|
type: "cdsFeatureTranslations",
|
|
1155
1162
|
text: "CDS Feature Translations",
|
|
1156
1163
|
isHidden: isProtein,
|
|
1157
|
-
isDisabled:
|
|
1164
|
+
isDisabled: props => {
|
|
1158
1165
|
return (
|
|
1159
1166
|
(!props.annotationVisibility.features &&
|
|
1160
1167
|
"Features must be visible to view their translations") ||
|
|
@@ -1174,11 +1181,11 @@ const annotationToggleCommandDefs = {};
|
|
|
1174
1181
|
type: "sequence",
|
|
1175
1182
|
name: "DNA Sequence",
|
|
1176
1183
|
noCount: true,
|
|
1177
|
-
isHidden:
|
|
1184
|
+
isHidden: props => !isProtein(props)
|
|
1178
1185
|
},
|
|
1179
1186
|
{
|
|
1180
1187
|
type: "reverseSequence",
|
|
1181
|
-
name:
|
|
1188
|
+
name: props =>
|
|
1182
1189
|
isProtein(props) ? "DNA Reverse Sequence" : "Reverse Sequence"
|
|
1183
1190
|
},
|
|
1184
1191
|
{
|
|
@@ -1188,12 +1195,12 @@ const annotationToggleCommandDefs = {};
|
|
|
1188
1195
|
{
|
|
1189
1196
|
type: "dnaColors",
|
|
1190
1197
|
name: () => "DNA Colors",
|
|
1191
|
-
isDisabled:
|
|
1198
|
+
isDisabled: props =>
|
|
1192
1199
|
!props.annotationVisibility.sequence &&
|
|
1193
1200
|
!props.annotationVisibility.reverseSequence &&
|
|
1194
1201
|
"The DNA sequence must be visible in order to color it"
|
|
1195
1202
|
}
|
|
1196
|
-
].forEach(
|
|
1203
|
+
].forEach(typeOrObj => {
|
|
1197
1204
|
let type = typeOrObj;
|
|
1198
1205
|
let obj = {};
|
|
1199
1206
|
if (typeOrObj.type) {
|
|
@@ -1203,7 +1210,7 @@ const annotationToggleCommandDefs = {};
|
|
|
1203
1210
|
const cmdId = `toggle${upperFirst(type)}`;
|
|
1204
1211
|
annotationToggleCommandDefs[cmdId] = {
|
|
1205
1212
|
toggle: ["show", "hide"],
|
|
1206
|
-
name:
|
|
1213
|
+
name: props => {
|
|
1207
1214
|
const sequenceData = props.sequenceData || {};
|
|
1208
1215
|
let count;
|
|
1209
1216
|
let hasCount = false;
|
|
@@ -1238,14 +1245,14 @@ const annotationToggleCommandDefs = {};
|
|
|
1238
1245
|
</span>
|
|
1239
1246
|
);
|
|
1240
1247
|
},
|
|
1241
|
-
handler:
|
|
1242
|
-
isActive:
|
|
1248
|
+
handler: props => props.annotationVisibilityToggle(type),
|
|
1249
|
+
isActive: props => {
|
|
1243
1250
|
return (
|
|
1244
1251
|
props && props.annotationVisibility && props.annotationVisibility[type]
|
|
1245
1252
|
);
|
|
1246
1253
|
},
|
|
1247
1254
|
...obj, //spread this here to override the above props if necessary
|
|
1248
|
-
isHidden:
|
|
1255
|
+
isHidden: props => {
|
|
1249
1256
|
return (
|
|
1250
1257
|
(props && props.typesToOmit && props.typesToOmit[type] === false) ||
|
|
1251
1258
|
(obj.isHidden && obj.isHidden(props))
|
|
@@ -1256,11 +1263,11 @@ const annotationToggleCommandDefs = {};
|
|
|
1256
1263
|
|
|
1257
1264
|
const additionalAnnotationCommandsDefs = {
|
|
1258
1265
|
limitsMenu: {
|
|
1259
|
-
isHidden:
|
|
1266
|
+
isHidden: props => props.maxAnnotationsToDisplay
|
|
1260
1267
|
},
|
|
1261
1268
|
showAll: {
|
|
1262
|
-
handler:
|
|
1263
|
-
annotationTypes.forEach(
|
|
1269
|
+
handler: props => {
|
|
1270
|
+
annotationTypes.forEach(type => {
|
|
1264
1271
|
if (props.isProtein) {
|
|
1265
1272
|
if (type === "translations" || type === "cutsites")
|
|
1266
1273
|
return props.annotationVisibilityHide(type);
|
|
@@ -1270,15 +1277,15 @@ const additionalAnnotationCommandsDefs = {
|
|
|
1270
1277
|
}
|
|
1271
1278
|
},
|
|
1272
1279
|
hideAll: {
|
|
1273
|
-
handler:
|
|
1274
|
-
annotationTypes.forEach(
|
|
1280
|
+
handler: props => {
|
|
1281
|
+
annotationTypes.forEach(type => {
|
|
1275
1282
|
props.annotationVisibilityHide(type);
|
|
1276
1283
|
});
|
|
1277
1284
|
}
|
|
1278
1285
|
},
|
|
1279
1286
|
showAllLabels: {
|
|
1280
|
-
handler:
|
|
1281
|
-
annotationTypes.forEach(
|
|
1287
|
+
handler: props => {
|
|
1288
|
+
annotationTypes.forEach(type => {
|
|
1282
1289
|
// if (props.isProtein) {
|
|
1283
1290
|
// if (type === "translations" || type === "cutsites")
|
|
1284
1291
|
// return props.annotationVisibilityHide(type);
|
|
@@ -1288,39 +1295,39 @@ const additionalAnnotationCommandsDefs = {
|
|
|
1288
1295
|
}
|
|
1289
1296
|
},
|
|
1290
1297
|
hideAllLabels: {
|
|
1291
|
-
handler:
|
|
1292
|
-
annotationTypes.forEach(
|
|
1298
|
+
handler: props => {
|
|
1299
|
+
annotationTypes.forEach(type => {
|
|
1293
1300
|
props.annotationLabelVisibilityHide(type);
|
|
1294
1301
|
});
|
|
1295
1302
|
}
|
|
1296
1303
|
},
|
|
1297
1304
|
toggleAminoAcidNumbers_dna: {
|
|
1298
1305
|
...annotationToggleCommandDefs.toggleAminoAcidNumbers,
|
|
1299
|
-
isHidden:
|
|
1306
|
+
isHidden: props => isProtein(props)
|
|
1300
1307
|
},
|
|
1301
1308
|
toggleAminoAcidNumbers_protein: {
|
|
1302
1309
|
...annotationToggleCommandDefs.toggleAminoAcidNumbers,
|
|
1303
|
-
isHidden:
|
|
1310
|
+
isHidden: props => isProtein(props)
|
|
1304
1311
|
}
|
|
1305
1312
|
};
|
|
1306
1313
|
|
|
1307
1314
|
const toolCommandDefs = {
|
|
1308
1315
|
simulateDigestion: {
|
|
1309
|
-
handler:
|
|
1316
|
+
handler: props => props.createNewDigest(),
|
|
1310
1317
|
hotkey: "mod+shift+d",
|
|
1311
1318
|
hotkeyProps: { preventDefault: true },
|
|
1312
|
-
isHidden:
|
|
1319
|
+
isHidden: props => isProtein(props)
|
|
1313
1320
|
},
|
|
1314
1321
|
simulatePCR: {
|
|
1315
|
-
handler:
|
|
1322
|
+
handler: props => props.createNewPCR(),
|
|
1316
1323
|
hotkey: "mod+shift+p",
|
|
1317
1324
|
hotkeyProps: { preventDefault: true },
|
|
1318
|
-
isHidden:
|
|
1325
|
+
isHidden: props => isProtein(props)
|
|
1319
1326
|
},
|
|
1320
1327
|
// TODO: enzyme manager (?)
|
|
1321
1328
|
restrictionEnzymesManager: {
|
|
1322
1329
|
name: "Manage Enzymes",
|
|
1323
|
-
handler:
|
|
1330
|
+
handler: props => {
|
|
1324
1331
|
if (props.enzymeManageOverride) {
|
|
1325
1332
|
props.enzymeManageOverride(props);
|
|
1326
1333
|
} else {
|
|
@@ -1335,14 +1342,14 @@ const toolCommandDefs = {
|
|
|
1335
1342
|
});
|
|
1336
1343
|
}
|
|
1337
1344
|
},
|
|
1338
|
-
isHidden:
|
|
1345
|
+
isHidden: props => isProtein(props)
|
|
1339
1346
|
},
|
|
1340
1347
|
openFilterCutsites: {
|
|
1341
1348
|
name: "Filter Cut Sites",
|
|
1342
|
-
handler:
|
|
1349
|
+
handler: props => {
|
|
1343
1350
|
props.openToolbarItemUpdate("cutsiteTool");
|
|
1344
1351
|
},
|
|
1345
|
-
isHidden:
|
|
1352
|
+
isHidden: props => isProtein(props)
|
|
1346
1353
|
},
|
|
1347
1354
|
openCreateCustomEnzyme: {
|
|
1348
1355
|
name: "Create Custom Enzyme",
|
|
@@ -1351,7 +1358,7 @@ const toolCommandDefs = {
|
|
|
1351
1358
|
dialogType: "CreateCustomEnzyme"
|
|
1352
1359
|
});
|
|
1353
1360
|
},
|
|
1354
|
-
isHidden:
|
|
1361
|
+
isHidden: props => props.overrideManageEnzymes
|
|
1355
1362
|
}
|
|
1356
1363
|
};
|
|
1357
1364
|
|
|
@@ -1372,8 +1379,8 @@ const labelSizes = {
|
|
|
1372
1379
|
const labelCommandDefs = {
|
|
1373
1380
|
adjustLabelLineIntensity: {
|
|
1374
1381
|
name: "Label Line Intensity",
|
|
1375
|
-
submenu:
|
|
1376
|
-
map(Object.keys(labelIntensities),
|
|
1382
|
+
submenu: props =>
|
|
1383
|
+
map(Object.keys(labelIntensities), key => ({
|
|
1377
1384
|
text: key,
|
|
1378
1385
|
checked: props.labelLineIntensity === labelIntensities[key],
|
|
1379
1386
|
onClick: () => props.changeLabelLineIntensity(labelIntensities[key])
|
|
@@ -1381,8 +1388,8 @@ const labelCommandDefs = {
|
|
|
1381
1388
|
},
|
|
1382
1389
|
adjustLabelSize: {
|
|
1383
1390
|
name: "Circular Label Size",
|
|
1384
|
-
submenu:
|
|
1385
|
-
map(Object.keys(labelSizes),
|
|
1391
|
+
submenu: props =>
|
|
1392
|
+
map(Object.keys(labelSizes), key => ({
|
|
1386
1393
|
text: key,
|
|
1387
1394
|
checked: props.labelSize === labelSizes[key],
|
|
1388
1395
|
onClick: () => props.changeLabelSize(labelSizes[key])
|
|
@@ -1392,7 +1399,7 @@ const labelCommandDefs = {
|
|
|
1392
1399
|
|
|
1393
1400
|
export const commandDefs = {
|
|
1394
1401
|
showChromQualScoresMenu: {
|
|
1395
|
-
isHidden:
|
|
1402
|
+
isHidden: props =>
|
|
1396
1403
|
!props.sequenceData.chromatogramData ||
|
|
1397
1404
|
!props.sequenceData.chromatogramData.baseTraces
|
|
1398
1405
|
},
|
|
@@ -1413,7 +1420,7 @@ export const commandDefs = {
|
|
|
1413
1420
|
...labelCommandDefs
|
|
1414
1421
|
};
|
|
1415
1422
|
|
|
1416
|
-
export default
|
|
1423
|
+
export default instance => oveCommandFactory(instance, commandDefs);
|
|
1417
1424
|
|
|
1418
1425
|
const invertString = function (str) {
|
|
1419
1426
|
let s = "";
|
|
@@ -1436,11 +1443,11 @@ const invertString = function (str) {
|
|
|
1436
1443
|
|
|
1437
1444
|
function getFilterByLengthCmd(type) {
|
|
1438
1445
|
return {
|
|
1439
|
-
name:
|
|
1446
|
+
name: props => {
|
|
1440
1447
|
return (
|
|
1441
1448
|
<div data-test={`filter-${type}-length`}>
|
|
1442
1449
|
Filter By Length
|
|
1443
|
-
<div onClick={
|
|
1450
|
+
<div onClick={e => e.stopPropagation()}>
|
|
1444
1451
|
<NumericInput
|
|
1445
1452
|
onValueChange={function (valueAsNumber) {
|
|
1446
1453
|
const minimumFilterLength = parseInt(valueAsNumber, 10);
|
|
@@ -1479,8 +1486,8 @@ function getFilterByLengthCmd(type) {
|
|
|
1479
1486
|
</div>
|
|
1480
1487
|
);
|
|
1481
1488
|
},
|
|
1482
|
-
isActive:
|
|
1483
|
-
handler:
|
|
1489
|
+
isActive: props => props[`${type}LengthsToHide`].enabled,
|
|
1490
|
+
handler: props => {
|
|
1484
1491
|
props[`toggle${startCase(type)}LengthsToHide`]();
|
|
1485
1492
|
}
|
|
1486
1493
|
};
|
|
@@ -1490,7 +1497,7 @@ function getFilterIndividualCmd(type) {
|
|
|
1490
1497
|
const pluralType = pluralize(type);
|
|
1491
1498
|
const upperType = startCase(type);
|
|
1492
1499
|
return {
|
|
1493
|
-
isHidden:
|
|
1500
|
+
isHidden: props => {
|
|
1494
1501
|
const total = Object.keys(
|
|
1495
1502
|
reduce(
|
|
1496
1503
|
props.sequenceData[pluralType],
|
|
@@ -1503,7 +1510,7 @@ function getFilterIndividualCmd(type) {
|
|
|
1503
1510
|
).length;
|
|
1504
1511
|
return total > 500;
|
|
1505
1512
|
},
|
|
1506
|
-
name:
|
|
1513
|
+
name: props => {
|
|
1507
1514
|
const total = Object.keys(
|
|
1508
1515
|
reduce(
|
|
1509
1516
|
props.sequenceData[pluralType],
|
|
@@ -1526,11 +1533,11 @@ function getFilterIndividualCmd(type) {
|
|
|
1526
1533
|
</span>
|
|
1527
1534
|
);
|
|
1528
1535
|
},
|
|
1529
|
-
submenu:
|
|
1536
|
+
submenu: props => {
|
|
1530
1537
|
const individualAnns = {};
|
|
1531
1538
|
forEach(
|
|
1532
1539
|
sortBy(props.sequenceData[pluralType], ({ start }) => start + 1),
|
|
1533
|
-
|
|
1540
|
+
ann => {
|
|
1534
1541
|
if (!ann.id) return;
|
|
1535
1542
|
const checked =
|
|
1536
1543
|
!props.annotationVisibility[`${type}IndividualToHide`][ann.id];
|