725e90237508115d42656743ea35a6da01be4464
angie
  Wed May 29 18:49:14 2024 -0700
When multiple references are matched, we make multiple 'view single subtree' buttons so add serial number to their IDs to prevent broken clicks.  Also, apply MAX_SUBTREE_BUTTONS only when we're making individual buttons, not when we're making a dropdown to select the subtree.

diff --git src/hg/hgPhyloPlace/phyloPlace.c src/hg/hgPhyloPlace/phyloPlace.c
index 55a9244..d00d9d4 100644
--- src/hg/hgPhyloPlace/phyloPlace.c
+++ src/hg/hgPhyloPlace/phyloPlace.c
@@ -1494,31 +1494,34 @@
 {
 char buttonId[256];
 safef(buttonId, sizeof buttonId, "%s%d", idBase, ix+1);
 char buttonLabel[256];
 safef(buttonLabel, sizeof buttonLabel, "view subtree %d in Nextstrain", ix+1);
 struct dyString *dyMo = dyStringCreate("view subtree %d with %d of your sequences and %d other "
                                        "sequences from the phylogenetic tree for context",
                                        ix+1, userSampleCount, subtreeSize - userSampleCount);
 makeNextstrainButton(buttonId, jsonTns[ix], buttonLabel, dyMo->string);
 dyStringFree(&dyMo);
 }
 
 static void makeNsSingleTreeButton(struct tempName *tn)
 /* Make a button to view single subtree (with all uploaded samples) in Nextstrain. */
 {
-makeNextstrainButton("viewNextstrainSingleSubtree", tn,
+static int serial = 0;
+char buttonId[256];
+safef(buttonId, sizeof buttonId, "viewNextstrainSingleSubtree%d", serial++);
+makeNextstrainButton(buttonId, tn,
                      "view downsampled global tree in Nextstrain",
                      "view one subtree that includes all of your uploaded sequences plus "
                      SINGLE_SUBTREE_SIZE" randomly selected sequences from the global phylogenetic "
                      "tree for context");
 }
 
 char *microbeTraceHost()
 /* Return the MicrobeTrace hostname from an hg.conf param, or NULL if missing. Do not free result. */
 {
 return cfgOption("microbeTraceHost");
 }
 
 static char *microbeTraceUrlBase()
 /* Alloc & return the part of the MicrobeTrace URL before the JSON filename. */
 {
@@ -1617,31 +1620,31 @@
                           NEXTSTRAIN_URL_PARAMS, TRUE);
     puts("<br>");
     if (subtreeSize <= MAX_MICROBETRACE_SUBTREE_SIZE)
         {
         makeSubtreeJumpButton(subtreeDropdownName, "MicrobeTrace", microbeTraceUrlBase(),
                               MICROBETRACE_URL_PARAMS, FALSE);
         }
     else
         {
         cgiMakeOptionalButton("disabledMTButton", "MicrobeTrace", TRUE);
         printf(" (%d samples is too many to view in MicrobeTrace; maximum is %d)",
                subtreeSize, MAX_MICROBETRACE_SUBTREE_SIZE);
         }
     puts("</td>");
     }
-else if (nextstrainHost())
+else if (nextstrainHost() && slCount(subtreeInfoList) <= MAX_SUBTREE_BUTTONS)
     {
     // Nextstrain only: do the old row of subtree buttons
     puts("<td>");
     struct subtreeInfo *ti;
     int ix;
     for (ix = 0, ti = subtreeInfoList;  ti != NULL;  ti = ti->next, ix++)
         {
         int userSampleCount = slCount(ti->subtreeUserSampleIds);
         printf("&nbsp;");
         makeNextstrainButtonN("viewNextstrainTopRow", ix, userSampleCount, subtreeSize, jsonTns);
         }
     puts("</td>");
     }
 if (0 && isFasta)
     {
@@ -3456,44 +3459,41 @@
         treeToAuspiceJson(ti, org, refName, geneInfoList, gSeqWin, sampleMetadata, NULL,
                           results->samplePlacements, jsonTns[ix]->forCgi, source);
         // Add a link for every sample to this subtree, so the single-subtree JSON can
         // link to subtree JSONs
         char *subtreeUrl = nextstrainUrlFromTn(jsonTns[ix]);
         struct slName *sample;
         for (sample = ti->subtreeUserSampleIds;  sample != NULL;  sample = sample->next)
             hashAdd(sampleUrls, sample->name, subtreeUrl);
         }
     struct tempName *singleSubtreeJsonTn;
     AllocVar(singleSubtreeJsonTn);
     trashDirFile(singleSubtreeJsonTn, "ct", "singleSubtreeAuspice", ".json");
     treeToAuspiceJson(results->singleSubtreeInfo, org, refName, geneInfoList, gSeqWin, sampleMetadata,
                       sampleUrls, results->samplePlacements, singleSubtreeJsonTn->forCgi, source);
     reportTiming(&startTime, "make Auspice JSON");
-    struct subtreeInfo *subtreeInfoForButtons = results->subtreeInfoList;
-    if (subtreeCount > MAX_SUBTREE_BUTTONS)
-        subtreeInfoForButtons = NULL;
     char *dbSetting = phyloPlaceRefSetting(org, refName, "db");
     if (dbSetting)
         db = connectIfHub(cart, dbSetting);
     boolean canDoCustomTracks = (!subtreesOnly &&
                                  (sameString(db, refName) || isNotEmpty(dbSetting)));
     if (canDoCustomTracks)
         // Form submits subtree custom tracks to hgTracks
         printf("<form action='%s' name='resultsForm_%s' method=%s>\n\n",
                hgTracksName(), db, cartUsualString(cart, "formMethod", "POST"));
 
-    makeButtonRow(singleSubtreeJsonTn, jsonTns, subtreeInfoForButtons, subtreeSize, isFasta,
+    makeButtonRow(singleSubtreeJsonTn, jsonTns, results->subtreeInfoList, subtreeSize, isFasta,
                   canDoCustomTracks);
     printf("<p>If you have metadata you wish to display, click a 'view subtree in "
            "Nextstrain' button, and then you can drag on a CSV file to "
            "<a href='"NEXTSTRAIN_DRAG_DROP_DOC"' target=_blank>add it to the tree view</a>."
            "</p>\n");
     puts("<p><em>Note: "
          "The Nextstrain subtree views, and Download files below, are temporary files and will "
          "expire within two days.  "
          "Please download the Nextstrain subtree JSON files if you will want to view them "
          "again in the future.  The JSON files can be drag-dropped onto "
          "<a href='https://auspice.us/' target=_blank>https://auspice.us/</a>."
          "</em></p>");
 
     struct tempName *tsvTn = NULL, *sTsvTn = NULL;
     struct tempName *zipTn = makeSubtreeZipFile(results, jsonTns, singleSubtreeJsonTn,