@teselagen/ove 0.7.30-beta.2 → 0.7.30
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/CircularView/Labels/index.d.ts +1 -0
- package/CreateAnnotationsPage.d.ts +3 -4
- package/index.cjs.js +12306 -11064
- package/index.es.js +12306 -11064
- package/index.umd.js +13606 -12364
- package/ove.css +55 -55
- package/package.json +9 -13
- package/selectors/orfsSelector.d.ts +2 -2
- package/selectors/translationsSelector.d.ts +1 -1
- package/src/AlignmentView/index.js +5 -42
- package/src/AutoAnnotate.js +4 -4
- package/src/CircularView/Labels/index.js +84 -49
- package/src/CreateAnnotationsPage.js +2 -1
- package/src/GlobalDialogUtils.js +2 -2
- package/src/RowItem/Labels.js +5 -4
- package/src/ToolBar/alignmentTool.js +2 -2
- package/src/helperComponents/MergeFeaturesDialog/index.js +2 -2
- package/src/redux/alignments.js +2 -2
- package/src/redux/sequenceData/index.js +2 -2
- package/src/redux/sequenceData/upsertDeleteActionGenerator.js +2 -2
- package/src/selectors/cutsitesSelector.js +2 -2
- package/src/selectors/translationsSelector.js +3 -3
- package/src/utils/cleanSequenceData_DEPRECATED/arrayToObjWithIds.js +2 -2
- package/src/withEditorInteractions/index.js +136 -83
- package/src/withEditorProps/index.js +2 -2
- package/fileUtils.d.ts +0 -12
- package/html2canvas.esm--JN4fLQL.js +0 -7891
- package/html2canvas.esm-B7d7VJmQ.cjs +0 -7891
- package/src/fileUtils.js +0 -103
- package/style.css +0 -12107
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import omit from "lodash/omit";
|
|
2
|
-
import
|
|
2
|
+
import uuid from "shortid";
|
|
3
3
|
|
|
4
4
|
// ------------------------------------
|
|
5
5
|
// Reducer
|
|
@@ -10,7 +10,7 @@ export default function upsertDeleteActionGenerator(
|
|
|
10
10
|
) {
|
|
11
11
|
return {
|
|
12
12
|
[upsertAction]: (state, payload) => {
|
|
13
|
-
const idToUse = payload.id ||
|
|
13
|
+
const idToUse = payload.id || uuid();
|
|
14
14
|
return {
|
|
15
15
|
...state,
|
|
16
16
|
[idToUse]: { ...(state[idToUse] || {}), ...payload, id: idToUse }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import shortid from "shortid";
|
|
2
2
|
import circularSelector from "./circularSelector";
|
|
3
3
|
import sequenceSelector from "./sequenceSelector";
|
|
4
4
|
import restrictionEnzymesSelector from "./restrictionEnzymesSelector";
|
|
@@ -20,7 +20,7 @@ function cutsitesSelector(sequence, circular, enzymeList, cutsiteLabelColors) {
|
|
|
20
20
|
const cutsitesForEnzyme = cutsitesByName[enzymeName];
|
|
21
21
|
cutsitesForEnzyme.forEach(function (cutsite) {
|
|
22
22
|
const numberOfCuts = cutsitesByName[enzymeName].length;
|
|
23
|
-
const uniqueId =
|
|
23
|
+
const uniqueId = shortid();
|
|
24
24
|
cutsite.id = uniqueId;
|
|
25
25
|
cutsite.numberOfCuts = numberOfCuts;
|
|
26
26
|
cutsite.annotationType = "cutsite";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { reduce } from "lodash-es";
|
|
2
|
-
import
|
|
2
|
+
import uuid from "shortid";
|
|
3
3
|
import sequenceSelector from "./sequenceSelector";
|
|
4
4
|
import orfsSelector from "./orfsSelector";
|
|
5
5
|
import { createSelector } from "reselect";
|
|
@@ -28,7 +28,7 @@ function translationsSelector(
|
|
|
28
28
|
const translationsToPass = {
|
|
29
29
|
...translationSearchMatches.reduce((acc, match) => {
|
|
30
30
|
if (!match) return acc;
|
|
31
|
-
const id = match.id ||
|
|
31
|
+
const id = match.id || uuid();
|
|
32
32
|
acc[id] = {
|
|
33
33
|
...match,
|
|
34
34
|
id,
|
|
@@ -79,7 +79,7 @@ function translationsSelector(
|
|
|
79
79
|
(acc, isActive, frameName) => {
|
|
80
80
|
const frameOffset = Number(frameName);
|
|
81
81
|
if (isActive) {
|
|
82
|
-
const id =
|
|
82
|
+
const id = uuid();
|
|
83
83
|
acc[id] = {
|
|
84
84
|
id,
|
|
85
85
|
start:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//helper function to make sure any arrays coming in
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import shortid from "shortid";
|
|
4
4
|
|
|
5
5
|
//get converted to objects with unique ids
|
|
6
6
|
export default function arrayToObjWithIds(array) {
|
|
@@ -8,7 +8,7 @@ export default function arrayToObjWithIds(array) {
|
|
|
8
8
|
array.forEach(function (item) {
|
|
9
9
|
const newItem = {
|
|
10
10
|
...item,
|
|
11
|
-
id: item.id ||
|
|
11
|
+
id: item.id || shortid()
|
|
12
12
|
};
|
|
13
13
|
newObj[newItem.id] = newItem;
|
|
14
14
|
});
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
getAminoAcidStringFromSequenceString
|
|
5
5
|
} from "@teselagen/sequence-utils";
|
|
6
6
|
import { getSequenceWithinRange } from "@teselagen/range-utils";
|
|
7
|
+
import Clipboard from "clipboard";
|
|
7
8
|
import { compose } from "redux";
|
|
8
9
|
import {
|
|
9
10
|
getReverseComplementSequenceAndAnnotations,
|
|
@@ -258,7 +259,8 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
258
259
|
e.preventDefault();
|
|
259
260
|
};
|
|
260
261
|
|
|
261
|
-
handleCutOrCopy =
|
|
262
|
+
handleCutOrCopy = _isCut => async e => {
|
|
263
|
+
const isCut = _isCut || this.isCut || false;
|
|
262
264
|
e.preventDefault();
|
|
263
265
|
const {
|
|
264
266
|
onCopy = noop,
|
|
@@ -313,16 +315,9 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
313
315
|
: seqData.sequence;
|
|
314
316
|
|
|
315
317
|
seqData.textToCopy = textToCopy;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
// new ClipboardItem({
|
|
320
|
-
// "application/json": new Blob([JSON.stringify(seqData)], {
|
|
321
|
-
// type: "application/json"
|
|
322
|
-
// }),
|
|
323
|
-
// "text/plain": new Blob([textToCopy], { type: "text/plain" })
|
|
324
|
-
// })
|
|
325
|
-
// ]);
|
|
318
|
+
e.clipboardData.setData("text/plain", textToCopy);
|
|
319
|
+
e.clipboardData.setData("application/json", JSON.stringify(seqData));
|
|
320
|
+
e.preventDefault();
|
|
326
321
|
|
|
327
322
|
if (isCut && !(readOnly || disableBpEditing) && !disableBpEditing) {
|
|
328
323
|
this.handleDnaDelete(false);
|
|
@@ -337,6 +332,8 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
337
332
|
} else {
|
|
338
333
|
onCopy(e, seqData, this.props);
|
|
339
334
|
}
|
|
335
|
+
document.body.removeEventListener("cut", this.handleCut);
|
|
336
|
+
document.body.removeEventListener("copy", this.handleCopy);
|
|
340
337
|
window.toastr.success(
|
|
341
338
|
`Selection ${
|
|
342
339
|
isCut && !(readOnly || disableBpEditing) && !disableBpEditing
|
|
@@ -518,14 +515,11 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
518
515
|
};
|
|
519
516
|
|
|
520
517
|
annotationClicked = ({ event, annotation }) => {
|
|
518
|
+
if (event.target) {
|
|
519
|
+
event.target?.closest(".veVectorInteractionWrapper")?.focus();
|
|
520
|
+
}
|
|
521
521
|
event.preventDefault && event.preventDefault();
|
|
522
522
|
event.stopPropagation && event.stopPropagation();
|
|
523
|
-
// if (hoveredAnnEasyStore.selectedAnn?.id === annotation?.id) {
|
|
524
|
-
// hoveredAnnEasyStore.selectedAnn = undefined;
|
|
525
|
-
// hoveredAnnEasyStore.hoveredAnn = undefined;
|
|
526
|
-
// } else {
|
|
527
|
-
// hoveredAnnEasyStore.selectedAnn = annotation;
|
|
528
|
-
// }
|
|
529
523
|
|
|
530
524
|
const {
|
|
531
525
|
annotationSelect,
|
|
@@ -608,51 +602,67 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
608
602
|
const { sequenceData, readOnly, disableBpEditing, selectionLayer } =
|
|
609
603
|
this.props;
|
|
610
604
|
const { isProtein } = sequenceData;
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
const { sequenceData, copyOptions, selectionLayer } =
|
|
615
|
-
store.getState().VectorEditor[editorName];
|
|
605
|
+
// Add the appropriate listener
|
|
606
|
+
document.body.addEventListener("copy", this.handleCopy, { once: true });
|
|
607
|
+
document.body.addEventListener("cut", this.handleCut, { once: true });
|
|
616
608
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
{
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
609
|
+
const makeTextCopyable = (transformFunc, className, action = "copy") => {
|
|
610
|
+
return new Clipboard(`.${className}`, {
|
|
611
|
+
action: () => action,
|
|
612
|
+
text: () => {
|
|
613
|
+
this.isCut = action === "cut";
|
|
614
|
+
const { editorName, store } = this.props;
|
|
615
|
+
const { sequenceData, copyOptions, selectionLayer } =
|
|
616
|
+
store.getState().VectorEditor[editorName];
|
|
617
|
+
|
|
618
|
+
const selectedSeqData = getSequenceDataBetweenRange(
|
|
619
|
+
sequenceData,
|
|
620
|
+
getSelFromWrappedAddon(
|
|
621
|
+
selectionLayer,
|
|
622
|
+
sequenceData.sequence.length
|
|
623
|
+
),
|
|
624
|
+
{
|
|
625
|
+
excludePartial: {
|
|
626
|
+
features: !copyOptions.partialFeatures,
|
|
627
|
+
parts: !copyOptions.partialParts
|
|
628
|
+
},
|
|
629
|
+
exclude: {
|
|
630
|
+
features: !copyOptions.features,
|
|
631
|
+
parts: !copyOptions.parts
|
|
632
|
+
}
|
|
631
633
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
this.sequenceDataToCopy = sequenceDataToCopy;
|
|
634
|
+
);
|
|
635
|
+
const sequenceDataToCopy = transformFunc(
|
|
636
|
+
selectedSeqData,
|
|
637
|
+
sequenceData
|
|
638
|
+
);
|
|
639
|
+
this.sequenceDataToCopy = sequenceDataToCopy;
|
|
639
640
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
641
|
+
if (window.Cypress) {
|
|
642
|
+
window.Cypress.textToCopy = sequenceDataToCopy.textToCopy;
|
|
643
|
+
window.Cypress.seqDataToCopy = sequenceDataToCopy;
|
|
644
|
+
}
|
|
645
|
+
return sequenceDataToCopy.textToCopy || sequenceDataToCopy.sequence;
|
|
643
646
|
}
|
|
644
|
-
|
|
645
|
-
};
|
|
647
|
+
});
|
|
646
648
|
};
|
|
647
649
|
const aaCopy = {
|
|
648
650
|
text: "Copy AA Sequence",
|
|
649
651
|
className: "openVeCopyAA",
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
652
|
+
willUnmount: () => {
|
|
653
|
+
this.openVeCopyAA && this.openVeCopyAA.destroy();
|
|
654
|
+
},
|
|
655
|
+
didMount: ({ className }) => {
|
|
656
|
+
this.openVeCopyAA = makeTextCopyable(selectedSeqData => {
|
|
657
|
+
const textToCopy = isProtein
|
|
658
|
+
? selectedSeqData.proteinSequence.toUpperCase()
|
|
659
|
+
: getAminoAcidStringFromSequenceString(selectedSeqData.sequence);
|
|
660
|
+
return {
|
|
661
|
+
...selectedSeqData,
|
|
662
|
+
textToCopy
|
|
663
|
+
};
|
|
664
|
+
}, className);
|
|
665
|
+
}
|
|
656
666
|
};
|
|
657
667
|
return [
|
|
658
668
|
...(readOnly || disableBpEditing
|
|
@@ -665,7 +675,19 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
665
675
|
{
|
|
666
676
|
text: "Cut",
|
|
667
677
|
className: "openVeCut",
|
|
668
|
-
|
|
678
|
+
willUnmount: () => {
|
|
679
|
+
this.openVeCut && this.openVeCut.destroy();
|
|
680
|
+
},
|
|
681
|
+
didMount: ({ className }) => {
|
|
682
|
+
this.openVeCut = makeTextCopyable(
|
|
683
|
+
s => ({
|
|
684
|
+
...s,
|
|
685
|
+
textToCopy: isProtein ? s.proteinSequence : s.sequence
|
|
686
|
+
}),
|
|
687
|
+
className,
|
|
688
|
+
"cut"
|
|
689
|
+
);
|
|
690
|
+
}
|
|
669
691
|
}
|
|
670
692
|
]),
|
|
671
693
|
{
|
|
@@ -678,45 +700,80 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
678
700
|
{
|
|
679
701
|
text: isProtein ? "Copy DNA Bps" : "Copy",
|
|
680
702
|
className: "openVeCopy2",
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
})
|
|
703
|
+
willUnmount: () => {
|
|
704
|
+
this.openVeCopy2 && this.openVeCopy2.destroy();
|
|
705
|
+
},
|
|
706
|
+
didMount: ({ className }) => {
|
|
707
|
+
this.openVeCopy2 = makeTextCopyable(
|
|
708
|
+
s => ({ ...s, textToCopy: s.sequence }),
|
|
709
|
+
className
|
|
710
|
+
);
|
|
711
|
+
}
|
|
685
712
|
},
|
|
686
713
|
|
|
687
714
|
{
|
|
688
715
|
text: "Copy Genbank For Selection",
|
|
689
716
|
className: "openVeCopyGenbankForSelection",
|
|
690
|
-
|
|
717
|
+
willUnmount: () => {
|
|
718
|
+
this.openVeCopyGenbankForSelection &&
|
|
719
|
+
this.openVeCopyGenbankForSelection.destroy();
|
|
720
|
+
},
|
|
721
|
+
didMount: ({ className }) => {
|
|
722
|
+
this.openVeCopyGenbankForSelection = makeTextCopyable(
|
|
723
|
+
getGenbankFromSelection,
|
|
724
|
+
className
|
|
725
|
+
);
|
|
726
|
+
}
|
|
691
727
|
},
|
|
692
728
|
{
|
|
693
729
|
text: isProtein
|
|
694
730
|
? "Copy Reverse Complement DNA Bps"
|
|
695
731
|
: "Copy Reverse Complement",
|
|
696
732
|
className: "openVeCopyReverse",
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
733
|
+
willUnmount: () => {
|
|
734
|
+
this.openVeCopyReverse && this.openVeCopyReverse.destroy();
|
|
735
|
+
},
|
|
736
|
+
didMount: ({ className }) => {
|
|
737
|
+
this.openVeCopyReverse = makeTextCopyable(
|
|
738
|
+
getReverseComplementSequenceAndAnnotations,
|
|
739
|
+
className
|
|
740
|
+
);
|
|
741
|
+
}
|
|
700
742
|
},
|
|
701
743
|
...(isProtein ? [] : [aaCopy]),
|
|
702
744
|
{
|
|
703
745
|
text: "Copy Reverse Complement AA Sequence",
|
|
704
746
|
className: "openVeCopyAAReverse",
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
747
|
+
willUnmount: () => {
|
|
748
|
+
this.openVeCopyAAReverse && this.openVeCopyAAReverse.destroy();
|
|
749
|
+
},
|
|
750
|
+
didMount: ({ className }) => {
|
|
751
|
+
this.openVeCopyAAReverse = makeTextCopyable(selectedSeqData => {
|
|
752
|
+
const revSeqData =
|
|
753
|
+
getReverseComplementSequenceAndAnnotations(selectedSeqData);
|
|
754
|
+
const textToCopy = isProtein
|
|
711
755
|
? revSeqData.proteinSequence.toUpperCase()
|
|
712
|
-
: getAminoAcidStringFromSequenceString(revSeqData.sequence)
|
|
713
|
-
|
|
714
|
-
|
|
756
|
+
: getAminoAcidStringFromSequenceString(revSeqData.sequence);
|
|
757
|
+
return {
|
|
758
|
+
...revSeqData,
|
|
759
|
+
textToCopy
|
|
760
|
+
};
|
|
761
|
+
}, className);
|
|
762
|
+
}
|
|
715
763
|
},
|
|
716
764
|
{
|
|
717
765
|
text: isProtein ? "Copy Complement DNA Bps" : "Copy Complement",
|
|
718
766
|
className: "openVeCopyComplement",
|
|
719
|
-
|
|
767
|
+
willUnmount: () => {
|
|
768
|
+
this.openVeCopyComplement &&
|
|
769
|
+
this.openVeCopyComplement.destroy();
|
|
770
|
+
},
|
|
771
|
+
didMount: ({ className }) => {
|
|
772
|
+
this.openVeCopyComplement = makeTextCopyable(
|
|
773
|
+
getComplementSequenceAndAnnotations,
|
|
774
|
+
className
|
|
775
|
+
);
|
|
776
|
+
}
|
|
720
777
|
},
|
|
721
778
|
copyOptionsMenu
|
|
722
779
|
]
|
|
@@ -753,10 +810,14 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
753
810
|
};
|
|
754
811
|
enhanceRightClickAction = (action, key) => {
|
|
755
812
|
return opts => {
|
|
756
|
-
const lastFocusedEl = document.activeElement;
|
|
757
813
|
const { rightClickOverrides = {} } = this.props;
|
|
758
814
|
const items = action(opts);
|
|
759
815
|
const e = (items && items._event) || opts.event || opts;
|
|
816
|
+
if (e.target) {
|
|
817
|
+
e.target?.closest(".veVectorInteractionWrapper")?.focus();
|
|
818
|
+
}
|
|
819
|
+
const lastFocusedEl = document.activeElement;
|
|
820
|
+
|
|
760
821
|
e.preventDefault && e.preventDefault();
|
|
761
822
|
e.stopPropagation && e.stopPropagation();
|
|
762
823
|
//override hook here
|
|
@@ -766,15 +827,7 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
766
827
|
[this.commandEnhancer],
|
|
767
828
|
e,
|
|
768
829
|
() => {
|
|
769
|
-
if (
|
|
770
|
-
lastFocusedEl &&
|
|
771
|
-
document.activeElement &&
|
|
772
|
-
(document.activeElement.classList.contains(
|
|
773
|
-
"bp3-popover-enter-done"
|
|
774
|
-
) ||
|
|
775
|
-
(document.activeElement.type === "textarea" && //this is the clipboard textarea created by clipboardjs
|
|
776
|
-
document.activeElement.offsetLeft === -9999))
|
|
777
|
-
) {
|
|
830
|
+
if (lastFocusedEl) {
|
|
778
831
|
lastFocusedEl.focus();
|
|
779
832
|
}
|
|
780
833
|
},
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
invertRange,
|
|
28
28
|
normalizeRange
|
|
29
29
|
} from "@teselagen/range-utils";
|
|
30
|
-
import
|
|
30
|
+
import shortid from "shortid";
|
|
31
31
|
|
|
32
32
|
import addMetaToActionCreators from "../redux/utils/addMetaToActionCreators";
|
|
33
33
|
import { actions, editorReducer } from "../redux";
|
|
@@ -268,7 +268,7 @@ export const importSequenceFromFile =
|
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
if (seqData) {
|
|
271
|
-
seqData.stateTrackingId =
|
|
271
|
+
seqData.stateTrackingId = shortid();
|
|
272
272
|
updateEditor(
|
|
273
273
|
{
|
|
274
274
|
getState: () => ({ VectorEditor: { [props.editorName]: props } }),
|
package/fileUtils.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export const allowedCsvFileTypes: string[];
|
|
2
|
-
export function isZipFile(file: any): boolean;
|
|
3
|
-
export function getExt(file: any): any;
|
|
4
|
-
export function isExcelFile(file: any): boolean;
|
|
5
|
-
export function isCsvFile(file: any): boolean;
|
|
6
|
-
export function isTextFile(file: any): boolean;
|
|
7
|
-
export function parseCsvFile(csvFile: any, parserOptions?: {}): Promise<any>;
|
|
8
|
-
export function parseCsvString(csvString: any, parserOptions?: {}): void;
|
|
9
|
-
export function cleanCommaSeparatedCell(cellData: any): any;
|
|
10
|
-
export function cleanCsvExport(rows: any): any;
|
|
11
|
-
export function validateCSVRequiredHeaders(fields: any, requiredHeaders: any, filename: any): string | undefined;
|
|
12
|
-
export function validateCSVRow(row: any, requiredHeaders: any, index: any): string | undefined;
|