ove-auto-annotate 0.0.5 → 0.0.8

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/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ # UI:
2
+ ![image](https://user-images.githubusercontent.com/2730609/125001643-013bf980-e008-11eb-9385-b834b8e9573f.png)
3
+
4
+ ![image](https://user-images.githubusercontent.com/2730609/125001747-38120f80-e008-11eb-9981-292cebba847d.png)
5
+
1
6
  # Usage:
2
7
 
3
8
  ```js
@@ -43,6 +48,9 @@ window.createVectorEditor(yourDomNodeHere, {
43
48
 
44
49
  # Passing a custom list of existing annotations to choose from:
45
50
 
51
+ ![image](https://user-images.githubusercontent.com/2730609/125001693-14e76000-e008-11eb-903b-e7f074a7747c.png)
52
+
53
+
46
54
  ```js
47
55
  async function getCustomAutoAnnotateList ({ annotationType, sequenceData }) { //annotationType = feature|part|oligo
48
56
  const dataToReturn = await fetch("/my/endpoint/here", { ...someParams }); //hit your endpoint here
package/es/index.js CHANGED
@@ -23,6 +23,7 @@ import { formName } from "./constants";
23
23
  import { AutoAnnotateBpMatchingDialog } from "./AutoAnnotateBpMatchingDialog";
24
24
  import { parseCsvFile, validateCSVRequiredHeaders, validateCSVRow } from "./fileUtils";
25
25
  import downloadjs from "downloadjs";
26
+ import { convertProteinSeqToDNAIupac } from "ve-sequence-utils";
26
27
  var _window$addOnGlobals = window.addOnGlobals,
27
28
  shortid = _window$addOnGlobals.shortid,
28
29
  FileUploadField = _window$addOnGlobals.FileUploadField,
@@ -32,8 +33,8 @@ var _window$addOnGlobals = window.addOnGlobals,
32
33
  pluralize = _window$addOnGlobals.pluralize,
33
34
  reduxForm = _window$addOnGlobals.reduxForm,
34
35
  SubmissionError = _window$addOnGlobals.SubmissionError,
35
- featureColors = _window$addOnGlobals.featureColors,
36
- FeatureTypes = _window$addOnGlobals.FeatureTypes,
36
+ getFeatureToColorMap = _window$addOnGlobals.getFeatureToColorMap,
37
+ getFeatureTypes = _window$addOnGlobals.getFeatureTypes,
37
38
  InfoHelper = _window$addOnGlobals.InfoHelper,
38
39
  showConfirmationDialog = _window$addOnGlobals.showConfirmationDialog,
39
40
  wrapDialog = _window$addOnGlobals.wrapDialog,
@@ -79,6 +80,7 @@ export function autoAnnotatePrimers() {
79
80
  }
80
81
  export var AutoAnnotateModal = compose(wrapDialog(function (p) {
81
82
  return {
83
+ canEscapeKeyClose: false,
82
84
  title: "Auto Annotate " + startCase(pluralize(p.annotationType))
83
85
  };
84
86
  }), withEditorProps, reduxForm({
@@ -164,24 +166,7 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
164
166
  onChange: setSelectedImportType,
165
167
  selectedTabId: fileType
166
168
  }, /*#__PURE__*/React.createElement(Tab, {
167
- panel: /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, "Select a CSV file with the following columns -", /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("div", {
168
- style: {
169
- display: "flex"
170
- }
171
- }, "name,description,sequence,type,", /*#__PURE__*/React.createElement("span", {
172
- style: {
173
- display: "flex"
174
- }
175
- }, "isRegex \xA0", /*#__PURE__*/React.createElement(InfoHelper, {
176
- onClick: function onClick(e) {
177
- e.stopPropagation();
178
- e.preventDefault();
179
- showDialog({
180
- ModalComponent: AutoAnnotateBpMatchingDialog
181
- });
182
- },
183
- content: true ? /*#__PURE__*/React.createElement("span", null, "Any valid regexes allowed. Click for more info about regex matching") : "All valid IUPAC bases allowed as well as a couple special characters. Click for more info"
184
- }))), /*#__PURE__*/React.createElement("br", null), annotationType !== "feature" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("i", null, "Note: the \"type\" column is optional"), /*#__PURE__*/React.createElement("br", null)), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("a", {
169
+ panel: /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, "Select a CSV file (", /*#__PURE__*/React.createElement("a", {
185
170
  onClick: function onClick() {
186
171
  var rows = [_extends({
187
172
  name: "Example " + startCase(annotationType) + " 1",
@@ -190,7 +175,17 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
190
175
  }, annotationType === "feature" && {
191
176
  type: "cds"
192
177
  }, {
193
- isRegex: false
178
+ isRegex: false,
179
+ matchType: "dna"
180
+ }), _extends({
181
+ name: "Example Protein " + startCase(annotationType),
182
+ description: "I'm a description",
183
+ sequence: "APGSGTGGGSGSAPG"
184
+ }, annotationType === "feature" && {
185
+ type: "cds"
186
+ }, {
187
+ isRegex: false,
188
+ matchType: "protein"
194
189
  }), _extends({
195
190
  name: "Example " + startCase(annotationType) + " 2",
196
191
  description: "I'm another description",
@@ -198,7 +193,8 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
198
193
  }, annotationType === "feature" && {
199
194
  type: "cds"
200
195
  }, {
201
- isRegex: true
196
+ isRegex: true,
197
+ matchType: "dna"
202
198
  })];
203
199
  var csv = unparse(rows); // const blob = new Blob([convert(sequenceData)], { type: "text/plain" });
204
200
  // const filename = `${sequenceData.name || "Untitled_Sequence"}.${fileExt}`;
@@ -206,7 +202,25 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
206
202
 
207
203
  downloadjs(csv, "Example CSV Annotation Upload File.csv", "text/plain");
208
204
  }
209
- }, "download example")), /*#__PURE__*/React.createElement(FileUploadField, {
205
+ }, "download example"), ") with the following columns:", /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("div", {
206
+ style: {
207
+ display: "flex"
208
+ }
209
+ }, "name,description,sequence,type,", /*#__PURE__*/React.createElement("span", {
210
+ style: {
211
+ display: "flex"
212
+ }
213
+ }, "isRegex \xA0", /*#__PURE__*/React.createElement(InfoHelper, {
214
+ onClick: function onClick(e) {
215
+ e.stopPropagation();
216
+ e.preventDefault();
217
+ showDialog({
218
+ ModalComponent: AutoAnnotateBpMatchingDialog
219
+ });
220
+ },
221
+ content: true ? /*#__PURE__*/React.createElement("span", null, "Any valid regexes allowed. Click for more info about regex matching") : "All valid IUPAC bases allowed as well as a couple special characters. Click for more info"
222
+ })), ",matchType"), /*#__PURE__*/React.createElement("br", null), annotationType !== "feature" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("i", null, "Note: the \"type\" column is optional"), /*#__PURE__*/React.createElement("br", null))), /*#__PURE__*/React.createElement(FileUploadField, {
223
+ validateAgainstSchema: validateAgainstSchema,
210
224
  name: "csvFile",
211
225
  fileLimit: 1,
212
226
  isRequired: true,
@@ -248,7 +262,7 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
248
262
  disabled: fileType === "implementerDefined" && !(customAnnResponse && customAnnResponse.list && customAnnResponse.list.length),
249
263
  onClick: handleSubmit( /*#__PURE__*/function () {
250
264
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref2) {
251
- var apeFile, csvFile, convertNonStandardTypes, annsToCheck, _seqsToAnnotateById, validateRow, _iterator, _step, _step$value, i, _step$value$, name, sequence, type, isRegex, csvHeaders, _yield$parseCsvFile, data, fields, _error, _iterator2, _step2, _step2$value, index, row, _error2, _yield$parseCsvFile2, _data, _iterator3, _step3, _step3$value, _i, _step3$value$, _name, _sequence, _type, annotationsToCheckById, seqId, _autoAnnotate, newAnns, _SubmissionError;
265
+ var apeFile, csvFile, convertNonStandardTypes, annsToCheck, _seqsToAnnotateById, validateRow, _iterator, _step, _step$value, i, _step$value$, name, sequence, matchType, type, isRegex, csvHeaders, _yield$parseCsvFile, data, fields, _error, _iterator2, _step2, _step2$value, index, row, _error2, _yield$parseCsvFile2, _data, _iterator3, _step3, _step3$value, _i, _step3$value$, _name, _sequence, _type, annotationsToCheckById, seqId, _autoAnnotate, newAnns, _SubmissionError;
252
266
 
253
267
  return _regeneratorRuntime.wrap(function _callee3$(_context3) {
254
268
  while (1) {
@@ -274,7 +288,7 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
274
288
  break;
275
289
  }
276
290
 
277
- cleanedType = FeatureTypes.find(function (t) {
291
+ cleanedType = getFeatureTypes().find(function (t) {
278
292
  return t.toLowerCase() === type.toLowerCase();
279
293
  });
280
294
 
@@ -381,11 +395,12 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
381
395
  }
382
396
 
383
397
  _step$value = _step.value, // eslint-disable-next-line no-unused-vars
384
- i = _step$value[0], _step$value$ = _step$value[1], name = _step$value$.name, sequence = _step$value$.sequence, type = _step$value$.type, isRegex = _step$value$.isRegex;
398
+ i = _step$value[0], _step$value$ = _step$value[1], name = _step$value$.name, sequence = _step$value$.sequence, matchType = _step$value$.matchType, type = _step$value$.type, isRegex = _step$value$.isRegex;
385
399
  _context3.next = 11;
386
400
  return validateRow({
387
401
  name: name,
388
402
  sequence: sequence,
403
+ matchType: matchType,
389
404
  type: type,
390
405
  isRegex: isRegex ? "TRUE" : "FALSE"
391
406
  }, "Row " + (i + 1) + " (" + name + ")");
@@ -515,6 +530,10 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
515
530
  case 57:
516
531
  annotationsToCheckById = {};
517
532
  annsToCheck.forEach(function (ann) {
533
+ if (ann.matchType === "protein") {
534
+ ann.sequence = convertProteinSeqToDNAIupac(ann.sequence);
535
+ }
536
+
518
537
  var id = shortid();
519
538
  annotationsToCheckById[id] = _extends({}, ann, {
520
539
  sequence: ann.isRegex ? ann.sequence : convertApELikeRegexToRegex(ann.sequence),
@@ -536,7 +555,7 @@ export var AutoAnnotateModal = compose(wrapDialog(function (p) {
536
555
  id: shortid()
537
556
  });
538
557
 
539
- toRet.color = toRet.color || featureColors[toRet.type];
558
+ toRet.color = toRet.color || getFeatureToColorMap()[toRet.type];
540
559
  return toRet;
541
560
  }));
542
561
  } else {
@@ -581,4 +600,31 @@ window._ove_addons.autoAnnotateFeatures = autoAnnotateFeatures;
581
600
  window._ove_addons.autoAnnotateParts = autoAnnotateParts;
582
601
  window._ove_addons.autoAnnotatePrimers = autoAnnotatePrimers;
583
602
  var customAnnsSchema = ["name", "sequence", typeField, "isRegex"];
584
- var customAnnsSchemaNoType = ["name", "sequence", typeField, "isRegex"];
603
+ var customAnnsSchemaNoType = ["name", "sequence", typeField, "isRegex"];
604
+ var validateAgainstSchema = {
605
+ fields: [{
606
+ path: "name",
607
+ type: "string",
608
+ isRequired: true
609
+ }, {
610
+ path: "description",
611
+ type: "string"
612
+ }, {
613
+ path: "sequence",
614
+ type: "string",
615
+ isRequired: true
616
+ }, {
617
+ path: "type",
618
+ type: "dropdown",
619
+ values: getFeatureTypes(),
620
+ defaultValue: "misc_feature"
621
+ }, {
622
+ path: "isRegex",
623
+ type: "boolean"
624
+ }, {
625
+ path: "matchType",
626
+ type: "dropdown",
627
+ defaultValue: "dna",
628
+ values: ["dna", "protein"]
629
+ }]
630
+ };
package/lib/index.js CHANGED
@@ -20,6 +20,8 @@ var _fileUtils = require("./fileUtils");
20
20
 
21
21
  var _downloadjs = _interopRequireDefault(require("downloadjs"));
22
22
 
23
+ var _veSequenceUtils = require("ve-sequence-utils");
24
+
23
25
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
24
26
 
25
27
  function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -43,8 +45,8 @@ var _window$addOnGlobals = window.addOnGlobals,
43
45
  pluralize = _window$addOnGlobals.pluralize,
44
46
  reduxForm = _window$addOnGlobals.reduxForm,
45
47
  SubmissionError = _window$addOnGlobals.SubmissionError,
46
- featureColors = _window$addOnGlobals.featureColors,
47
- FeatureTypes = _window$addOnGlobals.FeatureTypes,
48
+ getFeatureToColorMap = _window$addOnGlobals.getFeatureToColorMap,
49
+ getFeatureTypes = _window$addOnGlobals.getFeatureTypes,
48
50
  InfoHelper = _window$addOnGlobals.InfoHelper,
49
51
  showConfirmationDialog = _window$addOnGlobals.showConfirmationDialog,
50
52
  wrapDialog = _window$addOnGlobals.wrapDialog,
@@ -94,6 +96,7 @@ function autoAnnotatePrimers() {
94
96
 
95
97
  var AutoAnnotateModal = compose(wrapDialog(function (p) {
96
98
  return {
99
+ canEscapeKeyClose: false,
97
100
  title: "Auto Annotate " + startCase(pluralize(p.annotationType))
98
101
  };
99
102
  }), withEditorProps, reduxForm({
@@ -179,24 +182,7 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
179
182
  onChange: setSelectedImportType,
180
183
  selectedTabId: fileType
181
184
  }, /*#__PURE__*/React.createElement(Tab, {
182
- panel: /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, "Select a CSV file with the following columns -", /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("div", {
183
- style: {
184
- display: "flex"
185
- }
186
- }, "name,description,sequence,type,", /*#__PURE__*/React.createElement("span", {
187
- style: {
188
- display: "flex"
189
- }
190
- }, "isRegex \xA0", /*#__PURE__*/React.createElement(InfoHelper, {
191
- onClick: function onClick(e) {
192
- e.stopPropagation();
193
- e.preventDefault();
194
- showDialog({
195
- ModalComponent: _AutoAnnotateBpMatchingDialog.AutoAnnotateBpMatchingDialog
196
- });
197
- },
198
- content: true ? /*#__PURE__*/React.createElement("span", null, "Any valid regexes allowed. Click for more info about regex matching") : "All valid IUPAC bases allowed as well as a couple special characters. Click for more info"
199
- }))), /*#__PURE__*/React.createElement("br", null), annotationType !== "feature" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("i", null, "Note: the \"type\" column is optional"), /*#__PURE__*/React.createElement("br", null)), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("a", {
185
+ panel: /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, "Select a CSV file (", /*#__PURE__*/React.createElement("a", {
200
186
  onClick: function onClick() {
201
187
  var rows = [_extends({
202
188
  name: "Example " + startCase(annotationType) + " 1",
@@ -205,7 +191,17 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
205
191
  }, annotationType === "feature" && {
206
192
  type: "cds"
207
193
  }, {
208
- isRegex: false
194
+ isRegex: false,
195
+ matchType: "dna"
196
+ }), _extends({
197
+ name: "Example Protein " + startCase(annotationType),
198
+ description: "I'm a description",
199
+ sequence: "APGSGTGGGSGSAPG"
200
+ }, annotationType === "feature" && {
201
+ type: "cds"
202
+ }, {
203
+ isRegex: false,
204
+ matchType: "protein"
209
205
  }), _extends({
210
206
  name: "Example " + startCase(annotationType) + " 2",
211
207
  description: "I'm another description",
@@ -213,7 +209,8 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
213
209
  }, annotationType === "feature" && {
214
210
  type: "cds"
215
211
  }, {
216
- isRegex: true
212
+ isRegex: true,
213
+ matchType: "dna"
217
214
  })];
218
215
  var csv = (0, _papaparse.unparse)(rows); // const blob = new Blob([convert(sequenceData)], { type: "text/plain" });
219
216
  // const filename = `${sequenceData.name || "Untitled_Sequence"}.${fileExt}`;
@@ -221,7 +218,25 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
221
218
 
222
219
  (0, _downloadjs["default"])(csv, "Example CSV Annotation Upload File.csv", "text/plain");
223
220
  }
224
- }, "download example")), /*#__PURE__*/React.createElement(FileUploadField, {
221
+ }, "download example"), ") with the following columns:", /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("div", {
222
+ style: {
223
+ display: "flex"
224
+ }
225
+ }, "name,description,sequence,type,", /*#__PURE__*/React.createElement("span", {
226
+ style: {
227
+ display: "flex"
228
+ }
229
+ }, "isRegex \xA0", /*#__PURE__*/React.createElement(InfoHelper, {
230
+ onClick: function onClick(e) {
231
+ e.stopPropagation();
232
+ e.preventDefault();
233
+ showDialog({
234
+ ModalComponent: _AutoAnnotateBpMatchingDialog.AutoAnnotateBpMatchingDialog
235
+ });
236
+ },
237
+ content: true ? /*#__PURE__*/React.createElement("span", null, "Any valid regexes allowed. Click for more info about regex matching") : "All valid IUPAC bases allowed as well as a couple special characters. Click for more info"
238
+ })), ",matchType"), /*#__PURE__*/React.createElement("br", null), annotationType !== "feature" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("i", null, "Note: the \"type\" column is optional"), /*#__PURE__*/React.createElement("br", null))), /*#__PURE__*/React.createElement(FileUploadField, {
239
+ validateAgainstSchema: validateAgainstSchema,
225
240
  name: "csvFile",
226
241
  fileLimit: 1,
227
242
  isRequired: true,
@@ -263,7 +278,7 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
263
278
  disabled: fileType === "implementerDefined" && !(customAnnResponse && customAnnResponse.list && customAnnResponse.list.length),
264
279
  onClick: handleSubmit( /*#__PURE__*/function () {
265
280
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regenerator["default"].mark(function _callee3(_ref2) {
266
- var apeFile, csvFile, convertNonStandardTypes, annsToCheck, _seqsToAnnotateById, validateRow, _iterator, _step, _step$value, i, _step$value$, name, sequence, type, isRegex, csvHeaders, _yield$parseCsvFile, data, fields, _error, _iterator2, _step2, _step2$value, index, row, _error2, _yield$parseCsvFile2, _data, _iterator3, _step3, _step3$value, _i, _step3$value$, _name, _sequence, _type, annotationsToCheckById, seqId, _autoAnnotate, newAnns, _SubmissionError;
281
+ var apeFile, csvFile, convertNonStandardTypes, annsToCheck, _seqsToAnnotateById, validateRow, _iterator, _step, _step$value, i, _step$value$, name, sequence, matchType, type, isRegex, csvHeaders, _yield$parseCsvFile, data, fields, _error, _iterator2, _step2, _step2$value, index, row, _error2, _yield$parseCsvFile2, _data, _iterator3, _step3, _step3$value, _i, _step3$value$, _name, _sequence, _type, annotationsToCheckById, seqId, _autoAnnotate, newAnns, _SubmissionError;
267
282
 
268
283
  return _regenerator["default"].wrap(function _callee3$(_context3) {
269
284
  while (1) {
@@ -289,7 +304,7 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
289
304
  break;
290
305
  }
291
306
 
292
- cleanedType = FeatureTypes.find(function (t) {
307
+ cleanedType = getFeatureTypes().find(function (t) {
293
308
  return t.toLowerCase() === type.toLowerCase();
294
309
  });
295
310
 
@@ -396,11 +411,12 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
396
411
  }
397
412
 
398
413
  _step$value = _step.value, // eslint-disable-next-line no-unused-vars
399
- i = _step$value[0], _step$value$ = _step$value[1], name = _step$value$.name, sequence = _step$value$.sequence, type = _step$value$.type, isRegex = _step$value$.isRegex;
414
+ i = _step$value[0], _step$value$ = _step$value[1], name = _step$value$.name, sequence = _step$value$.sequence, matchType = _step$value$.matchType, type = _step$value$.type, isRegex = _step$value$.isRegex;
400
415
  _context3.next = 11;
401
416
  return validateRow({
402
417
  name: name,
403
418
  sequence: sequence,
419
+ matchType: matchType,
404
420
  type: type,
405
421
  isRegex: isRegex ? "TRUE" : "FALSE"
406
422
  }, "Row " + (i + 1) + " (" + name + ")");
@@ -530,6 +546,10 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
530
546
  case 57:
531
547
  annotationsToCheckById = {};
532
548
  annsToCheck.forEach(function (ann) {
549
+ if (ann.matchType === "protein") {
550
+ ann.sequence = (0, _veSequenceUtils.convertProteinSeqToDNAIupac)(ann.sequence);
551
+ }
552
+
533
553
  var id = shortid();
534
554
  annotationsToCheckById[id] = _extends({}, ann, {
535
555
  sequence: ann.isRegex ? ann.sequence : convertApELikeRegexToRegex(ann.sequence),
@@ -551,7 +571,7 @@ var AutoAnnotateModal = compose(wrapDialog(function (p) {
551
571
  id: shortid()
552
572
  });
553
573
 
554
- toRet.color = toRet.color || featureColors[toRet.type];
574
+ toRet.color = toRet.color || getFeatureToColorMap()[toRet.type];
555
575
  return toRet;
556
576
  }));
557
577
  } else {
@@ -597,4 +617,31 @@ window._ove_addons.autoAnnotateFeatures = autoAnnotateFeatures;
597
617
  window._ove_addons.autoAnnotateParts = autoAnnotateParts;
598
618
  window._ove_addons.autoAnnotatePrimers = autoAnnotatePrimers;
599
619
  var customAnnsSchema = ["name", "sequence", typeField, "isRegex"];
600
- var customAnnsSchemaNoType = ["name", "sequence", typeField, "isRegex"];
620
+ var customAnnsSchemaNoType = ["name", "sequence", typeField, "isRegex"];
621
+ var validateAgainstSchema = {
622
+ fields: [{
623
+ path: "name",
624
+ type: "string",
625
+ isRequired: true
626
+ }, {
627
+ path: "description",
628
+ type: "string"
629
+ }, {
630
+ path: "sequence",
631
+ type: "string",
632
+ isRequired: true
633
+ }, {
634
+ path: "type",
635
+ type: "dropdown",
636
+ values: getFeatureTypes(),
637
+ defaultValue: "misc_feature"
638
+ }, {
639
+ path: "isRegex",
640
+ type: "boolean"
641
+ }, {
642
+ path: "matchType",
643
+ type: "dropdown",
644
+ defaultValue: "dna",
645
+ values: ["dna", "protein"]
646
+ }]
647
+ };
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "ove-auto-annotate",
3
- "version": "0.0.5",
3
+ "version": "0.0.8",
4
4
  "scripts": {
5
5
  "build": "nwb build-react-component --copy-files --no-demo",
6
- "prepublish": "npm run build"
6
+ "prepublishOnly": "npm run build"
7
7
  },
8
8
  "dependencies": {
9
- "downloadjs": "^1.4.7",
10
9
  "papaparse": "^5.3.1"
11
10
  },
12
11
  "devDependencies": {
package/src/index.js CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  validateCSVRow
12
12
  } from "./fileUtils";
13
13
  import downloadjs from "downloadjs";
14
+ import { convertProteinSeqToDNAIupac } from "ve-sequence-utils";
14
15
 
15
16
  const {
16
17
  shortid,
@@ -21,8 +22,8 @@ const {
21
22
  pluralize,
22
23
  reduxForm,
23
24
  SubmissionError,
24
- featureColors,
25
- FeatureTypes,
25
+ getFeatureToColorMap,
26
+ getFeatureTypes,
26
27
  InfoHelper,
27
28
  showConfirmationDialog,
28
29
  wrapDialog,
@@ -68,6 +69,7 @@ export function autoAnnotatePrimers() {
68
69
 
69
70
  export const AutoAnnotateModal = compose(
70
71
  wrapDialog((p) => ({
72
+ canEscapeKeyClose: false,
71
73
  title: `Auto Annotate ${startCase(pluralize(p.annotationType))}`
72
74
  })),
73
75
  withEditorProps,
@@ -120,41 +122,7 @@ export const AutoAnnotateModal = compose(
120
122
  panel={
121
123
  <div>
122
124
  <div>
123
- Select a CSV file with the following columns -<br></br>
124
- <br></br>
125
- <div style={{ display: "flex" }}>
126
- name,description,sequence,type,
127
- <span style={{ display: "flex" }}>
128
- isRegex &nbsp;
129
- <InfoHelper
130
- onClick={(e) => {
131
- e.stopPropagation();
132
- e.preventDefault();
133
- showDialog({
134
- ModalComponent: AutoAnnotateBpMatchingDialog
135
- });
136
- }}
137
- content={
138
- true ? (
139
- <span>
140
- Any valid regexes allowed. Click for more info about
141
- regex matching
142
- </span>
143
- ) : (
144
- `All valid IUPAC bases allowed as well as a couple special characters. Click for more info`
145
- )
146
- }
147
- ></InfoHelper>
148
- </span>
149
- </div>
150
- <br></br>
151
- {annotationType !== "feature" && (
152
- <React.Fragment>
153
- <i>Note: the "type" column is optional</i>
154
- <br></br>
155
- </React.Fragment>
156
- )}
157
- <br></br>
125
+ Select a CSV file (
158
126
  <a
159
127
  onClick={() => {
160
128
  const rows = [
@@ -165,7 +133,18 @@ export const AutoAnnotateModal = compose(
165
133
  ...(annotationType === "feature" && {
166
134
  type: `cds`
167
135
  }),
168
- isRegex: false
136
+ isRegex: false,
137
+ matchType: "dna"
138
+ },
139
+ {
140
+ name: `Example Protein ${startCase(annotationType)}`,
141
+ description: "I'm a description",
142
+ sequence: `APGSGTGGGSGSAPG`,
143
+ ...(annotationType === "feature" && {
144
+ type: `cds`
145
+ }),
146
+ isRegex: false,
147
+ matchType: "protein"
169
148
  },
170
149
  {
171
150
  name: `Example ${startCase(annotationType)} 2`,
@@ -174,7 +153,8 @@ export const AutoAnnotateModal = compose(
174
153
  ...(annotationType === "feature" && {
175
154
  type: `cds`
176
155
  }),
177
- isRegex: true
156
+ isRegex: true,
157
+ matchType: "dna"
178
158
  }
179
159
  ];
180
160
  const csv = unparse(rows);
@@ -190,8 +170,44 @@ export const AutoAnnotateModal = compose(
190
170
  >
191
171
  download example
192
172
  </a>
173
+ ) with the following columns:<br></br>
174
+ <br></br>
175
+ <div style={{ display: "flex" }}>
176
+ name,description,sequence,type,
177
+ <span style={{ display: "flex" }}>
178
+ isRegex &nbsp;
179
+ <InfoHelper
180
+ onClick={(e) => {
181
+ e.stopPropagation();
182
+ e.preventDefault();
183
+ showDialog({
184
+ ModalComponent: AutoAnnotateBpMatchingDialog
185
+ });
186
+ }}
187
+ content={
188
+ true ? (
189
+ <span>
190
+ Any valid regexes allowed. Click for more info about
191
+ regex matching
192
+ </span>
193
+ ) : (
194
+ `All valid IUPAC bases allowed as well as a couple special characters. Click for more info`
195
+ )
196
+ }
197
+ ></InfoHelper>
198
+ </span>
199
+ ,matchType
200
+ </div>
201
+ <br></br>
202
+ {annotationType !== "feature" && (
203
+ <React.Fragment>
204
+ <i>Note: the "type" column is optional</i>
205
+ <br></br>
206
+ </React.Fragment>
207
+ )}
193
208
  </div>
194
209
  <FileUploadField
210
+ validateAgainstSchema={validateAgainstSchema}
195
211
  name="csvFile"
196
212
  fileLimit={1}
197
213
  isRequired
@@ -285,7 +301,7 @@ FRT GAAGTTCCTATTCTCTAGAAAGTATAGGAACTTC misc_recomb orchid pink 0 0`,
285
301
  let regexConvertedSeq;
286
302
 
287
303
  if (annotationType === "feature") {
288
- const cleanedType = FeatureTypes.find(
304
+ const cleanedType = getFeatureTypes().find(
289
305
  (t) => t.toLowerCase() === type.toLowerCase()
290
306
  );
291
307
  if (!cleanedType) {
@@ -329,10 +345,16 @@ FRT GAAGTTCCTATTCTCTAGAAAGTATAGGAACTTC misc_recomb orchid pink 0 0`,
329
345
  // eslint-disable-next-line no-unused-vars
330
346
  i,
331
347
  // eslint-disable-next-line no-unused-vars
332
- { name, sequence, type, isRegex }
348
+ { name, sequence, matchType, type, isRegex }
333
349
  ] of customAnnResponse.list.entries()) {
334
350
  await validateRow(
335
- { name, sequence, type, isRegex: isRegex ? "TRUE" : "FALSE" },
351
+ {
352
+ name,
353
+ sequence,
354
+ matchType,
355
+ type,
356
+ isRegex: isRegex ? "TRUE" : "FALSE"
357
+ },
336
358
  `Row ${i + 1} (${name})`
337
359
  );
338
360
  }
@@ -386,6 +408,9 @@ FRT GAAGTTCCTATTCTCTAGAAAGTATAGGAACTTC misc_recomb orchid pink 0 0`,
386
408
  }
387
409
  const annotationsToCheckById = {};
388
410
  annsToCheck.forEach((ann) => {
411
+ if (ann.matchType === "protein") {
412
+ ann.sequence = convertProteinSeqToDNAIupac(ann.sequence);
413
+ }
389
414
  const id = shortid();
390
415
  annotationsToCheckById[id] = {
391
416
  ...ann,
@@ -413,7 +438,8 @@ FRT GAAGTTCCTATTCTCTAGAAAGTATAGGAACTTC misc_recomb orchid pink 0 0`,
413
438
  forward: a.strand !== -1,
414
439
  id: shortid()
415
440
  };
416
- toRet.color = toRet.color || featureColors[toRet.type];
441
+ toRet.color =
442
+ toRet.color || getFeatureToColorMap()[toRet.type];
417
443
  return toRet;
418
444
  })
419
445
  );
@@ -446,3 +472,38 @@ window._ove_addons.autoAnnotatePrimers = autoAnnotatePrimers;
446
472
 
447
473
  const customAnnsSchema = ["name", "sequence", typeField, "isRegex"];
448
474
  const customAnnsSchemaNoType = ["name", "sequence", typeField, "isRegex"];
475
+
476
+ const validateAgainstSchema = {
477
+ fields: [
478
+ {
479
+ path: "name",
480
+ type: "string",
481
+ isRequired: true
482
+ },
483
+ {
484
+ path: "description",
485
+ type: "string"
486
+ },
487
+ {
488
+ path: "sequence",
489
+ type: "string",
490
+ isRequired: true
491
+ },
492
+ {
493
+ path: "type",
494
+ type: "dropdown",
495
+ values: getFeatureTypes(),
496
+ defaultValue: "misc_feature"
497
+ },
498
+ {
499
+ path: "isRegex",
500
+ type: "boolean"
501
+ },
502
+ {
503
+ path: "matchType",
504
+ type: "dropdown",
505
+ defaultValue: "dna",
506
+ values: ["dna", "protein"]
507
+ }
508
+ ]
509
+ };