@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
@@ -44,15 +44,58 @@ const genericAnnotationProperties = ({
44
44
  constructor(props) {
45
45
  super(props);
46
46
  this.commands = commands(this);
47
+ }
48
+ onRowSelect = ([record]) => {
49
+ if (!record) return;
50
+ const { dispatch, editorName } = this.props;
51
+ dispatch({
52
+ type: "SELECTION_LAYER_UPDATE",
53
+ payload: record,
54
+ meta: {
55
+ editorName
56
+ }
57
+ });
58
+ };
59
+ render() {
60
+ const {
61
+ readOnly,
62
+ annotations = {},
63
+ annotationVisibility,
64
+ sequenceLength,
65
+ selectionLayer,
66
+ sequence,
67
+ isProtein,
68
+ allPartTags,
69
+ annotationPropertiesSelectedEntities:
70
+ _annotationPropertiesSelectedEntities,
71
+ selectedAnnotationId
72
+ } = this.props;
73
+ const annotationPropertiesSelectedEntities =
74
+ _annotationPropertiesSelectedEntities.filter(a => annotations[a.id]);
75
+
76
+ const deleteAnnotation = this.props[`delete${annotationTypeUpper}`];
77
+
78
+ const annotationsToUse = map(annotations, annotation => {
79
+ return {
80
+ ...annotation,
81
+ ...(annotation.strand === undefined && {
82
+ strand: annotation.forward ? 1 : -1
83
+ }),
84
+ size: getRangeLength(annotation, sequenceLength)
85
+ };
86
+ });
87
+
88
+ const keyedPartTags = getKeyedTagsAndTagOptions(allPartTags) ?? {};
89
+
47
90
  this.schema = {
48
91
  fields: [
49
92
  {
50
93
  path: "name",
51
94
  type: "string",
52
95
 
53
- render: (name, ann, row, props) => {
96
+ render: (name, ann) => {
54
97
  const checked =
55
- !props.annotationVisibility[
98
+ !this.props.annotationVisibility[
56
99
  `${annotationType}IndividualToHide`
57
100
  ][ann.id];
58
101
 
@@ -64,9 +107,9 @@ const genericAnnotationProperties = ({
64
107
  e.stopPropagation();
65
108
  const upperType = startCase(annotationType);
66
109
  if (checked) {
67
- props[`hide${upperType}Individual`]([ann.id]);
110
+ this.props[`hide${upperType}Individual`]([ann.id]);
68
111
  } else {
69
- props[`show${upperType}Individual`]([ann.id]);
112
+ this.props[`show${upperType}Individual`]([ann.id]);
70
113
  }
71
114
  }}
72
115
  style={{
@@ -89,10 +132,10 @@ const genericAnnotationProperties = ({
89
132
  {
90
133
  path: "bases",
91
134
  type: "string",
92
- render: (bases, primer, row, props) => {
135
+ render: (bases, primer) => {
93
136
  let bps = bases;
94
137
  if (!bases) {
95
- bps = getSequenceWithinRange(primer, props.sequence);
138
+ bps = getSequenceWithinRange(primer, this.props.sequence);
96
139
  if (!primer.forward) {
97
140
  bps = getReverseComplementSequenceString(bps);
98
141
  }
@@ -121,13 +164,13 @@ const genericAnnotationProperties = ({
121
164
  }
122
165
  }
123
166
  ]),
124
- sizeSchema,
167
+ sizeSchema(this.props.isProtein),
125
168
  ...(withTags && this.props.allPartTags
126
169
  ? [
127
170
  {
128
171
  path: "tags",
129
172
  type: "string",
130
- getValueToFilterOn: (o, { keyedPartTags }) => {
173
+ getValueToFilterOn: o => {
131
174
  const toRet = (o.tags || [])
132
175
  .map(tagId => {
133
176
  const tag = keyedPartTags[tagId];
@@ -137,7 +180,7 @@ const genericAnnotationProperties = ({
137
180
  .join(" ");
138
181
  return toRet;
139
182
  },
140
- render: (tags, b, c, { keyedPartTags = {} }) => {
183
+ render: tags => {
141
184
  return (
142
185
  <div style={{ display: "flex" }}>
143
186
  {(tags || []).map((tagId, i) => {
@@ -154,46 +197,6 @@ const genericAnnotationProperties = ({
154
197
  { path: "strand", type: "number" }
155
198
  ]
156
199
  };
157
- }
158
- onRowSelect = ([record]) => {
159
- if (!record) return;
160
- const { dispatch, editorName } = this.props;
161
- dispatch({
162
- type: "SELECTION_LAYER_UPDATE",
163
- payload: record,
164
- meta: {
165
- editorName
166
- }
167
- });
168
- };
169
- render() {
170
- const {
171
- readOnly,
172
- annotations = {},
173
- annotationVisibility,
174
- sequenceLength,
175
- selectionLayer,
176
- sequence,
177
- isProtein,
178
- allPartTags,
179
- annotationPropertiesSelectedEntities:
180
- _annotationPropertiesSelectedEntities,
181
- selectedAnnotationId
182
- } = this.props;
183
- const annotationPropertiesSelectedEntities =
184
- _annotationPropertiesSelectedEntities.filter(a => annotations[a.id]);
185
-
186
- const deleteAnnotation = this.props[`delete${annotationTypeUpper}`];
187
-
188
- const annotationsToUse = map(annotations, annotation => {
189
- return {
190
- ...annotation,
191
- ...(annotation.strand === undefined && {
192
- strand: annotation.forward ? 1 : -1
193
- }),
194
- size: getRangeLength(annotation, sequenceLength)
195
- };
196
- });
197
200
 
198
201
  return (
199
202
  <DataTable
@@ -337,7 +340,6 @@ const genericAnnotationProperties = ({
337
340
  formName="annotationProperties"
338
341
  noRouter
339
342
  isProtein={isProtein}
340
- keyedPartTags={getKeyedTagsAndTagOptions(allPartTags)}
341
343
  compact
342
344
  isInfinite
343
345
  schema={this.schema}
@@ -80,7 +80,7 @@ class OrfProperties extends React.Component {
80
80
  displayName: "Size (aa)",
81
81
  type: "number"
82
82
  },
83
- sizeSchema,
83
+ sizeSchema(this.props.isProtein),
84
84
  { path: "frame", type: "number" },
85
85
  { path: "strand", type: "number" }
86
86
  ]
@@ -1,11 +1,17 @@
1
- import React from "react";
1
+ import React, { useCallback, useMemo } from "react";
2
2
  import { DataTable } from "@teselagen/ui";
3
-
4
3
  import { CutsiteTag } from "../../CutsiteFilter/AdditionalCutsiteInfoDialog";
5
-
6
4
  import EnzymeViewer from "../../EnzymeViewer";
7
5
  import { getEnzymeAliases } from "../../utils/editorUtils";
8
6
 
7
+ const schema = {
8
+ fields: [
9
+ { path: "topSnipPosition", displayName: "Top Snip", type: "string" },
10
+ { path: "position", type: "string" },
11
+ { path: "strand", type: "string" }
12
+ ]
13
+ };
14
+
9
15
  export default function SingleEnzymeCutsiteInfo({
10
16
  cutsiteGroup,
11
17
  enzyme,
@@ -16,40 +22,52 @@ export default function SingleEnzymeCutsiteInfo({
16
22
  allCutsites,
17
23
  filteredCutsites: { cutsitesByName: cutsitesByNameActive }
18
24
  }) {
19
- const onRowSelect = ([record]) => {
20
- if (!record) return;
25
+ const onRowSelect = useCallback(
26
+ ([record]) => {
27
+ if (!record) return;
21
28
 
22
- dispatch({
23
- type: "CARET_POSITION_UPDATE",
24
- payload: record.topSnipPosition,
25
- meta: {
26
- editorName
27
- }
28
- });
29
- };
30
- const aliases = getEnzymeAliases(enzyme);
31
- const entities = cutsiteGroup
32
- .sort((a, b) => a.topSnipPosition - b.topSnipPosition)
33
- .map(
34
- ({
35
- restrictionEnzyme: { forwardRegex, reverseRegex } = {},
36
- forward,
37
- id,
38
- topSnipBeforeBottom,
39
- topSnipPosition,
40
- bottomSnipPosition
41
- }) => {
42
- return {
43
- id,
44
- topSnipPosition,
45
- position: topSnipBeforeBottom
46
- ? topSnipPosition + " - " + bottomSnipPosition
47
- : bottomSnipPosition + " - " + topSnipPosition,
48
- strand:
49
- forwardRegex === reverseRegex ? "Palindromic" : forward ? "1" : "-1"
50
- };
51
- }
52
- );
29
+ dispatch({
30
+ type: "CARET_POSITION_UPDATE",
31
+ payload: record.topSnipPosition,
32
+ meta: {
33
+ editorName
34
+ }
35
+ });
36
+ },
37
+ [dispatch, editorName]
38
+ );
39
+
40
+ const aliases = useMemo(() => getEnzymeAliases(enzyme), [enzyme]);
41
+ const entities = useMemo(
42
+ () =>
43
+ cutsiteGroup
44
+ .sort((a, b) => a.topSnipPosition - b.topSnipPosition)
45
+ .map(
46
+ ({
47
+ restrictionEnzyme: { forwardRegex, reverseRegex } = {},
48
+ forward,
49
+ id,
50
+ topSnipBeforeBottom,
51
+ topSnipPosition,
52
+ bottomSnipPosition
53
+ }) => {
54
+ return {
55
+ id,
56
+ topSnipPosition,
57
+ position: topSnipBeforeBottom
58
+ ? topSnipPosition + " - " + bottomSnipPosition
59
+ : bottomSnipPosition + " - " + topSnipPosition,
60
+ strand:
61
+ forwardRegex === reverseRegex
62
+ ? "Palindromic"
63
+ : forward
64
+ ? "1"
65
+ : "-1"
66
+ };
67
+ }
68
+ ),
69
+ [cutsiteGroup]
70
+ );
53
71
 
54
72
  return (
55
73
  <div>
@@ -61,14 +79,12 @@ export default function SingleEnzymeCutsiteInfo({
61
79
  >
62
80
  {enzyme && (
63
81
  <EnzymeViewer
64
- {...{
65
- sequence: enzyme.site,
66
- reverseSnipPosition: enzyme.bottomSnipOffset,
67
- forwardSnipPosition: enzyme.topSnipOffset
68
- }}
82
+ sequence={enzyme.site}
83
+ reverseSnipPosition={enzyme.bottomSnipOffset}
84
+ forwardSnipPosition={enzyme.topSnipOffset}
69
85
  />
70
86
  )}
71
- <br></br>
87
+ <br />
72
88
  {entities && !!entities.length && (
73
89
  <div>
74
90
  <DataTable
@@ -106,7 +122,7 @@ export default function SingleEnzymeCutsiteInfo({
106
122
  key={i}
107
123
  name={n}
108
124
  doNotShowCuts
109
- ></CutsiteTag>
125
+ />
110
126
  );
111
127
  })}
112
128
  </div>
@@ -117,14 +133,6 @@ export default function SingleEnzymeCutsiteInfo({
117
133
  );
118
134
  }
119
135
 
120
- const schema = {
121
- fields: [
122
- { path: "topSnipPosition", displayName: "Top Snip", type: "string" },
123
- { path: "position", type: "string" },
124
- { path: "strand", type: "string" }
125
- ]
126
- };
127
-
128
136
  // export default compose(
129
137
  // withEditorProps,
130
138
  // withRestrictionEnzymes
@@ -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
- <React.Fragment>
21
+ <>
22
22
  {additionalHeaderEls}
23
23
  <Comp {...rest} />
24
24
  {additionalFooterEls}
25
- </React.Fragment>
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
- const { width, height: heightFromDim } = dimensions;
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
- 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];
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
- const name = nameOrOverride.name || nameOrOverride;
81
- const Comp = nameOrOverride.Comp || allTabs[name];
82
- if (isProtein) {
83
- if (
84
- name === "translations" ||
85
- name === "orfs" ||
86
- name === "primers" ||
87
- name === "cutsites"
88
- ) {
89
- return null;
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
- const title = (() => {
93
- if (nameOrOverride.Comp) return name; //just use the user supplied name because this is a custom panel
94
- if (name === "orfs") return "ORFs";
95
- if (name === "cutsites") return "Cut Sites";
96
- return startCase(name);
97
- })();
98
- return (
99
- <Tab
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
- position: "relative"
134
+ display: "flex",
135
+ width,
136
+ height: heightToUse || 300,
137
+ zIndex: 10,
138
+ padding: 10
139
+ // paddingBottom: '31px',
126
140
  }}
127
141
  >
128
- {closePanelButton}
129
- <div
130
- className="ve-propertiesPanel"
131
- style={{
132
- display: "flex",
133
- width,
134
- height: heightToUse || 300,
135
- zIndex: 10,
136
- padding: 10
137
- // paddingBottom: '31px',
138
- }}
139
- >
140
- {propertiesTabs.length ? (
141
- <Tabs
142
- style={{ width }}
143
- renderActiveTabPanelOnly
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 }) => {
@@ -2,11 +2,11 @@ import React from "react";
2
2
  import { convertDnaCaretPositionOrRangeToAA } from "@teselagen/sequence-utils";
3
3
  import { convertRangeTo1Based } from "@teselagen/range-utils";
4
4
 
5
- export const sizeSchema = {
5
+ export const sizeSchema = isProtein => ({
6
6
  path: "size",
7
7
  type: "number",
8
- render: (val, _record, i, props) => {
9
- const record = props.isProtein
8
+ render: (val, _record) => {
9
+ const record = isProtein
10
10
  ? convertDnaCaretPositionOrRangeToAA(_record)
11
11
  : _record;
12
12
  const base1Range = convertRangeTo1Based(record);
@@ -14,7 +14,7 @@ export const sizeSchema = {
14
14
 
15
15
  return (
16
16
  <span>
17
- {props.isProtein ? Math.floor(val / 3) : val}{" "}
17
+ {isProtein ? Math.floor(val / 3) : val}{" "}
18
18
  <span style={{ fontSize: 10 }}>
19
19
  {hasJoinedLocations ? (
20
20
  record.locations.map((loc, i) => {
@@ -34,4 +34,4 @@ export const sizeSchema = {
34
34
  </span>
35
35
  );
36
36
  }
37
- };
37
+ });