@teselagen/ove 0.6.1-beta.1 → 0.7.2

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 (44) hide show
  1. package/DigestTool/DigestTool.d.ts +2 -10
  2. package/Menlo.ttf +0 -0
  3. package/Monaco.ttf +0 -0
  4. package/helperComponents/PropertiesDialog/index.d.ts +2 -7
  5. package/helperComponents/PropertiesDialog/utils.d.ts +5 -5
  6. package/html2canvas.esm--JN4fLQL.mjs +7891 -0
  7. package/html2canvas.esm-B7d7VJmQ.js +7891 -0
  8. package/html2canvas.esm-GLpiTZLt.cjs +7891 -0
  9. package/html2canvas.esm-GLpiTZLt.js +7891 -0
  10. package/html2canvas.esm-nFNn58sx.js +7891 -0
  11. package/html2canvas.esm-nFNn58sx.mjs +7891 -0
  12. package/index.cjs.js +78073 -73781
  13. package/index.es.js +78467 -74175
  14. package/index.umd.js +81406 -77036
  15. package/package.json +7 -8
  16. package/src/AutoAnnotate.js +1 -0
  17. package/src/CircularView/Labels/index.js +1 -15
  18. package/src/CircularView/index.js +3 -4
  19. package/src/CreateAnnotationsPage.js +1 -1
  20. package/src/CutsiteFilter/index.js +51 -55
  21. package/src/DigestTool/DigestTool.js +193 -188
  22. package/src/GlobalDialogUtils.js +1 -0
  23. package/src/PCRTool/PCRTool.js +8 -2
  24. package/src/Reflex/reflex-styles.css +10 -10
  25. package/src/RowItem/CutsiteSelectionLayers.js +1 -1
  26. package/src/RowItem/SelectionLayer/index.js +2 -2
  27. package/src/RowItem/Sequence.js +0 -1
  28. package/src/RowItem/Translations/Translation.js +1 -0
  29. package/src/RowItem/index.js +0 -1
  30. package/src/helperComponents/AddOrEditAnnotationDialog/index.js +8 -4
  31. package/src/helperComponents/AddOrEditFeatureDialog/index.js +9 -7
  32. package/src/helperComponents/AddOrEditPartDialog/index.js +3 -3
  33. package/src/helperComponents/AddOrEditPrimerDialog/index.js +3 -7
  34. package/src/helperComponents/PropertiesDialog/CutsiteProperties.js +126 -135
  35. package/src/helperComponents/PropertiesDialog/GenericAnnotationProperties.js +52 -50
  36. package/src/helperComponents/PropertiesDialog/OrfProperties.js +1 -1
  37. package/src/helperComponents/PropertiesDialog/SingleEnzymeCutsiteInfo.js +59 -51
  38. package/src/helperComponents/PropertiesDialog/index.js +115 -114
  39. package/src/helperComponents/PropertiesDialog/utils.js +5 -5
  40. package/src/helperComponents/RemoveDuplicates/index.js +149 -165
  41. package/src/utils/useFormValue.js +7 -0
  42. package/src/withEditorInteractions/index.js +8 -7
  43. package/style.css +287 -263
  44. package/utils/useFormValue.d.ts +1 -0
@@ -1,194 +1,178 @@
1
- import React from "react";
1
+ import React, { useCallback, useMemo, useState } from "react";
2
2
  import { reduxForm } from "redux-form";
3
-
4
3
  import {
5
4
  wrapDialog,
6
5
  DataTable,
7
- withSelectedEntities,
8
6
  SwitchField,
9
- tgFormValues
7
+ useTableEntities
10
8
  } from "@teselagen/ui";
11
9
  import { compose } from "redux";
12
10
  import { Button, Classes, Popover } from "@blueprintjs/core";
13
11
  import classNames from "classnames";
14
-
15
12
  import withEditorProps from "../../withEditorProps";
16
13
  import { forEach, camelCase, startCase } from "lodash-es";
17
14
  import { sizeSchema } from "../PropertiesDialog/utils";
18
15
  import { getRangeLength } from "@teselagen/range-utils";
16
+ import { useFormValue } from "../../utils/useFormValue";
19
17
 
