dc68ca87c184d7a6d4112e293073bddb34a9e913
hiram
  Tue Mar 19 10:36:54 2019 -0700
full reporting of all track names in html display even when not in detail mode refs #18869

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index 81847be..f9a2b0c 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -152,52 +152,74 @@
     hashIncInt(countTracks, "superTrack child");
     hashIncInt(countTracks, stripType);
     hashIncInt(countTracks, "track count");
     }
 else if (isEmpty(tdb->type))
     hashIncInt(countTracks, "no type specified");
 else
     {
     hashIncInt(countTracks, stripType);
     hashIncInt(countTracks, "track count");
     }
 freeMem(stripType);
 // showCounts(countTracks);
 }
 
+static void showSubTracks(struct trackDb *tdb, struct hash *countTracks)
+/* tdb has subtracks, show only subTracks, no details */
+{
+hPrintf("    <li><ul>\n");
+if (tdb->subtracks)
+    {
+    struct trackDb *tdbEl = NULL;
+    for (tdbEl = tdb->subtracks; tdbEl; tdbEl = tdbEl->next)
+	{
+        if (tdbIsCompositeView(tdbEl))
+	    hPrintf("<li>%s : %s : composite view of parent: %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track);
+	else
+            hPrintf("<li>%s : %s : subtrack of parent: %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track);
+	hashCountTrack(tdbEl, countTracks);
+        if (tdbEl->subtracks)
+	    showSubTracks(tdbEl, countTracks);
+	}
+    }
+hPrintf("    </ul></li>\n");
+}
+
 static void trackSettings(struct trackDb *tdb, struct hash *countTracks)
 /* process the settingsHash for a trackDb, recursive when subtracks */
 {
 hPrintf("    <li><ul>\n");
 // if (tdb->children)  haven't yet seen a track with children ?
 //   hPrintf("    <li>%s: has children</li>\n", tdb->track);
 // else
 //   hPrintf("    <li>%s: NO children</li>\n", tdb->track);
 struct hashEl *hel;
 struct hashCookie hc = hashFirst(tdb->settingsHash);
 while ((hel = hashNext(&hc)) != NULL)
     {
     if (sameWord("track", hel->name))
 	continue;	// already output in header
     if (isEmpty((char *)hel->val))
 	hPrintf("    <li>%s : &lt;empty&gt;</li>\n", hel->name);
     else
 	hPrintf("    <li>%s : '%s'</li>\n", hel->name, (char *)hel->val);
     }
 if (tdb->subtracks)
     {
     struct trackDb *tdbEl = NULL;
+    if (debug)
 	hPrintf("   <li>has %d subtrack(s)</li>\n", slCount(tdb->subtracks));
     for (tdbEl = tdb->subtracks; tdbEl; tdbEl = tdbEl->next)
 	{
         hPrintf("<li>subtrack: %s of parent: %s : type: '%s'</li>\n", tdbEl->track, tdbEl->parent->track, tdbEl->type);
 	hashCountTrack(tdbEl, countTracks);
 	trackSettings(tdbEl, countTracks);
 	}
     }
 hPrintf("    </ul></li>\n");
 }
 
 static int bbiBriefMeasure(char *type, char *bigDataUrl, char *bigDataIndex, long *chromCount, long *itemCount, struct dyString *errors)
 /* check a bigDataUrl to find chrom count and item count */
 {
 int retVal = 0;
@@ -315,78 +337,84 @@
             hPrintf("    <li>%s : %s : <font color='red'>ERROR: %s</font></li>\n", tdb->track, tdb->type, errors->string);
         }
     else
         {
         if (startsWithWord("bigBed", tdb->type))
             hPrintf("    <li>%s : %s : %ld chroms : %ld item count</li>\n", tdb->track, tdb->type, chromCount, itemCount);
         else if (startsWithWord("bigWig", tdb->type))
             hPrintf("    <li>%s : %s : %ld chroms : %ld bases covered</li>\n", tdb->track, tdb->type, chromCount, itemCount);
         else
             hPrintf("    <li>%s : %s : %ld chroms : %ld count</li>\n", tdb->track, tdb->type, chromCount, itemCount);
         }
     }
 else
     {
     if (compositeContainer)
-        hPrintf("    <li>%s : %s : composite track container</li>\n", tdb->track, tdb->type);
+        hPrintf("    <li>%s : %s : composite track container has %d subtracks</li>\n", tdb->track, tdb->type, slCount(tdb->subtracks));
     else if (compositeView)
         hPrintf("    <li>%s : %s : composite view of parent: %s</li>\n", tdb->track, tdb->type, tdb->parent->track);
     else if (superChild)
         hPrintf("    <li>%s : %s : superTrack child of parent: %s</li>\n", tdb->track, tdb->type, tdb->parent->track);
-    else if (! depthSearch)
+    else if (! depthSearch && bigDataUrl)
         hPrintf("    <li>%s : %s : %s</li>\n", tdb->track, tdb->type, bigDataUrl);
     else
         hPrintf("    <li>%s : %s</li>\n", tdb->track, tdb->type);
     }
 if (allTrackSettings)
     {
     hPrintf("    <li><ul>\n");
     trackSettings(tdb, countTracks); /* show all settings */
     hPrintf("    </ul></li>\n");
     }
+else if (tdb->subtracks)
+    {
+    showSubTracks(tdb, countTracks);
+    }
 return;
 }	/*	static void countOneTdb(struct trackDb *tdb,
 	 *	    char *bigDataIndex, struct hash *countTracks)
 	 */
 
 static void hubTrackList(struct trackDb *topTrackDb, struct trackHubGenome *genome)
 /* process the track list in a hub to show all tracks */
 {
 hPrintf("    <li><ul>\n");
 if (topTrackDb)
     {
     struct hash *countTracks = hashNew(0);
     struct trackDb *tdb = NULL;
     for ( tdb = topTrackDb; tdb; tdb = tdb->next )
 	{
 	char *bigDataIndex = NULL;
 	char *relIdxUrl = trackDbSetting(topTrackDb, "bigDataIndex");
 	if (relIdxUrl != NULL)
 	    bigDataIndex = trackHubRelativeUrl(genome->trackDbFile, relIdxUrl);
 	countOneTdb(tdb, bigDataIndex, countTracks);
 	if (timeOutReached())
 	    break;
 	}	/*	for ( tdb = topTrackDb; tdb; tdb = tdb->next )	*/
-    hPrintf("    <li>%d different track types</li>\n", countTracks->elCount);
+    hPrintf("    <li>%d different track types</li>\n",countTracks->elCount - 1);
     /* add this single genome count to the overall multi-genome counts */
     if (countTracks->elCount)
 	{
         hPrintf("        <li><ol>\n");
 	struct hashEl *hel, *helList = hashElListHash(countTracks);
 	slSort(&helList, hashElCmpIntValDesc);
 	for (hel = helList; hel; hel = hel->next)
 	    {
+	    if (sameOk("track count", hel->name))
+		continue;
             int prevCount = ptToInt(hashFindVal(trackCounter, hel->name));
 	    if (differentStringNullOk("track count", hel->name))
 		totalTracks += ptToInt(hel->val);
 	    hashReplace(trackCounter, hel->name, intToPt(prevCount + ptToInt(hel->val)));
 	    hPrintf("        <li>%d - %s</li>\n", ptToInt(hel->val), hel->name);
 	    }
         hPrintf("        </ol></li>\n");
 	}
     }
 else
     hPrintf("    <li>no trackTopDb</li>\n");
 
 hPrintf("    </ul><li>\n");
 }	/*	static struct trackDb *hubTrackList()	*/
 
