327ff85429911eaa58790c850bc5e83ad4b1548f
angie
  Wed May 26 19:33:36 2021 -0700
User request (HT Krisandra Allen, WA DOH): add a box in which sequence names/IDs can be pasted instead of uploaded from file.

diff --git src/hg/hgPhyloPlace/hgPhyloPlace.c src/hg/hgPhyloPlace/hgPhyloPlace.c
index dd8661e..1ec2a3c 100644
--- src/hg/hgPhyloPlace/hgPhyloPlace.c
+++ src/hg/hgPhyloPlace/hgPhyloPlace.c
@@ -16,30 +16,31 @@
 #include "net.h"
 #include "options.h"
 #include "phyloPlace.h"
 #include "portable.h"
 #include "trackLayout.h"
 #include "udc.h"
 #include "web.h"
 
 /* Global Variables */
 struct cart *cart = NULL;      // CGI and other variables
 struct hash *oldVars = NULL;   // Old contents of cart before it was updated by CGI
 boolean measureTiming = FALSE; // Print out how long things take
 char *leftLabelWidthForLongNames = "55";// Leave plenty of room for tree and long virus strain names
 
 #define seqFileVar "sarsCoV2File"
+#define pastedIdVar "namesOrIds"
 #define remoteFileVar "remoteFile"
 
 static struct lineFile *lineFileFromFileInput(struct cart *cart, char *fileVar)
 /* Return a lineFile on data from an uploaded file with cart variable name fileVar.
  * If the file is binary, attempt to decompress it.  Return NULL if no data are found
  * or if there is a problem decompressing binary data.  If retFileName is not NULL */
 {
 struct lineFile *lf = NULL;
 // Depending on whether the file is plain text or binary, different cart variables are present.
 char *filePlainContents = cartOptionalString(cart, fileVar);
 char cartVar[2048];
 safef(cartVar, sizeof cartVar, "%s__binary", fileVar);
 char *fileBinaryCoords = cartOptionalString(cart, cartVar);
 // Also get the file name for error reporting.
 safef(cartVar, sizeof cartVar, "%s__filename", fileVar);
@@ -138,33 +139,43 @@
 
 // Container for bootstrap grid layout
 puts(
 "<div class='container-fluid'>\n");
 }
 
 static void newPageEndStuff()
 {
 puts(
 "</div>");
 jsIncludeFile("utils.js", NULL);
 webIncludeFile("inc/gbFooter.html");
 webEndJWest();
 }
 
-#define CHECK_FILE_INPUT_JS(varName) "{ var $fileInput = $('input[name="varName"]');  " \
-    "if ($fileInput && $fileInput[0] && $fileInput[0].files && !$fileInput[0].files.length) {" \
-      " alert('Please choose a file first, then click the upload button.');" \
+#define CHECK_FILE_OR_PASTE_INPUT_JS(fileVarName, pasteVarName) \
+    "{ var $fileInput = $('input[name="fileVarName"]');" \
+    "  var $pasteInput = $('textarea[name="pasteVarName"]');" \
+    "  if ($fileInput && $fileInput[0] && $fileInput[0].files && !$fileInput[0].files.length &&" \
+    "      $pasteInput && !$pasteInput.val()) {" \
+    "     alert('Please either choose a file or paste in sequence names/IDs first, ' +" \
+    "           'and then click the upload button.');" \
+    "     return false; " \
+    "   } else if ($fileInput && $fileInput[0] && $fileInput[0].files && " \
+    "              !!$fileInput[0].files.length &&" \
+    "              $pasteInput && !!$pasteInput.val()) {" \
+    "     alert('Sorry, unable to process both a file and pasted-in sequence names/IDs at the ' +" \
+    "            'same time.  Please clear one or the other and then click the upload button.');" \
     "     return false; " \
     "   } else { loadingImage.run(); return true; } }"
 
 static void inputForm()
 /* Ask the user for FASTA or VCF. */
 {
 printf("<form action='%s' name='mainForm' method=POST enctype='multipart/form-data'>\n\n",
        "hgPhyloPlace");
 cartSaveSession(cart);
 char *db = "wuhCor1";
 cgiMakeHiddenVar("db", db);
 puts("  <div class='gbControl col-md-12'>");
 puts("<div class='readableWidth'>");
 puts("<p>Upload your SARS-CoV-2 sequence (FASTA or VCF file) to find the most similar\n"
      "complete, high-coverage samples from \n"
@@ -218,47 +229,50 @@
      "<p>In order to enable rapid progress in SARS-CoV-2 research and genomic contact tracing,\n"
      "please share your SARS-CoV-2 sequences by submitting them to an "
      "<a href='https://ncbiinsights.ncbi.nlm.nih.gov/2020/08/17/insdc-covid-data-sharing/' "
      "target=_blank>INSDC</a> member institution\n"
      "(<a href='https://submit.ncbi.nlm.nih.gov/sarscov2/' target=_blank>NCBI</a>,\n"
      "<a href='https://www.covid19dataportal.org/submit-data' target=_blank>EMBL-EBI</a>\n"
      "or <a href='https://www.ddbj.nig.ac.jp/ddbj/websub.html' target=_blank>DDBJ</a>)\n"
      "and <a href='https://www.gisaid.org/' target=_blank>GISAID</a>.\n"
      "</p>\n");
 puts("</div>");
 puts("  </div>");
 puts("  <div class='gbControl col-md-12'>");
 printf("<p>Select your FASTA, VCF or list of sequence names/IDs: ");
 printf("<input type='file' id='%s' name='%s'>",
        seqFileVar, seqFileVar);
+printf("</p><p>or paste in sequence names/IDs:<br>\n");
+cgiMakeTextArea(pastedIdVar, "", 10, 70);
 struct treeChoices *treeChoices = loadTreeChoices(db);
 if (treeChoices)
     {
     puts("</p><p>");
     printf("Phylogenetic tree version: ");
     char *phyloPlaceTree = cartOptionalString(cart, "phyloPlaceTree");
     cgiMakeDropListWithVals("phyloPlaceTree", treeChoices->descriptions, treeChoices->protobufFiles,
                             treeChoices->count, phyloPlaceTree);
     }
 puts("</p><p>");
 printf("Number of samples per subtree showing sample placement: ");
 int subtreeSize = cartUsualInt(cart, "subtreeSize", 50);
 cgiMakeIntVarWithLimits("subtreeSize", subtreeSize,
                         "Number of samples in subtree showing neighborhood of placement",
                         5, 10, 5000);
 puts("</p><p>");
-cgiMakeOnClickSubmitButton(CHECK_FILE_INPUT_JS(seqFileVar), "submit", "upload");
+cgiMakeOnClickSubmitButton(CHECK_FILE_OR_PASTE_INPUT_JS(seqFileVar, pastedIdVar),
+                           "submit", "upload");
 puts("</p>");
 // Add a loading image to reassure people that we're working on it when they upload a big file
 printf("<div><img id='loadingImg' src='../images/loading.gif' />\n");
 printf("<span id='loadingMsg'></span></div>\n");
 jsInline("$(document).ready(function() {\n"
          "    loadingImage.init($('#loadingImg'), $('#loadingMsg'), "
          "'<p style=\"color: red; font-style: italic;\">Uploading and processing your sequences "
          "may take some time. Please leave this window open while we work on your sequences.</p>');"
          "});\n");
 
 puts("  </div>");
 puts("</form>");
 }
 
 static void exampleForm()