20
- const schema = {
21
- fields: [
22
- // ...(noColor
23
- // ? []
24
- // : [
25
- // {
26
- // path: "color",
27
- // type: "string",
28
- // render: color => {
29
- // return (
30
- // <ColorPickerPopover>
31
- // <div style={{ height: 20, width: 20, background: color }} />
32
- // </ColorPickerPopover>
33
- // );
34
- // }
35
- // }
36
- // ]),
37
- { path: "name", type: "string" },
38
- // ...(noType ? [] : [{ path: "type", type: "string" }]),
39
- sizeSchema,
40
- { path: "strand", type: "string" }
41
- ]
42
- };
18
+ const dialogFormName = "RemoveDuplicatesDialog";
19
+ const dataTableFormName = "duplicatesToRemove";
20
+ const checkboxStyle = { marginTop: 0, marginBottom: 0 };
21
+
22
+ const RemoveDuplicatesDialog = props => {
23
+ const {
24
+ type,
25
+ sequenceData = { sequence: "" },
26
+ sequenceLength,
27
+ isProtein,
28
+ hideModal
29
+ } = props;
30
+
31
+ const { selectedEntities } = useTableEntities(dataTableFormName);
43
32
 
44
- class RemoveDuplicatesDialog extends React.Component {
45
- state = {
46
- dups: []
47
- };
48
- componentDidMount() {
49
- this.recomputeDups();
50
- }
33
+ const ignoreName = useFormValue(dialogFormName, "ignoreName");
34
+ const ignoreStartAndEnd = useFormValue(dialogFormName, "ignoreStartAndEnd");
35
+ const ignoreStrand = useFormValue(dialogFormName, "ignoreStrand");
51
36
 
52
- checkboxStyle = { marginTop: 0, marginBottom: 0 };
37
+ const recomputeDups = useCallback(
38
+ values => {
39
+ const ignoreName = values?.ignoreName;
40
+ const ignoreStartAndEnd = values?.ignoreStartAndEnd;
41
+ const ignoreStrand = values?.ignoreStrand;
42
+ const annotations = sequenceData[type];
43
+ const newDups = [];
44
+ const seqsHashByStartEndStrandName = {};
45
+ forEach(annotations, a => {
46
+ const hash = `${ignoreStartAndEnd ? "" : a.start}&${
47
+ ignoreStartAndEnd ? "" : a.end
48
+ }&${ignoreStrand ? "" : a.strand}&${ignoreName ? "" : a.name}`;
49
+ if (seqsHashByStartEndStrandName[hash]) {
50
+ newDups.push({ ...a, size: getRangeLength(a, sequenceLength) });
51
+ } else {
52
+ seqsHashByStartEndStrandName[hash] = true;
53
+ }
54
+ });
55
+ return newDups;
56
+ },
57
+ [sequenceData, sequenceLength, type]
58
+ );
53
59
 
54
- delayedRecomputeDups = () => {
55
- setTimeout(() => {
56
- this.recomputeDups();
57
- });
58
- };
59
- recomputeDups = () => {
60
- const {
61
- // hideModal,
62
- type,
63
- sequenceData = { sequence: "" },
64
- // handleSubmit,
65
- sequenceLength,
66
- ignoreName,
67
- ignoreStrand,
68
- ignoreStartAndEnd
69
- // circular,
70
- // upsertFeature
71
- } = this.props;
60
+ const [dups, setDups] = useState(recomputeDups);
61
+ const selectedIds = useMemo(() => dups.map(d => d.id), [dups]);
72
62
 
73
- const annotations = sequenceData[type];
74
- const dups = [];
75
- const seqsHashByStartEndStrandName = {};
76
- forEach(annotations, a => {
77
- const hash = `${ignoreStartAndEnd ? "" : a.start}&${
78
- ignoreStartAndEnd ? "" : a.end
79
- }&${ignoreStrand ? "" : a.strand}&${ignoreName ? "" : a.name}`;
80
- if (seqsHashByStartEndStrandName[hash]) {
81
- dups.push({ ...a, size: getRangeLength(a, sequenceLength) });
82
- } else {
83
- seqsHashByStartEndStrandName[hash] = true;
84
- }
85
- });
86
- this.setState({ dups });
87
- };
88
- render() {
89
- const { duplicatesToRemoveSelectedEntities, hideModal, type } = this.props;
63
+ const fieldSubmit = useCallback(
64
+ (newVal, field) => {
65
+ const values = {
66
+ ignoreName,
67
+ ignoreStartAndEnd,
68
+ ignoreStrand,
69
+ [field]: newVal
70
+ };
71
+ const newDups = recomputeDups(values);
72
+ setDups(newDups);
73
+ },
74
+ [ignoreName, ignoreStartAndEnd, ignoreStrand, recomputeDups]
75
+ );
90
76
 
91
- const selectedIds = this.state.dups.map(d => d.id);
92
- // const sequenceLength = sequenceData.sequence.length;
93
- // const isCirc = (this.state || {}).circular;
94
- return (
95
- <div className={classNames(Classes.DIALOG_BODY, "tg-min-width-dialog")}>
96
- {/* {dups.map((d) => {
97
- return <div>
77
+ const schema = useMemo(
78
+ () => ({
79
+ fields: [
80
+ { path: "name", type: "string" },
81
+ // ...(noType ? [] : [{ path: "type", type: "string" }]),
82
+ sizeSchema(isProtein),
83
+ { path: "strand", type: "string" }
84
+ ]
85
+ }),
86
+ [isProtein]
87
+ );
98
88
 
99
- </div>
100
- })} */}
101
- <DataTable
102
- noPadding
103
- withCheckboxes
104
- noFullscreenButton
105
- // onRowSelect={this.onRowSelect}
106
- maxHeight={400}
107
- selectedIds={selectedIds}
108
- formName="duplicatesToRemove"
109
- noRouter
110
- noRowsFoundMessage="No duplicates found"
111
- compact
112
- noHeader
113
- noFooter
114
- withSearch={false}
115
- hideSelectedCount
116
- isInfinite
117
- schema={schema}
118
- entities={this.state.dups}
89
+ return (
90
+ <div className={classNames(Classes.DIALOG_BODY, "tg-min-width-dialog")}>
91
+ <DataTable
92
+ noPadding
93
+ withCheckboxes
94
+ noFullscreenButton
95
+ maxHeight={400}
96
+ selectedIds={selectedIds}
97
+ formName={dataTableFormName}
98
+ noRouter
99
+ noRowsFoundMessage="No duplicates found"
100
+ compact
101
+ noHeader
102
+ noFooter
103
+ withSearch={false}
104
+ hideSelectedCount
105
+ isInfinite
106
+ schema={schema}
107
+ entities={dups}
108
+ />
109
+ <div
110
+ style={{
111
+ marginTop: 10,
112
+ display: "flex",
113
+ justifyContent: "space-between"
114
+ }}
115
+ >
116
+ <Popover
117
+ target={<Button icon="settings" />}
118
+ content={
119
+ <div style={{ padding: 20, maxWidth: 250 }}>
120
+ <div>Ignore These Fields While Finding Duplicates:</div>
121
+ <br />
122
+ <SwitchField
123
+ containerStyle={{ marginBottom: 2 }}
124
+ //delay the call to recompute dups until redux has had time to update
125
+ onFieldSubmit={newVal => fieldSubmit(newVal, "ignoreName")}
126
+ style={checkboxStyle}
127
+ name="ignoreName"
128
+ label="Name"
129
+ />
130
+ <SwitchField
131
+ containerStyle={{ marginBottom: 2 }}
132
+ //delay the call to recompute dups until redux has had time to update
133
+ onFieldSubmit={newVal => fieldSubmit(newVal, "ignoreStrand")}
134
+ style={checkboxStyle}
135
+ name="ignoreStrand"
136
+ label="Strand"
137
+ />
138
+ <SwitchField
139
+ containerStyle={{ marginBottom: 2 }}
140
+ //delay the call to recompute dups until redux has had time to update
141
+ onFieldSubmit={newVal =>
142
+ fieldSubmit(newVal, "ignoreStartAndEnd")
143
+ }
144
+ style={checkboxStyle}
145
+ name="ignoreStartAndEnd"
146
+ label="Start and End"
147
+ />
148
+ </div>
149
+ }
119
150
  />
120
- <div
121
- style={{
122
- marginTop: 10,
123
- display: "flex",
124
- justifyContent: "space-between"
151
+
152
+ <Button
153
+ intent="primary"
154
+ onClick={() => {
155
+ props[camelCase(`delete_${type}`).slice(0, -1)](
156
+ Object.keys(selectedEntities || {})
157
+ );
158
+ window.toastr.success(
159
+ `Successfully Deleted ${
160
+ Object.keys(selectedEntities || {}).length
161
+ } ${startCase(type)}`
162
+ );
163
+ hideModal();
125
164
  }}
165
+ disabled={!Object.keys(selectedEntities || {}).length}
126
166
  >
127
- <Popover
128
- target={<Button icon="settings" />}
129
- content={
130
- <div style={{ padding: 20, maxWidth: 250 }}>
131
- <div>Ignore These Fields While Finding Duplicates:</div>
132
- <br></br>
133
- <SwitchField
134
- containerStyle={{ marginBottom: 2 }}
135
- //delay the call to recompute dups until redux has had time to update
136
- onFieldSubmit={this.delayedRecomputeDups}
137
- style={this.checkboxStyle}
138
- name="ignoreName"
139
- label="Name"
140
- ></SwitchField>
141
- <SwitchField
142
- containerStyle={{ marginBottom: 2 }}
143
- //delay the call to recompute dups until redux has had time to update
144
- onFieldSubmit={this.delayedRecomputeDups}
145
- style={this.checkboxStyle}
146
- name="ignoreStrand"
147
- label="Strand"
148
- ></SwitchField>
149
- <SwitchField
150
- containerStyle={{ marginBottom: 2 }}
151
- //delay the call to recompute dups until redux has had time to update
152
- onFieldSubmit={this.delayedRecomputeDups}
153
- style={this.checkboxStyle}
154
- name="ignoreStartAndEnd"
155
- label="Start and End"
156
- ></SwitchField>
157
- </div>
158
- }
159
- ></Popover>
160
-
161
- <Button
162
- intent="primary"
163
- onClick={() => {
164
- this.props[camelCase(`delete_${type}`).slice(0, -1)](
165
- duplicatesToRemoveSelectedEntities.map(d => d.id)
166
- );
167
- window.toastr.success(
168
- `Successfully Deleted ${
169
- duplicatesToRemoveSelectedEntities.length
170
- } ${startCase(type)}`
171
- );
172
- hideModal();
173
- }}
174
- disabled={!(duplicatesToRemoveSelectedEntities || []).length}
175
- >
176
- Remove {duplicatesToRemoveSelectedEntities.length} Duplicates
177
- </Button>
178
- </div>
167
+ Remove {Object.keys(selectedEntities || {}).length} Duplicates
168
+ </Button>
179
169
  </div>
180
- );
181
- }
182
- }
170
+ </div>
171
+ );
172
+ };
183
173
 
184
174
  export default compose(
185
175
  wrapDialog(),
186
176
  withEditorProps,
187
-
188
- withSelectedEntities("duplicatesToRemove"),
189
-
190
- reduxForm({
191
- form: "RemoveDuplicatesDialog"
192
- }),
193
- tgFormValues("ignoreName", "ignoreStrand", "ignoreStartAndEnd")
177
+ reduxForm({ form: dialogFormName })
194
178
  )(RemoveDuplicatesDialog);
@@ -0,0 +1,7 @@
1
+ /* Copyright (C) 2018 TeselaGen Biotechnology, Inc. */
2
+ import { useSelector } from "react-redux";
3
+ import { get } from "lodash";
4
+
5
+ export const useFormValue = (formName, field) => {
6
+ return useSelector(state => get(state.form?.[formName]?.values, field));
7
+ };
@@ -602,8 +602,13 @@ function VectorInteractionHOC(Component /* options */) {
602
602
  return new Clipboard(`.${className}`, {
603
603
  action: () => action,
604
604
  text: () => {
605
- const { selectionLayer, editorName, store } = this.props;
606
- const { sequenceData, copyOptions } =
605
+ if (action === "copy") {
606
+ document.body.addEventListener("copy", this.handleCopy);
607
+ } else {
608
+ document.body.addEventListener("cut", this.handleCut);
609
+ }
610
+ const { editorName, store } = this.props;
611
+ const { sequenceData, copyOptions, selectionLayer } =
607
612
  store.getState().VectorEditor[editorName];
608
613
 
609
614
  const selectedSeqData = getSequenceDataBetweenRange(
@@ -628,11 +633,7 @@ function VectorInteractionHOC(Component /* options */) {
628
633
  sequenceData
629
634
  );
630
635
  this.sequenceDataToCopy = sequenceDataToCopy;
631
- if (action === "copy") {
632
- document.body.addEventListener("copy", this.handleCopy);
633
- } else {
634
- document.body.addEventListener("cut", this.handleCut);
635
- }
636
+
636
637
  if (window.Cypress) {
637
638
  window.Cypress.textToCopy = sequenceDataToCopy.textToCopy;
638
639
  window.Cypress.seqDataToCopy = sequenceDataToCopy;