@teselagen/ove 0.7.30-beta.2 → 0.7.31

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.
@@ -3,7 +3,7 @@ import {
3
3
  condensePairwiseAlignmentDifferences
4
4
  } from "@teselagen/sequence-utils";
5
5
  import { convertBasePosTraceToPerBpTrace } from "@teselagen/bio-parsers";
6
- import { nanoid } from "nanoid";
6
+ import shortid from "shortid";
7
7
 
8
8
  import addDashesForMatchStartAndEndForTracks from "./utils/addDashesForMatchStartAndEndForTracks";
9
9
 
@@ -149,7 +149,7 @@ export default (state = {}, { payload = {}, type }) => {
149
149
  if (type === "UPSERT_ALIGNMENT_RUN") {
150
150
  const { id } = payload;
151
151
  const payloadToUse = {
152
- stateTrackingId: state[id]?.stateTrackingId ? nanoid() : "initialLoadId",
152
+ stateTrackingId: state[id]?.stateTrackingId ? shortid() : "initialLoadId",
153
153
  alignmentType: state[id]?.alignmentType,
154
154
  ...payload,
155
155
  //assign default visibilities
@@ -1,6 +1,6 @@
1
1
  import deepEqual from "deep-equal";
2
2
  import { tidyUpSequenceData } from "@teselagen/sequence-utils";
3
- import { nanoid } from "nanoid";
3
+ import uuid from "shortid";
4
4
 
5
5
  import createAction from "../utils/createMetaAction";
6
6
  import features from "./features";
@@ -75,7 +75,7 @@ export default function (state, action) {
75
75
  return {
76
76
  // ...cloneDeep(newState),
77
77
  ...newState,
78
- stateTrackingId: newState.stateTrackingId ? nanoid() : "initialLoadId"
78
+ stateTrackingId: newState.stateTrackingId ? uuid() : "initialLoadId"
79
79
  };
80
80
  }
81
81
  }
@@ -1,5 +1,5 @@
1
1
  import omit from "lodash/omit";
2
- import { nanoid } from "nanoid";
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 || nanoid();
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 { nanoid } from "nanoid";
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 = nanoid();
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 { nanoid } from "nanoid";
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 || nanoid();
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 = nanoid();
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 { nanoid } from "nanoid";
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 || nanoid()
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 = isCut => async e => {
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
- await navigator.clipboard.writeText(textToCopy);
317
- // application/json is not supported by clipboard api on browser
318
- // await navigator.clipboard.write([
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
- const makeTextCopyable = transformFunc => {
612
- return async e => {
613
- const { editorName, store } = this.props;
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
- const selectedSeqData = getSequenceDataBetweenRange(
618
- sequenceData,
619
- getSelFromWrappedAddon(
620
- selectionLayer,
621
- sequenceData.sequence.length
622
- ),
623
- {
624
- excludePartial: {
625
- features: !copyOptions.partialFeatures,
626
- parts: !copyOptions.partialParts
627
- },
628
- exclude: {
629
- features: !copyOptions.features,
630
- parts: !copyOptions.parts
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
- const sequenceDataToCopy = transformFunc(
635
- selectedSeqData,
636
- sequenceData
637
- );
638
- this.sequenceDataToCopy = sequenceDataToCopy;
634
+ );
635
+ const sequenceDataToCopy = transformFunc(
636
+ selectedSeqData,
637
+ sequenceData
638
+ );
639
+ this.sequenceDataToCopy = sequenceDataToCopy;
639
640
 
640
- if (window.Cypress) {
641
- window.Cypress.textToCopy = sequenceDataToCopy.textToCopy;
642
- window.Cypress.seqDataToCopy = sequenceDataToCopy;
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
- this.handleCopy(e);
645
- };
647
+ });
646
648
  };
647
649
  const aaCopy = {
648
650
  text: "Copy AA Sequence",
649
651
  className: "openVeCopyAA",
650
- onClick: makeTextCopyable(selectedSeqData => ({
651
- ...selectedSeqData,
652
- textToCopy: isProtein
653
- ? selectedSeqData.proteinSequence.toUpperCase()
654
- : getAminoAcidStringFromSequenceString(selectedSeqData.sequence)
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
- onClick: this.handleCut
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
- onClick: makeTextCopyable(s => ({
682
- ...s,
683
- textToCopy: s.sequence
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
- onClick: makeTextCopyable(getGenbankFromSelection)
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
- onClick: makeTextCopyable(
698
- getReverseComplementSequenceAndAnnotations
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
- onClick: makeTextCopyable(selectedSeqData => {
706
- const revSeqData =
707
- getReverseComplementSequenceAndAnnotations(selectedSeqData);
708
- return {
709
- ...revSeqData,
710
- textToCopy: isProtein
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
- onClick: makeTextCopyable(getComplementSequenceAndAnnotations)
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 { nanoid } from "nanoid";
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 = nanoid();
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;