@@ -425,30 +439,36 @@
 measureTiming = cartUsualBoolean(cart, "measureTiming", measureTiming);
 
 char *submitLabel = cgiOptionalString("submit");
 if (submitLabel && sameString(submitLabel, "try example"))
     {
     char *exampleFile = phyloPlaceDbSettingPath(db, "exampleFile");
     struct lineFile *lf = lineFileOpen(exampleFile, TRUE);
     resultsPage(db, lf);
     }
 else if (cgiOptionalString(remoteFileVar))
     {
     char *url = cgiString(remoteFileVar);
     struct lineFile *lf = netLineFileOpen(url);
     resultsPage(db, lf);
     }
+else if (isNotEmpty(trimSpaces(cgiOptionalString(pastedIdVar))))
+    {
+    char *pastedIds = cgiString(pastedIdVar);
+    struct lineFile *lf = lineFileOnString("pasted names/IDs", TRUE, pastedIds);
+    resultsPage(db, lf);
+    }
 else if (cgiOptionalString(seqFileVar) || cgiOptionalString(seqFileVar "__filename"))
     {
     struct lineFile *lf = lineFileFromFileInput(cart, seqFileVar);
     resultsPage(db, lf);
     }
 else
     mainPage(db);
 }
 
 #define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
 
 static void addLdLibraryPath()
 /* usher requires a tbb lib that is not in the yum package tbb-devel, so for now
  * I'm adding the .so files to hgPhyloPlaceData.  Set environment variable LD_LIBRARY_PATH
  * to pick them up from there. */
@@ -462,24 +482,25 @@
     char cwd[4096];
     getcwd(cwd, sizeof cwd);
     dyStringPrintf(dy, "%s/%s", cwd, PHYLOPLACE_DATA_DIR);
     }
 if (isNotEmpty(oldValue))
     dyStringPrintf(dy, ":%s", oldValue);
 setenv(LD_LIBRARY_PATH, dyStringCannibalize(&dy), TRUE);
 }
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 /* Null terminated list of CGI Variables we don't want to save to cart */
 char *excludeVars[] = {"submit", "Submit",
                        seqFileVar, seqFileVar "__binary", seqFileVar "__filename",
+                       pastedIdVar,
                        NULL};
 long enteredMainTime = clock1000();
 cgiSpoof(&argc, argv);
 oldVars = hashNew(10);
 addLdLibraryPath();
 cartEmptyShellNoContent(doMiddle, hUserCookie(), excludeVars, oldVars);
 cgiExitTime("hgPhyloPlace", enteredMainTime);
 return 0;
 }