a48e4a31e870414b9ed4a9731bf4ca694e6ff008
chmalee
  Wed Oct 30 11:36:15 2019 -0700
Fixes to hub searching after code review: Angie noticed that links were broken due to a bug, but it turns out they were broken in a much bigger way as subtrack search hits were not linking out to the right parent tracks. This has been fixed by adding a new column to the hubSearchText table to encode the parent type of the parent tracks (comp, super, etc), and then building the links the correct way, refs #24338

diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c
index 287e30f..1860562 100644
--- src/hg/hgHubConnect/hgHubConnect.c
+++ src/hg/hgHubConnect/hgHubConnect.c
@@ -789,105 +789,129 @@
 
 
 struct tdbOutputStructure *hstToTdbOutput(struct hubSearchText *hst, struct genomeOutputStructure *genomeOut, struct trackHub *hub)
 /* Convert a hubSearchText entry to a (list of) tdbOutputStructure(s) */
 {
 struct tdbOutputStructure *tdbOut = hashFindVal(genomeOut->tdbOutHash, hst->track);
 if (tdbOut == NULL)
     {
     genomeOut->trackCount++;
     AllocVar(tdbOut);
     tdbOut->shortLabel = dyStringNew(0);
     tdbOut->metaTags = dyStringNew(0);
     tdbOut->descriptionMatch = dyStringNew(0);
     tdbOut->configUrl = dyStringNew(0);
     dyStringPrintf(tdbOut->shortLabel, "%s", hst->label);
-
+    char *hubId = hubNameFromUrl(hub->url);
     if (isNotEmpty(hst->parents))
         {
         // hst->parents is a comma-sep list like "track1","track1Label","track2","track2Label"
         int i;
         int parentCount;
+        int parentTypesCount;
         char *parentTrack = NULL;
         char *parentLabel = NULL;
         char *parentTrackLabels[16]; // 2 slots per parent, can tracks nest more than 8 deep?
+        char *parentTypes[16]; // the types of parents, "comp", "super", "view", "other" for each track in parentTrackLabels
         struct tdbOutputStructure *parentTdbOut = NULL;
         struct tdbOutputStructure *savedParent = NULL;
 
         parentCount = chopByCharRespectDoubleQuotes(cloneString(hst->parents), ',', parentTrackLabels, sizeof(parentTrackLabels));
+        parentTypesCount = chopCommas(cloneString(hst->parentTypes), parentTypes);
         if (parentCount == 0 || parentCount % 2 != 0)
             {
             errAbort("error parsing hubSearchText->parents for %s.%s in hub: '%s'",
                 genomeOut->genomeName, hst->track, hub->url);
             }
-        dyStringPrintf(tdbOut->configUrl, "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s&hgsid=%s&%s",
-            hub->url, genomeOut->genomeName, parentTrackLabels[0], cartSessionId(cart),
-            genomeOut->positionString);
+        if (parentTypesCount != (parentCount / 2))
+            {
+            errAbort("error parsing hubSearchText->parentTypes: '%s' for %s.%s in hub: '%s'",
+                hst->parentTypes, genomeOut->genomeName, hst->track, hub->url);
+            }
 
         boolean foundParent = FALSE;
         boolean doAddSaveParent = FALSE;
         for (i = 0; i < parentCount; i += 2)
             {
             parentTrack = stripEnclosingDoubleQuotes(cloneString(parentTrackLabels[i]));
             parentLabel = stripEnclosingDoubleQuotes(cloneString(parentTrackLabels[i+1]));
-            parentTdbOut = hashFindVal(genomeOut->tdbOutHash, parentTrack);
-            if (parentTdbOut != NULL)
+            // wait until the first valid trackui page for the track hit
+            if (isEmpty(dyStringContents(tdbOut->configUrl)) && sameString(parentTypes[i/2], "comp"))
                 {
-                foundParent = TRUE; // don't add this track to the genomeOut->tracks hash again
-                if (savedParent && doAddSaveParent)
-                    {
-                    parentTdbOut->childCount += 1;
-                    slAddHead(&(parentTdbOut->children), savedParent);
+                dyStringPrintf(tdbOut->configUrl, "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s_%s&hgsid=%s&%s",
+                    hub->url, genomeOut->genomeName, hubId, parentTrack, cartSessionId(cart),
+                    genomeOut->positionString);
                 }
-                else if (!savedParent)
+            else if (isEmpty(dyStringContents(tdbOut->configUrl)) && sameString(parentTypes[i/2], "super"))
                 {
-                    parentTdbOut->childCount += 1;
-                    slAddHead(&(parentTdbOut->children), tdbOut);
-                    }
-                savedParent = parentTdbOut;
-                doAddSaveParent = FALSE;
+                dyStringPrintf(tdbOut->configUrl, "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s_%s&hgsid=%s&%s",
+                    hub->url, genomeOut->genomeName, hubId, hst->track, cartSessionId(cart),
+                    genomeOut->positionString);
                 }
-            else
+            parentTdbOut = hashFindVal(genomeOut->tdbOutHash, parentTrack);
+            if (parentTdbOut == NULL)
                 {
                 AllocVar(parentTdbOut);
                 parentTdbOut->shortLabel = dyStringNew(0);
                 parentTdbOut->metaTags = dyStringNew(0);
                 parentTdbOut->descriptionMatch = dyStringNew(0);
                 parentTdbOut->configUrl = dyStringNew(0);
-                dyStringPrintf(tdbOut->configUrl,
-                    "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s&hgsid=%s&%s",
-                    hub->url, genomeOut->genomeName, parentTrack, cartSessionId(cart), genomeOut->positionString);
+                // views will be in the parent list, but the &g parameter to trackUi should be the view's parent
+                if (sameString(parentTypes[(i/2)], "view"))
+                    dyStringPrintf(parentTdbOut->configUrl,
+                        "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s_%s&hgsid=%s&%s",
+                        hub->url, genomeOut->genomeName, hubId, stripEnclosingDoubleQuotes(parentTrackLabels[(i/2)+2]), cartSessionId(cart), genomeOut->positionString);
+                else // everything else has the correct &g param
+                    dyStringPrintf(parentTdbOut->configUrl,
+                        "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s_%s&hgsid=%s&%s",
+                        hub->url, genomeOut->genomeName, hubId, parentTrack, cartSessionId(cart), genomeOut->positionString);
                 dyStringPrintf(parentTdbOut->shortLabel, "%s", parentLabel);
                 parentTdbOut->childCount += 1;
                 if (savedParent)
                     slAddHead(&(parentTdbOut->children), savedParent);
                 else
                     slAddHead(&(parentTdbOut->children), tdbOut);
                 savedParent = parentTdbOut;
                 doAddSaveParent = TRUE;
                 hashAdd(genomeOut->tdbOutHash, parentTrack, parentTdbOut);
                 }
+            else
+                {
+                foundParent = TRUE; // don't add this track to the genomeOut->tracks hash again
+                if (savedParent && doAddSaveParent)
+                    {
+                    parentTdbOut->childCount += 1;
+                    slAddHead(&(parentTdbOut->children), savedParent);
+                    }
+                else if (!savedParent)
+                    {
+                    parentTdbOut->childCount += 1;
+                    slAddHead(&(parentTdbOut->children), tdbOut);
+                    }
+                savedParent = parentTdbOut;
+                doAddSaveParent = FALSE;
+                }
             }
         if (!foundParent)
             {
             slAddHead(&(genomeOut->tracks), parentTdbOut);
             }
         }
     else
         {
-        dyStringPrintf(tdbOut->configUrl, "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s&hgsid=%s&%s",
-            hub->url, genomeOut->genomeName, hst->track, cartSessionId(cart),
+        dyStringPrintf(tdbOut->configUrl, "../cgi-bin/hgTrackUi?hubUrl=%s&db=%s&g=%s_%s&hgsid=%s&%s",
+            hub->url, genomeOut->genomeName, hubId, hst->track, cartSessionId(cart),
             genomeOut->positionString);
         slAddHead(&(genomeOut->tracks), tdbOut);
         }
     hashAdd(genomeOut->tdbOutHash, hst->track, tdbOut);
     }
 return tdbOut;
 }
 
 struct hubOutputStructure *buildHubSearchOutputStructure(struct trackHub *hub,
         struct hubSearchText *searchResults)
 /* Build a structure that contains the data for writing out the hub search results for this hub */
 {
 struct hash *missingGenomes = hashNew(0);
 struct hubOutputStructure *hubOut = NULL;
 AllocVar(hubOut);