@teselagen/ove 0.3.11 → 0.3.12

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.
Files changed (148) hide show
  1. package/index.js +362 -209
  2. package/index.mjs +362 -209
  3. package/index.umd.js +339 -232
  4. package/package.json +1 -1
  5. package/src/AlignmentView/AlignmentVisibilityTool.js +1 -1
  6. package/src/AlignmentView/EditTrackNameDialog.js +1 -5
  7. package/src/AlignmentView/HorizontalPanelDragHandle.js +2 -2
  8. package/src/AlignmentView/Minimap.js +12 -12
  9. package/src/AlignmentView/PairwiseAlignmentView.js +1 -1
  10. package/src/AlignmentView/getGapMap.js +1 -1
  11. package/src/AlignmentView/getTrackFromEvent.js +1 -1
  12. package/src/AlignmentView/index.js +32 -37
  13. package/src/AutoAnnotate.js +48 -48
  14. package/src/CircularView/Cutsites.js +3 -3
  15. package/src/CircularView/Labels/index.js +7 -7
  16. package/src/CircularView/Labels/relaxLabels_DEPRECATED.js +5 -5
  17. package/src/CircularView/RotateCircularViewSlider.js +1 -1
  18. package/src/CircularView/SelectionLayer.js +2 -2
  19. package/src/CircularView/drawAnnotations.js +3 -3
  20. package/src/CircularView/getAngleForPositionMidpoint.js +1 -1
  21. package/src/CircularView/index.d.ts +11 -11
  22. package/src/CircularView/index.js +9 -9
  23. package/src/CreateAnnotationsPage.js +7 -5
  24. package/src/CreateCustomEnzyme/index.js +1 -5
  25. package/src/CutsiteFilter/AdditionalCutsiteInfoDialog.js +11 -11
  26. package/src/CutsiteFilter/index.js +12 -12
  27. package/src/DigestTool/AddLaddersDialog.js +1 -1
  28. package/src/DigestTool/DigestTool.js +3 -3
  29. package/src/DigestTool/Ladder.js +8 -8
  30. package/src/DigestTool/ladderDefaults.js +1 -2
  31. package/src/Editor/CommandHotkeyHandler.js +1 -1
  32. package/src/Editor/DropHandler.js +2 -2
  33. package/src/Editor/index.js +14 -14
  34. package/src/Editor/userDefinedHandlersAndOpts.js +2 -0
  35. package/src/FindBar/index.js +6 -6
  36. package/src/GlobalDialogUtils.js +6 -0
  37. package/src/LinearView/ZoomLinearView.js +1 -1
  38. package/src/LinearView/index.js +7 -7
  39. package/src/MenuBar/index.js +1 -1
  40. package/src/MenuBar/viewSubmenu.js +1 -1
  41. package/src/PCRTool/PCRTool.js +19 -19
  42. package/src/Reflex/Browser.js +4 -5
  43. package/src/Reflex/ReflexContainer.js +3 -3
  44. package/src/Reflex/ReflexElement.js +2 -2
  45. package/src/RowItem/Axis.js +1 -1
  46. package/src/RowItem/Caret/index.js +1 -1
  47. package/src/RowItem/Chromatograms/Chromatogram.js +3 -3
  48. package/src/RowItem/CutsiteSelectionLayers.js +1 -1
  49. package/src/RowItem/Cutsites.js +1 -1
  50. package/src/RowItem/Labels.js +2 -2
  51. package/src/RowItem/Orfs.js +2 -2
  52. package/src/RowItem/Sequence.js +4 -4
  53. package/src/RowItem/StackedAnnotations/PointedAnnotation.js +3 -3
  54. package/src/RowItem/StackedAnnotations/getStructuredBases.js +1 -1
  55. package/src/RowItem/Translations/AASliver.js +71 -75
  56. package/src/RowItem/Translations/index.js +1 -1
  57. package/src/RowItem/getCutsiteLabelHeights.js +1 -1
  58. package/src/RowItem/index.js +14 -8
  59. package/src/RowView/estimateRowHeight.js +5 -5
  60. package/src/RowView/index.d.ts +7 -7
  61. package/src/RowView/index.js +11 -12
  62. package/src/SimpleCircularOrLinearView.js +6 -6
  63. package/src/StatusBar/MeltingTemp.js +3 -3
  64. package/src/ToolBar/ToolbarItem.js +2 -2
  65. package/src/ToolBar/alignmentTool.js +9 -9
  66. package/src/ToolBar/editTool.js +1 -1
  67. package/src/ToolBar/findTool.js +2 -2
  68. package/src/ToolBar/importTool.js +1 -1
  69. package/src/ToolBar/index.js +2 -2
  70. package/src/ToolBar/oligoTool.js +1 -1
  71. package/src/ToolBar/orfTool.js +1 -6
  72. package/src/ToolBar/printTool.js +2 -2
  73. package/src/ToolBar/visibilityTool.js +1 -1
  74. package/src/VersionHistoryView/index.js +2 -2
  75. package/src/commands/index.js +236 -230
  76. package/src/createVectorEditor/index.js +4 -4
  77. package/src/fileUtils.js +18 -18
  78. package/src/helperComponents/AddOrEditAnnotationDialog/index.js +22 -15
  79. package/src/helperComponents/AddOrEditFeatureDialog/index.js +2 -2
  80. package/src/helperComponents/AddOrEditPartDialog/index.js +2 -2
  81. package/src/helperComponents/AddOrEditPrimerDialog/index.js +5 -5
  82. package/src/helperComponents/EnzymesDialog/index.js +17 -22
  83. package/src/helperComponents/GoToDialog.js +5 -1
  84. package/src/helperComponents/MergeFeaturesDialog/index.js +3 -3
  85. package/src/helperComponents/PinchHelper/PinchHelper.js +1 -1
  86. package/src/helperComponents/PrintDialog/index.js +4 -4
  87. package/src/helperComponents/PropertiesDialog/CutsiteProperties.js +3 -3
  88. package/src/helperComponents/PropertiesDialog/GenbankView.js +1 -1
  89. package/src/helperComponents/PropertiesDialog/GeneralProperties.js +5 -5
  90. package/src/helperComponents/PropertiesDialog/GenericAnnotationProperties.js +136 -138
  91. package/src/helperComponents/PropertiesDialog/OrfProperties.js +3 -3
  92. package/src/helperComponents/PropertiesDialog/PrimerProperties.js +1 -1
  93. package/src/helperComponents/PropertiesDialog/TranslationProperties.js +2 -2
  94. package/src/helperComponents/PropertiesDialog/index.js +3 -3
  95. package/src/helperComponents/RemoveDuplicates/index.js +3 -3
  96. package/src/helperComponents/SelectDialog.js +3 -3
  97. package/src/helperComponents/UncontrolledSliderWithPlusMinusBtns.js +5 -5
  98. package/src/helperComponents/createSimpleDialog.js +1 -1
  99. package/src/helperComponents/partTagSearch.js +2 -5
  100. package/src/helperComponents/withHover.js +3 -3
  101. package/src/redux/alignments.js +6 -6
  102. package/src/redux/annotationVisibility.js +4 -4
  103. package/src/redux/featureLengthsToHide.js +1 -1
  104. package/src/redux/frameTranslations.js +3 -3
  105. package/src/redux/middleware.js +2 -2
  106. package/src/redux/panelsShown.js +19 -19
  107. package/src/redux/partLengthsToHide.js +1 -1
  108. package/src/redux/primerLengthsToHide.js +1 -1
  109. package/src/redux/readOnly.js +1 -4
  110. package/src/redux/selectionLayer.js +1 -1
  111. package/src/redux/sequenceData/features.js +1 -1
  112. package/src/redux/sequenceData/upsertDeleteActionGenerator.js +1 -1
  113. package/src/redux/sequenceDataHistory.js +5 -5
  114. package/src/redux/toolBar.js +2 -4
  115. package/src/redux/utils/createMetaAction.js +2 -2
  116. package/src/redux/versionHistory.js +1 -2
  117. package/src/selectors/annotationSearchSelector.js +4 -4
  118. package/src/selectors/circularSelector.js +1 -1
  119. package/src/selectors/cutsiteLabelColorSelector.js +1 -1
  120. package/src/selectors/filteredCutsitesSelector.js +6 -6
  121. package/src/selectors/filteredFeaturesSelector.js +4 -4
  122. package/src/selectors/filteredPartsSelector.js +5 -5
  123. package/src/selectors/filteredPrimersSelector.js +3 -3
  124. package/src/selectors/isEnzymeFilterAndSelector.js +1 -1
  125. package/src/selectors/orfsSelector.js +1 -1
  126. package/src/selectors/restrictionEnzymesSelector.js +2 -2
  127. package/src/selectors/searchLayersSelector.js +7 -7
  128. package/src/selectors/sequenceLengthSelector.js +1 -1
  129. package/src/selectors/sequenceSelector.js +1 -1
  130. package/src/selectors/tagsToBoldSelector.js +1 -1
  131. package/src/selectors/translationsSelector.js +7 -7
  132. package/src/updateEditor.js +1 -1
  133. package/src/utils/PassThrough.js +1 -1
  134. package/src/utils/addWrappedAddons.js +1 -1
  135. package/src/utils/annotationTypes.js +2 -2
  136. package/src/utils/combineReducersDontIgnoreKeys.js +1 -1
  137. package/src/utils/editorUtils.js +2 -2
  138. package/src/utils/massageTickSpacing.js +1 -1
  139. package/src/utils/onlyUpdateForKeysDeep.js +1 -1
  140. package/src/utils/pureNoFunc.js +1 -1
  141. package/src/utils/shouldRerender.js +1 -1
  142. package/src/utils/showFileDialog.js +6 -7
  143. package/src/utils/updateLabelsForInViewFeatures.js +1 -1
  144. package/src/utils/useAnnotationLimits.js +1 -1
  145. package/src/withEditorInteractions/Keyboard.js +2 -3
  146. package/src/withEditorInteractions/createSequenceInputPopup.js +4 -4
  147. package/src/withEditorInteractions/index.js +93 -55
  148. package/src/withEditorProps/index.js +40 -37