@@ -581,38 +609,41 @@
 static void tracksForUcscDb(char *db)
 /* scan the specified database for all tracks */
 {
 struct hash *countTracks = hashNew(0);
 hPrintf("<p>Tracks in UCSC genome: '%s'<br>\n", db);
 struct trackDb *tdbList = obtainTdb(NULL, db);
 struct trackDb *tdb;
 hPrintf("<ul>\n");
 for (tdb = tdbList; tdb != NULL; tdb = tdb->next )
     {
     countOneTdb(tdb, NULL, countTracks);
     if (timeOutReached())
 	break;
     }
 int trackCount = ptToInt(hashFindVal(countTracks, "track count"));
-hPrintf("    <li>%d total tracks counted, %d different track types</li>\n", trackCount, countTracks->elCount);
+/* elCount - 1 since the 'track count' element isn't a track */
+hPrintf("    <li>%d total tracks counted, %d different track types</li>\n", trackCount, countTracks->elCount - 1);
 if (countTracks->elCount)
     {
     hPrintf("        <ol>\n");
     struct hashEl *hel, *helList = hashElListHash(countTracks);
     slSort(&helList, hashElCmpIntValDesc);
     for (hel = helList; hel; hel = hel->next)
 	{
+	if (sameOk("track count", hel->name))
+	    continue;
 	hPrintf("        <li>%d - %s</li>\n", ptToInt(hel->val), hel->name);
 	}
     hPrintf("        </ol>\n");
     }
 hPrintf("</ul>\n");
 hPrintf("</p>\n");
 }	// static void tracksForUcscDb(char * db)
 
 static void introductionText()
 /* output explanation text */
 {
 char *scriptUri = getenv("SCRIPT_URI");
 
 hPrintf("<h1>JSON data API interface to U.C. Santa Cruz genome browser data</h1>\n");
 hPrintf("<h2>Data access URL: <em>%s</em></h2>\n", scriptUri);
@@ -719,47 +750,44 @@
 initGenbankTableNames(database);
 
 char *docRoot = cfgOptionDefault("browser.documentRoot", DOCUMENT_ROOT);
 
 int timeout = cartUsualInt(cart, "udcTimeout", 300);
 if (udcCacheTimeout() < timeout)
     udcSetCacheTimeout(timeout);
 knetUdcInstall();
 
 char *pathInfo = getenv("PATH_INFO");
 /* nothing on incoming path, then display the WEB page instead */
 if (sameOk("/",pathInfo))
     pathInfo = NULL;
 
 boolean commandError = FALSE;
+/*expect no more than MAX_PATH_INFO number of words*/
 char *words[MAX_PATH_INFO];
 
 if (isNotEmpty(pathInfo))
     {
     setupFunctionHash();
-    /*expect no more than MAX_PATH_INFO number of words*/
     struct hashEl *hel = parsePathInfo(pathInfo, words);
     /* verify valid API command */
 
     if (hel)	/* have valid command */
 	{
         hPrintDisable();
 	puts("Content-Type:application/json");
 	puts("\n");
-	/* skip the first leading slash to simplify chopByChar parsing */
-//	pathInfo += 1;
-//	apiFunctionSwitch(hel, words);
         void (*apiFunction)(char **) = hel->val;
         (*apiFunction)(words);
 	return;
 	}
      else
 	commandError = TRUE;
     }
 
 puts("Content-Type:text/html");
 puts("\n");
 
 (void) hubPublicLoadAll();
 
 struct dbDb *dbList = ucscDbDb();
 char **ucscDbList = NULL;