@teselagen/ove 0.7.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.
- package/DigestTool/DigestTool.d.ts +1 -1
- package/Menlo.ttf +0 -0
- package/Monaco.ttf +0 -0
- package/helperComponents/PropertiesDialog/index.d.ts +2 -7
- package/html2canvas.esm--JN4fLQL.mjs +7891 -0
- package/html2canvas.esm-B7d7VJmQ.js +7891 -0
- package/html2canvas.esm-GLpiTZLt.cjs +7891 -0
- package/html2canvas.esm-GLpiTZLt.js +7891 -0
- package/html2canvas.esm-nFNn58sx.js +7891 -0
- package/html2canvas.esm-nFNn58sx.mjs +7891 -0
- package/index.cjs.js +6534 -536
- package/index.es.js +6523 -525
- package/index.umd.js +6523 -516
- package/package.json +2 -2
- package/src/AutoAnnotate.js +1 -0
- package/src/CircularView/Labels/index.js +1 -15
- package/src/CircularView/index.js +3 -4
- package/src/CreateAnnotationsPage.js +1 -1
- package/src/DigestTool/DigestTool.js +78 -75
- package/src/GlobalDialogUtils.js +1 -0
- package/src/Reflex/reflex-styles.css +10 -10
- package/src/RowItem/CutsiteSelectionLayers.js +1 -1
- package/src/RowItem/SelectionLayer/index.js +2 -2
- package/src/RowItem/Sequence.js +0 -1
- package/src/RowItem/Translations/Translation.js +1 -0
- package/src/RowItem/index.js +0 -1
- package/src/helperComponents/PropertiesDialog/CutsiteProperties.js +126 -135
- package/src/helperComponents/PropertiesDialog/SingleEnzymeCutsiteInfo.js +59 -51
- package/src/helperComponents/PropertiesDialog/index.js +115 -114
- package/src/helperComponents/RemoveDuplicates/index.js +144 -160
- package/src/utils/useFormValue.js +7 -0
- package/src/withEditorInteractions/index.js +8 -7
- package/style.css +39 -15
- package/utils/useFormValue.d.ts +1 -0
|
@@ -18,11 +18,11 @@ import { pick } from "lodash-es";
|
|
|
18
18
|
const PropertiesContainer = Comp => props => {
|
|
19
19
|
const { additionalFooterEls, additionalHeaderEls, ...rest } = props;
|
|
20
20
|
return (
|
|
21
|
-
|
|
21
|
+
<>
|
|
22
22
|
{additionalHeaderEls}
|
|
23
23
|
<Comp {...rest} />
|
|
24
24
|
{additionalFooterEls}
|
|
25
|
-
|
|
25
|
+
</>
|
|
26
26
|
);
|
|
27
27
|
};
|
|
28
28
|
const allTabs = {
|
|
@@ -35,129 +35,130 @@ const allTabs = {
|
|
|
35
35
|
orfs: PropertiesContainer(OrfProperties),
|
|
36
36
|
genbank: PropertiesContainer(GenbankView)
|
|
37
37
|
};
|
|
38
|
-
export class PropertiesDialog extends React.Component {
|
|
39
|
-
render() {
|
|
40
|
-
const {
|
|
41
|
-
propertiesTool = {},
|
|
42
|
-
propertiesViewTabUpdate,
|
|
43
|
-
dimensions = {},
|
|
44
|
-
height,
|
|
45
|
-
editorName,
|
|
46
|
-
onSave,
|
|
47
|
-
showReadOnly,
|
|
48
|
-
showAvailability,
|
|
49
|
-
isProtein,
|
|
50
|
-
annotationsToSupport = {},
|
|
51
|
-
disableSetReadOnly,
|
|
52
|
-
propertiesList = [
|
|
53
|
-
"general",
|
|
54
|
-
"features",
|
|
55
|
-
"parts",
|
|
56
|
-
"primers",
|
|
57
|
-
"translations",
|
|
58
|
-
"cutsites",
|
|
59
|
-
"orfs",
|
|
60
|
-
"genbank"
|
|
61
|
-
],
|
|
62
|
-
closePanelButton
|
|
63
|
-
} = { ...this.props, ...this.props.PropertiesProps };
|
|
64
38
|
|
|
65
|
-
|
|
39
|
+
export const PropertiesDialog = props => {
|
|
40
|
+
const {
|
|
41
|
+
propertiesTool = {},
|
|
42
|
+
propertiesViewTabUpdate,
|
|
43
|
+
dimensions = {},
|
|
44
|
+
height,
|
|
45
|
+
editorName,
|
|
46
|
+
onSave,
|
|
47
|
+
showReadOnly,
|
|
48
|
+
showAvailability,
|
|
49
|
+
isProtein,
|
|
50
|
+
annotationsToSupport = {},
|
|
51
|
+
disableSetReadOnly,
|
|
52
|
+
propertiesList = [
|
|
53
|
+
"general",
|
|
54
|
+
"features",
|
|
55
|
+
"parts",
|
|
56
|
+
"primers",
|
|
57
|
+
"translations",
|
|
58
|
+
"cutsites",
|
|
59
|
+
"orfs",
|
|
60
|
+
"genbank"
|
|
61
|
+
],
|
|
62
|
+
closePanelButton
|
|
63
|
+
} = { ...props, ...props.PropertiesProps };
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
tabId
|
|
65
|
+
const { width, height: heightFromDim } = dimensions;
|
|
66
|
+
|
|
67
|
+
let { tabId, selectedAnnotationId } = propertiesTool;
|
|
68
|
+
if (
|
|
69
|
+
propertiesList
|
|
70
|
+
.map(nameOrOverride => nameOrOverride.name || nameOrOverride)
|
|
71
|
+
.indexOf(tabId) === -1
|
|
72
|
+
) {
|
|
73
|
+
tabId = propertiesList[0].name || propertiesList[0];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const propertiesTabs = flatMap(propertiesList, nameOrOverride => {
|
|
77
|
+
if (annotationsToSupport[nameOrOverride] === false) {
|
|
78
|
+
return [];
|
|
74
79
|
}
|
|
75
|
-
const propertiesTabs = flatMap(propertiesList, nameOrOverride => {
|
|
76
|
-
if (annotationsToSupport[nameOrOverride] === false) {
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
81
|
+
const name = nameOrOverride.name || nameOrOverride;
|
|
82
|
+
const Comp = nameOrOverride.Comp || allTabs[name];
|
|
83
|
+
if (isProtein) {
|
|
84
|
+
if (
|
|
85
|
+
name === "translations" ||
|
|
86
|
+
name === "orfs" ||
|
|
87
|
+
name === "primers" ||
|
|
88
|
+
name === "cutsites"
|
|
89
|
+
) {
|
|
90
|
+
return null;
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
key={name}
|
|
101
|
-
title={title}
|
|
102
|
-
id={name}
|
|
103
|
-
panel={
|
|
104
|
-
<Comp
|
|
105
|
-
{...{
|
|
106
|
-
...pick(this.props, userDefinedHandlersAndOpts),
|
|
107
|
-
editorName,
|
|
108
|
-
onSave,
|
|
109
|
-
isProtein,
|
|
110
|
-
showReadOnly,
|
|
111
|
-
showAvailability,
|
|
112
|
-
disableSetReadOnly,
|
|
113
|
-
selectedAnnotationId,
|
|
114
|
-
...(nameOrOverride.name && nameOrOverride)
|
|
115
|
-
}}
|
|
116
|
-
/>
|
|
117
|
-
}
|
|
118
|
-
/>
|
|
119
|
-
);
|
|
120
|
-
});
|
|
121
|
-
const heightToUse = Math.max(0, Number((heightFromDim || height) - 30));
|
|
92
|
+
}
|
|
93
|
+
const title = (() => {
|
|
94
|
+
if (nameOrOverride.Comp) return name; //just use the user supplied name because this is a custom panel
|
|
95
|
+
if (name === "orfs") return "ORFs";
|
|
96
|
+
if (name === "cutsites") return "Cut Sites";
|
|
97
|
+
return startCase(name);
|
|
98
|
+
})();
|
|
99
|
+
|
|
122
100
|
return (
|
|
101
|
+
<Tab
|
|
102
|
+
key={name}
|
|
103
|
+
title={title}
|
|
104
|
+
id={name}
|
|
105
|
+
panel={
|
|
106
|
+
<Comp
|
|
107
|
+
{...{
|
|
108
|
+
...pick(props, userDefinedHandlersAndOpts),
|
|
109
|
+
editorName,
|
|
110
|
+
onSave,
|
|
111
|
+
isProtein,
|
|
112
|
+
showReadOnly,
|
|
113
|
+
showAvailability,
|
|
114
|
+
disableSetReadOnly,
|
|
115
|
+
selectedAnnotationId,
|
|
116
|
+
...(nameOrOverride.name && nameOrOverride)
|
|
117
|
+
}}
|
|
118
|
+
/>
|
|
119
|
+
}
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
const heightToUse = Math.max(0, Number((heightFromDim || height) - 30));
|
|
124
|
+
return (
|
|
125
|
+
<div
|
|
126
|
+
style={{
|
|
127
|
+
position: "relative"
|
|
128
|
+
}}
|
|
129
|
+
>
|
|
130
|
+
{closePanelButton}
|
|
123
131
|
<div
|
|
132
|
+
className="ve-propertiesPanel"
|
|
124
133
|
style={{
|
|
125
|
-
|
|
134
|
+
display: "flex",
|
|
135
|
+
width,
|
|
136
|
+
height: heightToUse || 300,
|
|
137
|
+
zIndex: 10,
|
|
138
|
+
padding: 10
|
|
139
|
+
// paddingBottom: '31px',
|
|
126
140
|
}}
|
|
127
141
|
>
|
|
128
|
-
{
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
selectedTabId={tabId}
|
|
145
|
-
onChange={propertiesViewTabUpdate}
|
|
146
|
-
>
|
|
147
|
-
<Tabs.Expander />
|
|
148
|
-
{propertiesTabs}
|
|
149
|
-
<Tabs.Expander />
|
|
150
|
-
</Tabs>
|
|
151
|
-
) : (
|
|
152
|
-
<div style={{ margin: 20, fontSize: 20 }}>
|
|
153
|
-
No Properties to display
|
|
154
|
-
</div>
|
|
155
|
-
)}
|
|
156
|
-
</div>
|
|
142
|
+
{propertiesTabs.length ? (
|
|
143
|
+
<Tabs
|
|
144
|
+
style={{ width }}
|
|
145
|
+
renderActiveTabPanelOnly
|
|
146
|
+
selectedTabId={tabId}
|
|
147
|
+
onChange={propertiesViewTabUpdate}
|
|
148
|
+
>
|
|
149
|
+
<Tabs.Expander />
|
|
150
|
+
{propertiesTabs}
|
|
151
|
+
<Tabs.Expander />
|
|
152
|
+
</Tabs>
|
|
153
|
+
) : (
|
|
154
|
+
<div style={{ margin: 20, fontSize: 20 }}>
|
|
155
|
+
No Properties to display
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
157
158
|
</div>
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
};
|
|
161
162
|
|
|
162
163
|
export default compose(
|
|
163
164
|
connectToEditor(({ propertiesTool, annotationsToSupport }) => {
|
|
@@ -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
|
-
|
|
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";
|
|
17
|
+
|
|
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;
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
state = {
|
|
22
|
-
dups: []
|
|
23
|
-
};
|
|
24
|
-
componentDidMount() {
|
|
25
|
-
this.recomputeDups();
|
|
26
|
-
}
|
|
31
|
+
const { selectedEntities } = useTableEntities(dataTableFormName);
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
const ignoreName = useFormValue(dialogFormName, "ignoreName");
|
|
34
|
+
const ignoreStartAndEnd = useFormValue(dialogFormName, "ignoreStartAndEnd");
|
|
35
|
+
const ignoreStrand = useFormValue(dialogFormName, "ignoreStrand");
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
+
);
|
|
48
59
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const seqsHashByStartEndStrandName = {};
|
|
52
|
-
forEach(annotations, a => {
|
|
53
|
-
const hash = `${ignoreStartAndEnd ? "" : a.start}&${
|
|
54
|
-
ignoreStartAndEnd ? "" : a.end
|
|
55
|
-
}&${ignoreStrand ? "" : a.strand}&${ignoreName ? "" : a.name}`;
|
|
56
|
-
if (seqsHashByStartEndStrandName[hash]) {
|
|
57
|
-
dups.push({ ...a, size: getRangeLength(a, sequenceLength) });
|
|
58
|
-
} else {
|
|
59
|
-
seqsHashByStartEndStrandName[hash] = true;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
this.setState({ dups });
|
|
63
|
-
};
|
|
64
|
-
render() {
|
|
65
|
-
const { duplicatesToRemoveSelectedEntities, hideModal, type } = this.props;
|
|
60
|
+
const [dups, setDups] = useState(recomputeDups);
|
|
61
|
+
const selectedIds = useMemo(() => dups.map(d => d.id), [dups]);
|
|
66
62
|
|
|
67
|
-
|
|
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
|
+
);
|
|
68
76
|
|
|
69
|
-
|
|
77
|
+
const schema = useMemo(
|
|
78
|
+
() => ({
|
|
70
79
|
fields: [
|
|
71
|
-
// ...(noColor
|
|
72
|
-
// ? []
|
|
73
|
-
// : [
|
|
74
|
-
// {
|
|
75
|
-
// path: "color",
|
|
76
|
-
// type: "string",
|
|
77
|
-
// render: color => {
|
|
78
|
-
// return (
|
|
79
|
-
// <ColorPickerPopover>
|
|
80
|
-
// <div style={{ height: 20, width: 20, background: color }} />
|
|
81
|
-
// </ColorPickerPopover>
|
|
82
|
-
// );
|
|
83
|
-
// }
|
|
84
|
-
// }
|
|
85
|
-
// ]),
|
|
86
80
|
{ path: "name", type: "string" },
|
|
87
81
|
// ...(noType ? [] : [{ path: "type", type: "string" }]),
|
|
88
|
-
sizeSchema(
|
|
82
|
+
sizeSchema(isProtein),
|
|
89
83
|
{ path: "strand", type: "string" }
|
|
90
84
|
]
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<div className={classNames(Classes.DIALOG_BODY, "tg-min-width-dialog")}>
|
|
96
|
-
{/* {dups.map((d) => {
|
|
97
|
-
return <div>
|
|
85
|
+
}),
|
|
86
|
+
[isProtein]
|
|
87
|
+
);
|
|
98
88
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
128
|
-
|
|
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);
|
|
@@ -602,8 +602,13 @@ function VectorInteractionHOC(Component /* options */) {
|
|
|
602
602
|
return new Clipboard(`.${className}`, {
|
|
603
603
|
action: () => action,
|
|
604
604
|
text: () => {
|
|
605
|
-
|
|
606
|
-
|
|
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
|
-
|
|
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;
|