@@ -10,7 +10,7 @@ const isEq = (o1, o2) => {
10
10
  return isEq;
11
11
  };
12
12
 
13
- const pure = (BaseComponent) => {
13
+ const pure = BaseComponent => {
14
14
  const hoc = shouldUpdate((props, nextProps) => !isEq(props, nextProps));
15
15
  return hoc(BaseComponent);
16
16
  };
@@ -18,7 +18,7 @@ const shouldRerender = (propKeys, stateKeys, that) => {
18
18
  export default shouldRerender;
19
19
 
20
20
  const isEq = (o1, o2) => {
21
- const isEq = isEqualWith(o1, o2, function(val1, val2) {
21
+ const isEq = isEqualWith(o1, o2, function (val1, val2) {
22
22
  if (isFunction(val1) && isFunction(val2)) {
23
23
  return val1 === val2 || val1.toString() === val2.toString();
24
24
  }
@@ -4,21 +4,20 @@ let callback;
4
4
 
5
5
  function getInput(multiple) {
6
6
  if (!hiddenInput) {
7
- hiddenInput = document.createElement('input');
8
- hiddenInput.type = 'file';
9
- hiddenInput.style.position = 'absolute';
10
- hiddenInput.style.visibility = 'hidden';
11
- hiddenInput.addEventListener('change', event => {
7
+ hiddenInput = document.createElement("input");
8
+ hiddenInput.type = "file";
9
+ hiddenInput.style.position = "absolute";
10
+ hiddenInput.style.visibility = "hidden";
11
+ hiddenInput.addEventListener("change", event => {
12
12
  callback(event.target.files);
13
13
  });
14
14
 
15
15
  document.body.appendChild(hiddenInput);
16
16
  }
17
- hiddenInput.multiple = multiple ? 'multiple' : undefined;
17
+ hiddenInput.multiple = multiple ? "multiple" : undefined;
18
18
  return hiddenInput;
19
19
  }
20
20
 
21
-
22
21
  export default function showFileDialog({ multiple = false, onSelect }) {
23
22
  const input = getInput(multiple);
24
23
  callback = onSelect;
@@ -20,7 +20,7 @@ export function updateLabelsForInViewFeatures({
20
20
  .querySelector(rectElement)
21
21
  .getBoundingClientRect();
22
22
 
23
- els.forEach((el) => {
23
+ els.forEach(el => {
24
24
  const elBounds = el.getBoundingClientRect();
25
25
  const isElIn = isElWithinAnotherEl(elBounds, boundingRect);
26
26
 
@@ -20,7 +20,7 @@ export function LimitAnnotations({ type, ...rest }) {
20
20
  const [limits = {}, setLimits] = useAnnotationLimits();
21
21
  return (
22
22
  <MenuItem icon="blank" shouldDismissPopover={false} {...rest}>
23
- {[50, 100, 200, 400].map((n) => (
23
+ {[50, 100, 200, 400].map(n => (
24
24
  <MenuItem
25
25
  shouldDismissPopover={false}
26
26
  icon={
@@ -24,7 +24,7 @@ class Clipboard extends React.Component {
24
24
  this.node.parentNode.removeEventListener("keyup", this.handleKeyUp, false);
25
25
  }
26
26
 
27
- handleKeyDown = (e) => {
27
+ handleKeyDown = e => {
28
28
  if (
29
29
  document.activeElement &&
30
30
  ["input", "select", "textarea"].indexOf(
@@ -63,7 +63,7 @@ class Clipboard extends React.Component {
63
63
  };
64
64
  return (
65
65
  <input
66
- ref={(c) => {
66
+ ref={c => {
67
67
  if (c) {
68
68
  this.node = c;
69
69
  }
@@ -83,4 +83,3 @@ class Clipboard extends React.Component {
83
83
  }
84
84
 
85
85
  export default Clipboard;
86
-
@@ -35,7 +35,7 @@ class SequenceInputNoHotkeys extends React.Component {
35
35
  this.handleUnmountIfClickOustidePopup
36
36
  );
37
37
  }
38
- handleUnmountIfClickOustidePopup = (e) => {
38
+ handleUnmountIfClickOustidePopup = e => {
39
39
  const n = findDOMNode(this);
40
40
  if (!n) return;
41
41
  const node = n.parentNode;
@@ -122,7 +122,7 @@ class SequenceInputNoHotkeys extends React.Component {
122
122
  <div className="sequenceInputBubble">
123
123
  <input
124
124
  autoCorrect="off"
125
- onKeyDown={(e) => {
125
+ onKeyDown={e => {
126
126
  if (e.keyCode === 27) {
127
127
  this.handleUnmount();
128
128
  }
@@ -135,9 +135,9 @@ class SequenceInputNoHotkeys extends React.Component {
135
135
  value={charsToInsert}
136
136
  autoFocus
137
137
  style={hasTempError ? { borderColor: "red" } : {}}
138
- onChange={(e) => {
138
+ onChange={e => {
139
139
  let sanitizedVal = "";
140
- e.target.value.split("").forEach((letter) => {
140
+ e.target.value.split("").forEach(letter => {
141
141
  const lowerLetter = letter.toLowerCase();
142
142
  if (replaceChars && replaceChars[lowerLetter]) {
143
143
  const isUpper = lowerLetter !== letter;
@@ -79,7 +79,7 @@ function VectorInteractionHOC(Component /* options */) {
79
79
  return class VectorInteractionWrapper extends React.Component {
80
80
  constructor(props) {
81
81
  super(props);
82
- annotationClickHandlers.forEach((handler) => {
82
+ annotationClickHandlers.forEach(handler => {
83
83
  this[handler] = (...args) => {
84
84
  const { clickOverrides = {} } = this.props;
85
85
  let preventDefault;
@@ -93,7 +93,7 @@ function VectorInteractionHOC(Component /* options */) {
93
93
  };
94
94
  });
95
95
 
96
- this.ConnectedMenu = (p) => {
96
+ this.ConnectedMenu = p => {
97
97
  return <ConnectedMenu {...props} {...p} />;
98
98
  };
99
99
  }
@@ -110,7 +110,7 @@ function VectorInteractionHOC(Component /* options */) {
110
110
  // documentation: https://craig.is/killing/mice
111
111
  this.combokeys.bind(
112
112
  "-.*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),
113
- (event) => {
113
+ event => {
114
114
  this.handleDnaInsert(event);
115
115
  }
116
116
  );
@@ -140,7 +140,7 @@ function VectorInteractionHOC(Component /* options */) {
140
140
  ];
141
141
 
142
142
  moveCaretBindings.forEach(({ keyCombo, type }) => {
143
- this.combokeys.bind(keyCombo, (event) => {
143
+ this.combokeys.bind(keyCombo, event => {
144
144
  const shiftHeld = event.shiftKey;
145
145
  const bpsPerRow = getBpsPerRow(this.props);
146
146
  const {
@@ -177,7 +177,7 @@ function VectorInteractionHOC(Component /* options */) {
177
177
  });
178
178
  });
179
179
 
180
- this.combokeys.bind(["backspace", "del"], (event) => {
180
+ this.combokeys.bind(["backspace", "del"], event => {
181
181
  // Handle shortcut
182
182
  this.handleDnaDelete(event);
183
183
  });
@@ -206,14 +206,18 @@ function VectorInteractionHOC(Component /* options */) {
206
206
  });
207
207
  };
208
208
 
209
- handlePaste = (e) => {
209
+ handlePaste = e => {
210
210
  const {
211
211
  caretPosition = -1,
212
212
  selectionLayer = { start: -1, end: -1 },
213
213
  readOnly,
214
- onPaste
214
+ onPaste,
215
+ disableBpEditing
215
216
  } = this.props;
216
217
 
218
+ if (disableBpEditing) {
219
+ return window.toastr.warning("Sorry the underlying sequence is locked");
220
+ }
217
221
  if (readOnly) {
218
222
  return window.toastr.warning("Sorry the sequence is Read-Only");
219
223
  }
@@ -253,12 +257,13 @@ function VectorInteractionHOC(Component /* options */) {
253
257
  e.preventDefault();
254
258
  };
255
259
 
256
- handleCutOrCopy = (isCut) => (e) => {
260
+ handleCutOrCopy = isCut => e => {
257
261
  const {
258
262
  onCopy = noop,
259
263
  sequenceData,
260
264
  selectionLayer,
261
265
  copyOptions,
266
+ disableBpEditing,
262
267
  readOnly
263
268
  } = this.props;
264
269
  const onCut = this.props.onCut || this.props.onCopy || noop;
@@ -289,7 +294,9 @@ function VectorInteractionHOC(Component /* options */) {
289
294
  !seqData.sequence.length
290
295
  )
291
296
  return window.toastr.warning(
292
- `No Sequence Selected To ${isCut && !readOnly ? "Cut" : "Copy"}`
297
+ `No Sequence Selected To ${
298
+ isCut && !(readOnly || disableBpEditing) ? "Cut" : "Copy"
299
+ }`
293
300
  );
294
301
 
295
302
  const clipboardData = e.clipboardData;
@@ -306,7 +313,7 @@ function VectorInteractionHOC(Component /* options */) {
306
313
  clipboardData.setData("application/json", JSON.stringify(seqData));
307
314
  e.preventDefault();
308
315
 
309
- if (isCut && !readOnly) {
316
+ if (isCut && !(readOnly || disableBpEditing) && !disableBpEditing) {
310
317
  this.handleDnaDelete(false);
311
318
  onCut(
312
319
  e,
@@ -319,7 +326,11 @@ function VectorInteractionHOC(Component /* options */) {
319
326
  document.body.removeEventListener("copy", this.handleCopy);
320
327
  }
321
328
  window.toastr.success(
322
- `Selection ${isCut && !readOnly ? "Cut" : "Copied"}`
329
+ `Selection ${
330
+ isCut && !(readOnly || disableBpEditing) && !disableBpEditing
331
+ ? "Cut"
332
+ : "Copied"
333
+ }`
323
334
  );
324
335
  this.sequenceDataToCopy = undefined;
325
336
  };
@@ -332,14 +343,18 @@ function VectorInteractionHOC(Component /* options */) {
332
343
  caretPosition = -1,
333
344
  selectionLayer = { start: -1, end: -1 },
334
345
  sequenceData = { sequence: "" },
335
- readOnly
346
+ readOnly,
347
+ disableBpEditing
336
348
  // updateSequenceData,
337
349
  // wrappedInsertSequenceDataAtPositionOrRange
338
350
  // handleInsert
339
351
  } = this.props;
340
352
  const sequenceLength = sequenceData.sequence.length;
341
353
  const isReplace = selectionLayer.start > -1;
342
- if (readOnly) {
354
+ if (disableBpEditing) {
355
+ return window.toastr.warning("Sorry the underlying sequence is locked");
356
+ }
357
+ if (readOnly || disableBpEditing) {
343
358
  window.toastr.warning("Sorry the sequence is Read-Only");
344
359
  } else {
345
360
  createSequenceInputPopup({
@@ -351,7 +366,7 @@ function VectorInteractionHOC(Component /* options */) {
351
366
  selectionLayer,
352
367
  sequenceLength,
353
368
  caretPosition,
354
- handleInsert: (seqDataToInsert) => {
369
+ handleInsert: seqDataToInsert => {
355
370
  insertAndSelectHelper({
356
371
  props: this.props,
357
372
  seqDataToInsert
@@ -369,13 +384,17 @@ function VectorInteractionHOC(Component /* options */) {
369
384
  selectionLayer = { start: -1, end: -1 },
370
385
  sequenceData = { sequence: "" },
371
386
  readOnly,
387
+ disableBpEditing,
372
388
  updateSequenceData,
373
389
  wrappedInsertSequenceDataAtPositionOrRange,
374
390
  caretPositionUpdate
375
391
  // handleInsert
376
392
  } = this.props;
377
393
  const sequenceLength = sequenceData.sequence.length;
378
- if (readOnly) {
394
+ if (disableBpEditing) {
395
+ return window.toastr.warning("Sorry the underlying sequence is locked");
396
+ }
397
+ if (readOnly || disableBpEditing) {
379
398
  return window.toastr.warning("Sorry the sequence is Read-Only");
380
399
  }
381
400
  if (sequenceLength > 0) {
@@ -421,7 +440,7 @@ function VectorInteractionHOC(Component /* options */) {
421
440
  }
422
441
  };
423
442
 
424
- caretPositionUpdate = (position) => {
443
+ caretPositionUpdate = position => {
425
444
  const { caretPosition = -1 } = this.props;
426
445
  if (caretPosition === position) {
427
446
  return;
@@ -429,7 +448,7 @@ function VectorInteractionHOC(Component /* options */) {
429
448
  //we only call caretPositionUpdate if we're actually changing something
430
449
  this.props.caretPositionUpdate(position);
431
450
  };
432
- selectionLayerUpdate = (newSelection) => {
451
+ selectionLayerUpdate = newSelection => {
433
452
  const { selectionLayer = { start: -1, end: -1 }, ignoreGapsOnHighlight } =
434
453
  this.props;
435
454
  if (!newSelection) return;
@@ -537,8 +556,9 @@ function VectorInteractionHOC(Component /* options */) {
537
556
  };
538
557
 
539
558
  // eslint-disable-next-line no-unused-vars
540
- getCopyOptions = (annotation) => {
541
- const { sequenceData, readOnly, selectionLayer } = this.props;
559
+ getCopyOptions = annotation => {
560
+ const { sequenceData, readOnly, disableBpEditing, selectionLayer } =
561
+ this.props;
542
562
  const { isProtein } = sequenceData;
543
563
  const makeTextCopyable = (transformFunc, className, action = "copy") => {
544
564
  return new Clipboard(`.${className}`, {
@@ -590,7 +610,7 @@ function VectorInteractionHOC(Component /* options */) {
590
610
  this.openVeCopyAA && this.openVeCopyAA.destroy();
591
611
  },
592
612
  didMount: ({ className }) => {
593
- this.openVeCopyAA = makeTextCopyable((selectedSeqData) => {
613
+ this.openVeCopyAA = makeTextCopyable(selectedSeqData => {
594
614
  const textToCopy = isProtein
595
615
  ? selectedSeqData.proteinSequence.toUpperCase()
596
616
  : getAminoAcidStringFromSequenceString(selectedSeqData.sequence);
@@ -604,7 +624,7 @@ function VectorInteractionHOC(Component /* options */) {
604
624
  // TODO: maybe stop using Clipboard.js and unify clipboard handling with
605
625
  // a more versatile approach
606
626
  return [
607
- ...(readOnly
627
+ ...(readOnly || disableBpEditing
608
628
  ? []
609
629
  : [
610
630
  {
@@ -620,7 +640,7 @@ function VectorInteractionHOC(Component /* options */) {
620
640
  didMount: ({ className }) => {
621
641
  // TODO: Maybe use a cut action instead
622
642
  this.openVeCut = makeTextCopyable(
623
- (s) => ({
643
+ s => ({
624
644
  ...s,
625
645
  textToCopy: isProtein ? s.proteinSequence : s.sequence
626
646
  }),
@@ -645,7 +665,7 @@ function VectorInteractionHOC(Component /* options */) {
645
665
  },
646
666
  didMount: ({ className }) => {
647
667
  this.openVeCopy2 = makeTextCopyable(
648
- (s) => ({ ...s, textToCopy: s.sequence }),
668
+ s => ({ ...s, textToCopy: s.sequence }),
649
669
  className
650
670
  );
651
671
  }
@@ -688,24 +708,17 @@ function VectorInteractionHOC(Component /* options */) {
688
708
  this.openVeCopyAAReverse && this.openVeCopyAAReverse.destroy();
689
709
  },
690
710
  didMount: ({ className }) => {
691
- this.openVeCopyAAReverse = makeTextCopyable(
692
- (selectedSeqData) => {
693
- const revSeqData =
694
- getReverseComplementSequenceAndAnnotations(
695
- selectedSeqData
696
- );
697
- const textToCopy = isProtein
698
- ? revSeqData.proteinSequence.toUpperCase()
699
- : getAminoAcidStringFromSequenceString(
700
- revSeqData.sequence
701
- );
702
- return {
703
- ...revSeqData,
704
- textToCopy
705
- };
706
- },
707
- className
708
- );
711
+ this.openVeCopyAAReverse = makeTextCopyable(selectedSeqData => {
712
+ const revSeqData =
713
+ getReverseComplementSequenceAndAnnotations(selectedSeqData);
714
+ const textToCopy = isProtein
715
+ ? revSeqData.proteinSequence.toUpperCase()
716
+ : getAminoAcidStringFromSequenceString(revSeqData.sequence);
717
+ return {
718
+ ...revSeqData,
719
+ textToCopy
720
+ };
721
+ }, className);
709
722
  }
710
723
  },
711
724
  {
@@ -728,7 +741,7 @@ function VectorInteractionHOC(Component /* options */) {
728
741
  ];
729
742
  };
730
743
 
731
- getSelectionMenuOptions = (annotation) => {
744
+ getSelectionMenuOptions = annotation => {
732
745
  const items = [
733
746
  ...this.getCopyOptions(annotation),
734
747
  createNewAnnotationMenu,
@@ -756,7 +769,7 @@ function VectorInteractionHOC(Component /* options */) {
756
769
  return handler({ event, ...rest }, this.props);
757
770
  };
758
771
  enhanceRightClickAction = (action, key) => {
759
- return (opts) => {
772
+ return opts => {
760
773
  const lastFocusedEl = document.activeElement;
761
774
  const { rightClickOverrides = {} } = this.props;
762
775
  const items = action(opts);
@@ -821,11 +834,12 @@ function VectorInteractionHOC(Component /* options */) {
821
834
  ({ nearestCaretPos, shiftHeld, event }) => {
822
835
  this.updateSelectionOrCaret(shiftHeld, nearestCaretPos);
823
836
  const {
824
- readOnly
837
+ readOnly,
838
+ disableBpEditing
825
839
  // sequenceData: { circular }
826
840
  } = this.props;
827
841
  const menu = [
828
- ...(readOnly
842
+ ...(readOnly || disableBpEditing
829
843
  ? []
830
844
  : [
831
845
  {
@@ -875,8 +889,7 @@ function VectorInteractionHOC(Component /* options */) {
875
889
  overlapsSelf: annotation.overlapsSelf
876
890
  });
877
891
  return [
878
- "editPart",
879
- "deletePart",
892
+ ...getEditDeleteHandlers("Part", annotation),
880
893
  "--",
881
894
  ...this.getSelectionMenuOptions(annotation),
882
895
  "--",
@@ -894,7 +907,7 @@ function VectorInteractionHOC(Component /* options */) {
894
907
  return [
895
908
  {
896
909
  text: "View Warning Details",
897
- onClick: (event) => {
910
+ onClick: event => {
898
911
  this.warningDoubleClicked({
899
912
  event,
900
913
  annotation,
@@ -919,8 +932,7 @@ function VectorInteractionHOC(Component /* options */) {
919
932
  event.persist();
920
933
  const { readOnly, annotationsToSupport: { parts } = {} } = this.props;
921
934
  return [
922
- "editFeature",
923
- "deleteFeature",
935
+ ...getEditDeleteHandlers("Feature", annotation),
924
936
  ...this.getSelectionMenuOptions(annotation),
925
937
  ...(readOnly
926
938
  ? []
@@ -932,7 +944,7 @@ function VectorInteractionHOC(Component /* options */) {
932
944
  onClick: async () => {
933
945
  const { sequenceData, upsertPart } = this.props;
934
946
  if (
935
- some(sequenceData.parts, (part) => {
947
+ some(sequenceData.parts, part => {
936
948
  if (
937
949
  part.start === annotation.start &&
938
950
  part.end === annotation.end
@@ -994,8 +1006,7 @@ function VectorInteractionHOC(Component /* options */) {
994
1006
  end: annotation.end
995
1007
  });
996
1008
  return [
997
- "editPrimer",
998
- "deletePrimer",
1009
+ ...getEditDeleteHandlers("Primer", annotation),
999
1010
  ...this.getSelectionMenuOptions(annotation),
1000
1011
  "showRemoveDuplicatesDialogPrimers",
1001
1012
  "viewPrimerProperties"
@@ -1127,7 +1138,7 @@ function VectorInteractionHOC(Component /* options */) {
1127
1138
  acc[handler] = this[handler];
1128
1139
  return acc;
1129
1140
  }, {}),
1130
- editorClicked: (p) => {
1141
+ editorClicked: p => {
1131
1142
  editorClicked({
1132
1143
  ...p,
1133
1144
  updateSelectionOrCaret: this.updateSelectionOrCaret
@@ -1140,7 +1151,7 @@ function VectorInteractionHOC(Component /* options */) {
1140
1151
  return (
1141
1152
  <div
1142
1153
  tabIndex={0} //this helps with focusing using Keyboard's parentElement.focus()
1143
- ref={(c) => (this.node = c)}
1154
+ ref={c => (this.node = c)}
1144
1155
  className="veVectorInteractionWrapper"
1145
1156
  style={{ position: "relative", ...vectorInteractionWrapperStyle }}
1146
1157
  onFocus={this.handleWrapperFocus}
@@ -1259,3 +1270,30 @@ const insertAndSelectHelper = ({ seqDataToInsert, props }) => {
1259
1270
  end: newSelectionLayerEnd % newSeqData.sequence.length
1260
1271
  });
1261
1272
  };
1273
+
1274
+ function getEditDeleteHandlers(type, annotation) {
1275
+ return [
1276
+ ...(annotation.isEditLocked
1277
+ ? [
1278
+ {
1279
+ shouldDismissPopover: false,
1280
+ text: (
1281
+ <div
1282
+ style={{
1283
+ fontSize: 11,
1284
+ fontStyle: "italic",
1285
+ color: "rgba(0,0,0,.5)"
1286
+ }}
1287
+ >
1288
+ {typeof annotation.isEditLocked === "string"
1289
+ ? annotation.isEditLocked
1290
+ : `Note: This Annotation is Locked`}
1291
+ </div>
1292
+ )
1293
+ }
1294
+ ]
1295
+ : []),
1296
+ `edit${type}`,
1297
+ ...(annotation.isEditLocked ? [] : [`delete${type}`])
1298
+ ];
1299
+ }