@teselagen/ove 0.7.27 → 0.7.28

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 (304) hide show
  1. package/AASliver.js +187 -0
  2. package/AddLaddersDialog.js +82 -0
  3. package/AdditionalCutsiteInfoDialog.js +599 -0
  4. package/AlignmentView/Mismatches.d.ts +3 -3
  5. package/AlignmentVisibilityTool.js +105 -0
  6. package/AnnotationContainerHolder.js +20 -0
  7. package/AnnotationPositioner.js +27 -0
  8. package/AutoAnnotate.js +501 -0
  9. package/AutoAnnotateBpMatchingDialog.js +208 -0
  10. package/Axis.js +151 -0
  11. package/AxisNumbers.js +35 -0
  12. package/Browser.js +106 -0
  13. package/Caret.js +63 -0
  14. package/Chromatogram.js +293 -0
  15. package/CircularDnaSequence.js +73 -0
  16. package/CircularView/Labels/index.d.ts +1 -1
  17. package/CircularView/index.d.ts +0 -1
  18. package/CircularZoomMinimap.js +16 -0
  19. package/ColorPicker.js +30 -0
  20. package/CommandHotkeyHandler.js +44 -0
  21. package/CreateAnnotationsPage.d.ts +4 -4
  22. package/CreateAnnotationsPage.js +98 -0
  23. package/Cutsite.js +18 -0
  24. package/CutsiteProperties.js +176 -0
  25. package/CutsiteSelectionLayers.js +47 -0
  26. package/Cutsites.js +271 -0
  27. package/DeletionLayer.js +28 -0
  28. package/DigestTool/Ladder.d.ts +1 -1
  29. package/DropHandler.css +21 -0
  30. package/DropHandler.js +64 -0
  31. package/EditCaretPosition.js +234 -0
  32. package/EditTrackNameDialog.js +30 -0
  33. package/Feature.js +83 -0
  34. package/FeatureProperties.js +6 -0
  35. package/FillWindow.js +47 -0
  36. package/GenbankView.js +74 -0
  37. package/GeneralProperties.js +117 -0
  38. package/GenericAnnotationProperties.js +406 -0
  39. package/GlobalDialog.js +73 -0
  40. package/GlobalDialogUtils.js +110 -0
  41. package/GoToDialog.js +25 -0
  42. package/HorizontalPanelDragHandle.js +35 -0
  43. package/Keyboard.js +85 -0
  44. package/Labels.js +327 -0
  45. package/Ladder.css +20 -0
  46. package/Ladder.js +303 -0
  47. package/MeltingTemp.js +85 -0
  48. package/Menlo.ttf +0 -0
  49. package/Minimap.js +515 -0
  50. package/Mismatches.js +134 -0
  51. package/Monaco.ttf +0 -0
  52. package/MultipleSeqsDetectedOnImportDialog.js +74 -0
  53. package/Orf.js +109 -0
  54. package/OrfProperties.js +117 -0
  55. package/Orfs.js +35 -0
  56. package/PCRTool.js +179 -0
  57. package/PairwiseAlignmentView.js +68 -0
  58. package/Part.js +34 -0
  59. package/PartProperties.js +9 -0
  60. package/PassThrough.js +3 -0
  61. package/PerformantSelectionLayer.js +32 -0
  62. package/PinchHelper.js +24 -0
  63. package/PointedAnnotation.js +347 -0
  64. package/PositionAnnotationOnCircle.js +26 -0
  65. package/Primer.js +41 -0
  66. package/PrimerProperties.js +19 -0
  67. package/Reflex/index.d.ts +0 -1
  68. package/ReflexContainer.js +802 -0
  69. package/ReflexElement.js +160 -0
  70. package/ReflexEvents.js +77 -0
  71. package/ReflexSplitter.js +205 -0
  72. package/RenameSequenceDialog.js +7 -0
  73. package/RotateCircularViewSlider.js +93 -0
  74. package/RowView/index.d.ts +0 -1
  75. package/SelectDialog.js +150 -0
  76. package/SequenceName.js +15 -0
  77. package/SimpleCircularOrLinearView.js +381 -0
  78. package/SimpleOligoPreview.js +39 -0
  79. package/SingleEnzymeCutsiteInfo.js +139 -0
  80. package/ToolBar/ToolbarItem.d.ts +1 -3
  81. package/ToolbarItem.js +192 -0
  82. package/Translation.js +198 -0
  83. package/TranslationProperties.js +149 -0
  84. package/UncontrolledSliderWithPlusMinusBtns.css +5 -0
  85. package/UncontrolledSliderWithPlusMinusBtns.js +134 -0
  86. package/VeTopRightContainer.js +12 -0
  87. package/ZoomCircularViewSlider.js +62 -0
  88. package/ZoomLinearView.js +47 -0
  89. package/addAlignment.js +6 -0
  90. package/addMetaToActionCreators.js +12 -0
  91. package/addWrappedAddons.js +20 -0
  92. package/alignmentTool.js +503 -0
  93. package/alignments.js +379 -0
  94. package/annotationLabelVisibility.js +2 -0
  95. package/annotationSearchSelector.js +24 -0
  96. package/annotationTypes.js +35 -0
  97. package/annotationVisibility.js +196 -0
  98. package/annotationsToSupport.js +104 -0
  99. package/arrayToObjWithIds.js +17 -0
  100. package/arrayUtils.js +19 -0
  101. package/array_move.js +10 -0
  102. package/calculateTickMarkPositionsForGivenRange.js +47 -0
  103. package/caretPosition.js +27 -0
  104. package/cdsFeaturesSelector.js +9 -0
  105. package/charWidth.js +22 -0
  106. package/circular.js +19 -0
  107. package/circularSelector.js +4 -0
  108. package/clickAndDragUtils.js +576 -0
  109. package/coerceInitialValue.js +7 -0
  110. package/combineReducersDontIgnoreKeys.js +12 -0
  111. package/commandUtils.js +20 -0
  112. package/constants.js +2 -0
  113. package/copyOptions.js +34 -0
  114. package/createFragmentLines.js +120 -0
  115. package/createMergedDefaultStateReducer.js +30 -0
  116. package/createMetaAction.js +12 -0
  117. package/createSequenceInputPopup.js +290 -0
  118. package/createSequenceInputPopupStyle.css +87 -0
  119. package/createSimpleDialog.js +89 -0
  120. package/createYourOwnEnzyme.js +39 -0
  121. package/cutsiteLabelColorSelector.js +6 -0
  122. package/cutsiteTool.js +88 -0
  123. package/cutsitesByRangeSelector.js +5 -0
  124. package/cutsitesSelector.js +61 -0
  125. package/darkmode.css +98 -0
  126. package/defaultConfig.js +150 -0
  127. package/deletionLayers.js +36 -0
  128. package/description.js +21 -0
  129. package/digestTool.js +34 -0
  130. package/dnaToColor.js +17 -0
  131. package/downloadTool.js +39 -0
  132. package/draggableClassnames.js +5 -0
  133. package/drawAnnotations.js +440 -0
  134. package/drawDirectedPiePiece.js +142 -0
  135. package/editTool.js +49 -0
  136. package/editorSelector.js +2 -0
  137. package/editorUtils.js +205 -0
  138. package/estimateRowHeight.js +184 -0
  139. package/featureLengthsToHide.js +27 -0
  140. package/featureTool.js +34 -0
  141. package/features.js +19 -0
  142. package/featuresSelector.js +8 -0
  143. package/filteredCutsitesSelector.js +136 -0
  144. package/filteredFeaturesSelector.js +32 -0
  145. package/filteredPartsSelector.js +57 -0
  146. package/filteredPrimersSelector.js +27 -0
  147. package/filteredRestrictionEnzymesSelector.js +1 -0
  148. package/find.png +0 -0
  149. package/findTool.js +79 -0
  150. package/findToolConstants.js +1 -0
  151. package/frameTranslations.js +52 -0
  152. package/fullscreen.png +0 -0
  153. package/getAdditionalEnzymesSelector.js +46 -0
  154. package/getAngleForPositionMidpoint.js +3 -0
  155. package/getAnnotationClassnames.js +12 -0
  156. package/getAnnotationNameAndStartStopString.js +61 -0
  157. package/getBpsPerRow.js +19 -0
  158. package/getCutsiteLabelHeights.js +56 -0
  159. package/getGapMap.js +12 -0
  160. package/getGaps.js +27 -0
  161. package/getInternalLabel.js +40 -0
  162. package/getOveHotkeyDefs.js +12 -0
  163. package/getPairwiseOverviewLinearViewOptions.js +38 -0
  164. package/getRangeAnglesSpecial.js +12 -0
  165. package/getStructuredBases.js +97 -0
  166. package/getTrackFromEvent.js +25 -0
  167. package/getVisibleStartEnd.js +7 -0
  168. package/getXStartAndWidthFromNonCircularRange.js +12 -0
  169. package/getXStartAndWidthOfRangeWrtRow.js +27 -0
  170. package/getXStartAndWidthOfRowAnnotation.js +19 -0
  171. package/getYOffset.js +15 -0
  172. package/hoveredAnnotation.js +24 -0
  173. package/{html2canvas.esm--JN4fLQL.js → html2canvas.esm-DiGWN1gP.js} +187 -229
  174. package/{html2canvas.esm-B7d7VJmQ.cjs → html2canvas.esm-J1esNpMJ.cjs} +187 -229
  175. package/importTool.js +27 -0
  176. package/index.cjs.js +48165 -47142
  177. package/index.es.js +47699 -46676
  178. package/index.js +71 -0
  179. package/inlineFindTool.js +38 -0
  180. package/isElementInViewport.js +29 -0
  181. package/isEnzymeFilterAndSelector.js +1 -0
  182. package/isTargetWithinEl.js +6 -0
  183. package/labelLineIntensity.js +25 -0
  184. package/labelSize.js +23 -0
  185. package/ladderDefaults.js +25 -0
  186. package/lastSavedId.js +20 -0
  187. package/lineageLines.js +11 -0
  188. package/linear.png +0 -0
  189. package/makeStore.js +34 -0
  190. package/massageTickSpacing.js +19 -0
  191. package/materiallyAvailable.js +19 -0
  192. package/middleware.js +112 -0
  193. package/minimumOrfSize.js +24 -0
  194. package/minimumOrfSizeSelector.js +2 -0
  195. package/modalActions.js +3 -0
  196. package/moveCaret.js +58 -0
  197. package/name.js +19 -0
  198. package/normalizeAngle.js +3 -0
  199. package/normalizeAngleRange.js +9 -0
  200. package/oligoTool.js +30 -0
  201. package/onlyUpdateForKeysDeep.js +31 -0
  202. package/orfFrameToColorMap.js +10 -0
  203. package/orfTool.js +136 -0
  204. package/orfsSelector.js +15 -0
  205. package/ove.css +12107 -0
  206. package/package.json +6 -5
  207. package/panelsShown.js +294 -0
  208. package/partLengthsToHide.js +23 -0
  209. package/partOverhangs.js +6 -0
  210. package/partTagSearch.js +69 -0
  211. package/partTool.js +45 -0
  212. package/parts.js +19 -0
  213. package/partsSelector.js +8 -0
  214. package/pie.png +0 -0
  215. package/polarToSpecialCartesian.js +7 -0
  216. package/positionCutsites.js +6 -0
  217. package/prepareRowData.js +64 -0
  218. package/primerBases.js +221 -0
  219. package/primerLengthsToHide.js +27 -0
  220. package/primers.js +19 -0
  221. package/primersSelector.js +8 -0
  222. package/print.png +0 -0
  223. package/printTool.js +31 -0
  224. package/propertiesTool.js +40 -0
  225. package/proteinUtils.js +3 -0
  226. package/pureNoFunc.js +18 -0
  227. package/readOnly.js +25 -0
  228. package/redoTool.js +30 -0
  229. package/reflex-styles.css +128 -0
  230. package/reflex-styles.css.map +9 -0
  231. package/relaxLabelAngles.js +157 -0
  232. package/relaxLabels_DEPRECATED.js +105 -0
  233. package/replacementLayers.js +36 -0
  234. package/restrictionEnzymes.js +52 -0
  235. package/restrictionEnzymesSelector.js +34 -0
  236. package/rowviewContants.js +3 -0
  237. package/ruler.css +89 -0
  238. package/save.png +0 -0
  239. package/saveTool.js +44 -0
  240. package/searchLayersSelector.js +71 -0
  241. package/selectedAnnotations.js +89 -0
  242. package/selectedAnnotationsSelector.js +1 -0
  243. package/selectedCutsitesSelector.js +21 -0
  244. package/selectedPartTags.js +21 -0
  245. package/selectionLayer.js +25 -0
  246. package/selectors/annotationSearchSelector.d.ts +1 -1
  247. package/sequence.js +12 -0
  248. package/sequenceDataHistory.js +43 -0
  249. package/sequenceDataSelector.js +2 -0
  250. package/sequenceLengthSelector.js +5 -0
  251. package/sequenceSelector.js +4 -0
  252. package/sharedActionCreators.js +0 -0
  253. package/shouldFlipText.js +4 -0
  254. package/shouldRerender.js +27 -0
  255. package/showFileDialog.js +25 -0
  256. package/showGCContent.js +23 -0
  257. package/show_cut_sites.png +0 -0
  258. package/show_features.png +0 -0
  259. package/show_orfs.png +0 -0
  260. package/show_primers.png +0 -0
  261. package/simpleDialog.css +13 -0
  262. package/specialCutsiteFilterOptions.js +22 -0
  263. package/src/Editor/DropHandler.js +2 -1
  264. package/src/Editor/index.js +0 -2
  265. package/src/RowItem/StackedAnnotations/getStructuredBases.js +20 -6
  266. package/src/ToolBar/cutsiteTool.js +1 -1
  267. package/src/helperComponents/PropertiesDialog/TranslationProperties.js +2 -1
  268. package/style.css +3 -12100
  269. package/tagsToBoldSelector.js +2 -0
  270. package/toggle_views.svg +1 -0
  271. package/toolBar.js +23 -0
  272. package/translationSearchMatchesSelector.js +14 -0
  273. package/translations.js +20 -0
  274. package/translationsRawSelector.js +8 -0
  275. package/translationsSelector.js +137 -0
  276. package/typeField.js +24 -0
  277. package/undoTool.js +30 -0
  278. package/updateEditor.d.ts +1 -3
  279. package/updateEditor.js +200 -0
  280. package/updateLabelsForInViewFeatures.js +55 -0
  281. package/updateLabelsForInViewFeaturesCircView.js +41 -0
  282. package/updateTrackHelper.js +58 -0
  283. package/uppercaseSequenceMapFont.js +25 -0
  284. package/upsertDeleteActionGenerator.js +31 -0
  285. package/useAAColorType.js +8 -0
  286. package/useAdditionalOrfStartCodons.js +24 -0
  287. package/useAnnotationLimits.js +42 -0
  288. package/useChromatogramPrefs.js +31 -0
  289. package/useFormValue.js +7 -0
  290. package/useLadders.js +6 -0
  291. package/useMeltingTemp.js +7 -0
  292. package/useTmType.js +10 -0
  293. package/userDefinedHandlersAndOpts.js +61 -0
  294. package/utils/getAnnotationNameAndStartStopString.d.ts +1 -5
  295. package/utils/selectionLayer.d.ts +2 -2
  296. package/utils.js +37 -0
  297. package/versionHistory.js +26 -0
  298. package/versionHistoryTool.js +21 -0
  299. package/viewSubmenu.js +479 -0
  300. package/visibilityTool.js +39 -0
  301. package/withEditorInteractions/getBpsPerRow.d.ts +1 -3
  302. package/withHover.js +113 -0
  303. package/withRestrictionEnzymes.js +15 -0
  304. package/index.umd.js +0 -188322
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+
3
+ const AnnotationContainerHolder = function (props) {
4
+ return (
5
+ <div
6
+ className={props.className || "annotationContainer"}
7
+ width="100%"
8
+ style={{
9
+ height: props.containerHeight,
10
+ position: "relative",
11
+ display: "block",
12
+ marginTop: props.marginTop + props.extraMargin,
13
+ marginBottom: props.marginBottom
14
+ }}
15
+ >
16
+ {props.children}
17
+ </div>
18
+ );
19
+ };
20
+ export default AnnotationContainerHolder;
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+
3
+ class AnnotationPositioner extends React.PureComponent {
4
+ render() {
5
+ return (
6
+ <svg
7
+ data-y-offset={this.props.yOffset}
8
+ transform={this.props.transform || null}
9
+ height={`${Math.max(0, this.props.height)}px`}
10
+ className={
11
+ (this.props.className || "") + " veRowViewAnnotationPosition"
12
+ }
13
+ width={Math.max(0, this.props.width + 5)}
14
+ style={{
15
+ position: "absolute",
16
+ top: this.props.top,
17
+ left: this.props.left
18
+ }}
19
+ >
20
+ {this.props.children}
21
+ </svg>
22
+ );
23
+ }
24
+ }
25
+ export default AnnotationPositioner;
26
+
27
+ // key={'feature' + annotation.id + 'start:' + annotationRange.start}
@@ -0,0 +1,501 @@
1
+ /* eslint-disable jsx-a11y/anchor-is-valid */
2
+ /* eslint-disable jsx-a11y/anchor-has-content */
3
+ /* eslint-disable no-throw-literal */
4
+ import { unparse } from "papaparse";
5
+ import pluralize from "pluralize";
6
+ import { SubmissionError, reduxForm } from "redux-form";
7
+ import shortid from "shortid";
8
+ import CreateAnnotationsPage from "./CreateAnnotationsPage";
9
+ import { formName } from "./constants";
10
+ import { AutoAnnotateBpMatchingDialog } from "./AutoAnnotateBpMatchingDialog";
11
+ import {
12
+ parseCsvFile,
13
+ validateCSVRequiredHeaders,
14
+ validateCSVRow
15
+ } from "@teselagen/file-utils";
16
+ import downloadjs from "downloadjs";
17
+ import {
18
+ autoAnnotate,
19
+ convertApELikeRegexToRegex,
20
+ convertProteinSeqToDNAIupac,
21
+ getFeatureToColorMap,
22
+ getFeatureTypes
23
+ } from "@teselagen/sequence-utils";
24
+ import { hideDialog, showDialog } from "./GlobalDialogUtils";
25
+ import { compose } from "redux";
26
+ import {
27
+ DataTable,
28
+ DialogFooter,
29
+ FileUploadField,
30
+ InfoHelper,
31
+ showConfirmationDialog,
32
+ wrapDialog
33
+ } from "@teselagen/ui";
34
+ import { startCase } from "lodash-es";
35
+ import withEditorProps from "./withEditorProps";
36
+ import { useEffect, useState } from "react";
37
+ import { Colors, Tab, Tabs } from "@blueprintjs/core";
38
+ import { typeField } from "./helperComponents/PropertiesDialog/typeField";
39
+
40
+ export function autoAnnotateFeatures() {
41
+ showDialog({
42
+ ModalComponent: AutoAnnotateModal, //we want to use a ModalComponent here so our addon does not
43
+ props: {
44
+ annotationType: "feature"
45
+ }
46
+ });
47
+ }
48
+ export function autoAnnotateParts() {
49
+ showDialog({
50
+ ModalComponent: AutoAnnotateModal, //we want to use a ModalComponent here so our addon does not
51
+ props: {
52
+ annotationType: "part"
53
+ }
54
+ });
55
+ }
56
+ export function autoAnnotatePrimers() {
57
+ showDialog({
58
+ ModalComponent: AutoAnnotateModal, //we want to use a ModalComponent here so our addon does not
59
+ props: {
60
+ annotationType: "primer"
61
+ }
62
+ });
63
+ }
64
+
65
+ export const AutoAnnotateModal = compose(
66
+ wrapDialog(p => ({
67
+ canEscapeKeyClose: false,
68
+ title: `Auto Annotate ${startCase(pluralize(p.annotationType))}`
69
+ })),
70
+ withEditorProps,
71
+ reduxForm({ form: formName })
72
+ )(props => {
73
+ const {
74
+ sequenceData,
75
+ handleSubmit,
76
+ annotationType = "feature",
77
+ error,
78
+ getCustomAutoAnnotateList
79
+ } = props;
80
+ const [fileType, setSelectedImportType] = useState("csvFile");
81
+ const [newAnnotations, setNewAnns] = useState(false);
82
+ const [customAnnResponse, setCustomAnnResponse] = useState();
83
+ const [loadingCustomAnnList, setLoadingCustomAnnList] = useState();
84
+ useEffect(() => {
85
+ (async () => {
86
+ if (getCustomAutoAnnotateList) {
87
+ setLoadingCustomAnnList(true);
88
+ try {
89
+ const anns = await getCustomAutoAnnotateList(props);
90
+ setCustomAnnResponse(anns);
91
+ } catch (e) {
92
+ window.toastr.warning("Error loading custom annotation list");
93
+ console.error(`e:`, e);
94
+ } finally {
95
+ setLoadingCustomAnnList(false);
96
+ }
97
+ }
98
+ })();
99
+ // eslint-disable-next-line react-hooks/exhaustive-deps
100
+ }, []);
101
+ if (newAnnotations) {
102
+ return (
103
+ <CreateAnnotationsPage
104
+ {...props}
105
+ newAnnotations={newAnnotations}
106
+ ></CreateAnnotationsPage>
107
+ );
108
+ }
109
+ return (
110
+ <div className="bp3-dialog-body">
111
+ <Tabs
112
+ renderActiveTabPanelOnly
113
+ onChange={setSelectedImportType}
114
+ selectedTabId={fileType}
115
+ >
116
+ <Tab
117
+ panel={
118
+ <div>
119
+ <div>
120
+ Select a CSV file (
121
+ <a
122
+ onClick={() => {
123
+ const rows = [
124
+ {
125
+ name: `Example ${startCase(annotationType)} 1`,
126
+ description: "I'm a description",
127
+ sequence: `gatNNtacaggttt`,
128
+ ...(annotationType === "feature" && {
129
+ type: `cds`
130
+ }),
131
+ isRegex: false,
132
+ matchType: "dna"
133
+ },
134
+ {
135
+ name: `Example Protein ${startCase(annotationType)}`,
136
+ description: "I'm a description",
137
+ sequence: `APGSGTGGGSGSAPG`,
138
+ ...(annotationType === "feature" && {
139
+ type: `cds`
140
+ }),
141
+ isRegex: false,
142
+ matchType: "protein"
143
+ },
144
+ {
145
+ name: `Example ${startCase(annotationType)} 2`,
146
+ description: "I'm another description",
147
+ sequence: `gat.*tacccc.*aggttt`,
148
+ ...(annotationType === "feature" && {
149
+ type: `cds`
150
+ }),
151
+ isRegex: true,
152
+ matchType: "dna"
153
+ }
154
+ ];
155
+ const csv = unparse(rows);
156
+ // const blob = new Blob([convert(sequenceData)], { type: "text/plain" });
157
+ // const filename = `${sequenceData.name || "Untitled_Sequence"}.${fileExt}`;
158
+ // FileSaver.saveAs(blob, filename);
159
+ downloadjs(
160
+ csv,
161
+ `Example CSV Annotation Upload File.csv`,
162
+ "text/plain"
163
+ );
164
+ }}
165
+ >
166
+ download example
167
+ </a>
168
+ ) with the following columns:<br></br>
169
+ <br></br>
170
+ <div style={{ display: "flex" }}>
171
+ name,description,sequence,type,
172
+ <span style={{ display: "flex" }}>
173
+ isRegex &nbsp;
174
+ <InfoHelper
175
+ onClick={e => {
176
+ e.stopPropagation();
177
+ e.preventDefault();
178
+ showDialog({
179
+ ModalComponent: AutoAnnotateBpMatchingDialog
180
+ });
181
+ }}
182
+ content={
183
+ <span>
184
+ Any valid regexes allowed. Click for more info about
185
+ regex matching
186
+ </span>
187
+ }
188
+ ></InfoHelper>
189
+ </span>
190
+ ,matchType
191
+ </div>
192
+ <br></br>
193
+ {annotationType !== "feature" && (
194
+ <>
195
+ <i>Note: the "type" column is optional</i>
196
+ <br></br>
197
+ </>
198
+ )}
199
+ </div>
200
+ <FileUploadField
201
+ validateAgainstSchema={validateAgainstSchema}
202
+ name="csvFile"
203
+ fileLimit={1}
204
+ isRequired
205
+ accept=".csv"
206
+ ></FileUploadField>
207
+ </div>
208
+ }
209
+ id="csvFile"
210
+ title="CSV"
211
+ ></Tab>
212
+ <Tab
213
+ panel={
214
+ <div>
215
+ <div>
216
+ Select an ApE style features .txt file (
217
+ <a
218
+ onClick={() => {
219
+ downloadjs(
220
+ `T3 ATTAACCCTCACTAAAGGGA primer_bind cyan green 0 0
221
+ M13-fwd TGTAAAACGACGGCCAGT primer_bind cyan green 0 0
222
+ FRT GAAGTTCCTATTCTCTAGAAAGTATAGGAACTTC misc_recomb orchid pink 0 0`,
223
+ `Example APE Feature List Upload File.txt`,
224
+ "text/plain"
225
+ );
226
+ }}
227
+ >
228
+ download example
229
+ </a>
230
+ ):
231
+ </div>
232
+ <FileUploadField
233
+ fileLimit={1}
234
+ name="apeFile"
235
+ isRequired
236
+ accept=".txt"
237
+ ></FileUploadField>
238
+ {error && (
239
+ <div style={{ padding: 5, color: Colors.RED1 }}>{error}</div>
240
+ )}
241
+ </div>
242
+ }
243
+ id="apeFile"
244
+ title="ApE File"
245
+ ></Tab>
246
+ {getCustomAutoAnnotateList &&
247
+ (loadingCustomAnnList ? (
248
+ <Tab disabled title="Loading..."></Tab>
249
+ ) : (
250
+ customAnnResponse &&
251
+ customAnnResponse.list && (
252
+ <Tab
253
+ id="implementerDefined"
254
+ title={customAnnResponse.title || "Custom List"}
255
+ panel={
256
+ customAnnResponse.list.length ? (
257
+ <div>
258
+ <DataTable
259
+ isInfinite
260
+ formName={"customAnnsTable"}
261
+ schema={
262
+ annotationType === "feature"
263
+ ? customAnnsSchema
264
+ : customAnnsSchemaNoType
265
+ }
266
+ entities={customAnnResponse.list}
267
+ ></DataTable>
268
+ </div>
269
+ ) : (
270
+ <div>No Annotations Found</div>
271
+ )
272
+ }
273
+ ></Tab>
274
+ )
275
+ ))}
276
+ </Tabs>
277
+ <DialogFooter
278
+ hideModal={hideDialog}
279
+ disabled={
280
+ fileType === "implementerDefined" &&
281
+ !(
282
+ customAnnResponse &&
283
+ customAnnResponse.list &&
284
+ customAnnResponse.list.length
285
+ )
286
+ }
287
+ onClick={handleSubmit(async ({ apeFile, csvFile }) => {
288
+ let convertNonStandardTypes = false;
289
+ const annsToCheck = [];
290
+ try {
291
+ const validateRow = async (row, rowName) => {
292
+ const { type = "", sequence } = row;
293
+ let regexConvertedSeq;
294
+
295
+ if (annotationType === "feature") {
296
+ const cleanedType = getFeatureTypes().find(
297
+ t => t.toLowerCase() === type.toLowerCase()
298
+ );
299
+ if (!cleanedType) {
300
+ if (!convertNonStandardTypes) {
301
+ convertNonStandardTypes = await showConfirmationDialog({
302
+ cancelButtonText: "Stop Auto-Annotate",
303
+ text: `Detected that ${rowName} has a non-standard type of ${type}. We will assign it and all subsequent non-standard types to use the misc_feature type instead`
304
+ });
305
+ if (!convertNonStandardTypes) {
306
+ throw {
307
+ validationError: `${rowName} specifies the feature type ${type} which is not valid`
308
+ };
309
+ }
310
+ }
311
+ row.type = "misc_feature";
312
+ } else {
313
+ row.type = cleanedType;
314
+ }
315
+ }
316
+ if (!sequence) {
317
+ throw {
318
+ validationError: `${rowName} did not have a sequence`
319
+ };
320
+ }
321
+ if (row.isRegex && row.isRegex.toUpperCase() === "TRUE") {
322
+ try {
323
+ new RegExp(regexConvertedSeq); //just trying out whether the regexConvertedSeq will work as a valid regex
324
+ } catch (error) {
325
+ throw {
326
+ validationError: `${rowName} has an invalid sequence/regex. Please fix it manually.`
327
+ };
328
+ }
329
+ row.isRegex = true;
330
+ } else {
331
+ row.isRegex = undefined;
332
+ }
333
+ annsToCheck.push(row);
334
+ };
335
+ if (fileType === "implementerDefined") {
336
+ for (const [
337
+ // eslint-disable-next-line no-unused-vars
338
+ i,
339
+ // eslint-disable-next-line no-unused-vars
340
+ { name, sequence, matchType, type, isRegex }
341
+ ] of customAnnResponse.list.entries()) {
342
+ await validateRow(
343
+ {
344
+ name,
345
+ sequence,
346
+ matchType,
347
+ type,
348
+ isRegex: isRegex ? "TRUE" : "FALSE"
349
+ },
350
+ `Row ${i + 1} (${name})`
351
+ );
352
+ }
353
+ } else if (fileType === "csvFile") {
354
+ const csvHeaders = ["name", "description", "sequence"];
355
+ if (annotationType === "feature") {
356
+ csvHeaders.push("type");
357
+ }
358
+ csvHeaders.push("isRegex");
359
+ const {
360
+ data,
361
+ meta: { fields }
362
+ } = await parseCsvFile(csvFile[0]);
363
+ const error = validateCSVRequiredHeaders(fields, csvHeaders);
364
+ if (error) {
365
+ throw {
366
+ validationError: error
367
+ };
368
+ }
369
+
370
+ // eslint-disable-next-line no-unused-vars
371
+ for (const [index, row] of data.entries()) {
372
+ const error = validateCSVRow(row, csvHeaders, index);
373
+ if (error) {
374
+ throw {
375
+ validationError: error
376
+ };
377
+ }
378
+ await validateRow(row, `Row ${index + 1} (${row.name})`);
379
+ }
380
+ } else if (fileType === "apeFile") {
381
+ const { data } = await parseCsvFile(apeFile[0], {
382
+ header: false
383
+ });
384
+ // eslint-disable-next-line no-unused-vars
385
+ for (const [i, [name, sequence, type]] of data.entries()) {
386
+ await validateRow(
387
+ { name, sequence, type },
388
+ `Row ${i + 1} (${name})`
389
+ );
390
+ }
391
+ } else {
392
+ console.info(`we shouldn't be here!`);
393
+ console.info(`fileType:`, fileType);
394
+ }
395
+
396
+ if (!annsToCheck.length) {
397
+ return window.toastr.warning(
398
+ "No Annotations Detected on File. Please check that your file is in the correct format."
399
+ );
400
+ }
401
+ const annotationsToCheckById = {};
402
+ annsToCheck.forEach(ann => {
403
+ if (ann.matchType === "protein") {
404
+ ann.sequence = convertProteinSeqToDNAIupac(ann.sequence);
405
+ }
406
+ const id = shortid();
407
+ annotationsToCheckById[id] = {
408
+ ...ann,
409
+ sequence: ann.isRegex
410
+ ? ann.sequence
411
+ : convertApELikeRegexToRegex(ann.sequence),
412
+ id
413
+ };
414
+ });
415
+
416
+ const seqId = "placeholderId";
417
+ const { [seqId]: newAnns } = autoAnnotate({
418
+ seqsToAnnotateById: {
419
+ [seqId]: { ...sequenceData, id: seqId }
420
+ },
421
+ annotationsToCheckById
422
+ });
423
+
424
+ if (newAnns && newAnns.length) {
425
+ setNewAnns(
426
+ newAnns.map(a => {
427
+ const toRet = {
428
+ ...annotationsToCheckById[a.id],
429
+ ...a,
430
+ forward: a.strand !== -1,
431
+ id: shortid()
432
+ };
433
+ toRet.color =
434
+ toRet.color || getFeatureToColorMap()[toRet.type];
435
+ return toRet;
436
+ })
437
+ );
438
+ } else {
439
+ window.toastr.warning(
440
+ `No ${annotationType}s detected on sequence.`
441
+ );
442
+ }
443
+ } catch (error) {
444
+ console.error(`error:`, error);
445
+ if (error.validationError) {
446
+ throw new SubmissionError({ [fileType]: error.validationError });
447
+ } else {
448
+ window.toastr.error(
449
+ `Error annotating ${annotationType}(s). Double check your file to make sure it is valid!`
450
+ );
451
+ }
452
+ }
453
+ })}
454
+ text="Annotate"
455
+ ></DialogFooter>
456
+ </div>
457
+ );
458
+ });
459
+
460
+ if (!window._ove_addons) window._ove_addons = {};
461
+ window._ove_addons.autoAnnotateFeatures = autoAnnotateFeatures;
462
+ window._ove_addons.autoAnnotateParts = autoAnnotateParts;
463
+ window._ove_addons.autoAnnotatePrimers = autoAnnotatePrimers;
464
+
465
+ const customAnnsSchema = ["name", "sequence", typeField, "isRegex"];
466
+ const customAnnsSchemaNoType = ["name", "sequence", typeField, "isRegex"];
467
+
468
+ const validateAgainstSchema = {
469
+ fields: [
470
+ {
471
+ path: "name",
472
+ type: "string",
473
+ isRequired: true
474
+ },
475
+ {
476
+ path: "description",
477
+ type: "string"
478
+ },
479
+ {
480
+ path: "sequence",
481
+ type: "string",
482
+ isRequired: true
483
+ },
484
+ {
485
+ path: "type",
486
+ type: "dropdown",
487
+ values: getFeatureTypes(),
488
+ defaultValue: "misc_feature"
489
+ },
490
+ {
491
+ path: "isRegex",
492
+ type: "boolean"
493
+ },
494
+ {
495
+ path: "matchType",
496
+ type: "dropdown",
497
+ defaultValue: "dna",
498
+ values: ["dna", "protein"]
499
+ }
500
+ ]
501
+ };