8dd7fb37563baba6ade31719a3b3cf5237f4348c
hiram
  Sat Jan 23 21:54:52 2021 -0800
pass better lable string in json to have better indication of what species is being selected in the species search box refs #23891

diff --git src/hg/hgGateway/hgGateway.c src/hg/hgGateway/hgGateway.c
index 3b02cf2..6d616c1 100644
--- src/hg/hgGateway/hgGateway.c
+++ src/hg/hgGateway/hgGateway.c
@@ -701,170 +701,188 @@
         checkTerm(term, dbDb->description, ddmtDescription, dbDb, matchHash, &matchList);
     }
 slSort(&matchList, dbDbMatchCmp);
 return matchList;
 }
 
 // Assembly hub match:
 
 struct aHubMatch
     // description of an assembly hub db
     {
     struct aHubMatch *next;
     char *shortLabel;          // hub shortLabel
     char *hubUrl;              // hub url
     char *aDb;                 // assembly db hosted by hub
+    char *label;               // label for this db
     };
 
-static struct aHubMatch *aHubMatchNew(char *shortLabel, char *hubUrl, char *aDb)
+static struct aHubMatch *aHubMatchNew(char *shortLabel, char *hubUrl, char *aDb, char *label)
 /* Allocate and return a description of an assembly hub db. */
 {
 struct aHubMatch *match;
 AllocVar(match);
 match->shortLabel = cloneString(shortLabel);
 match->hubUrl = cloneString(hubUrl);
 match->aDb = cloneString(aDb);
+match->label = cloneString(label);
 return match;
 }
 
-static struct hash *unpackHubDbUrlList(struct slName *hubDbUrlList)
-/* hubDbUrlList contains strings like "db,hubUrl" -- split on comma and return a hash of
+static struct hash *unpackHubDbUrlList(struct slName *hubDbUrlList, struct hash **labelHash)
+/* hubDbUrlList contains strings like "db\tlabel\thubUrl" -- split on tab and return a hash of
  * hubUrl to one or more dbs. */
 {
 struct hash *hubToDb = hashNew(0);
+struct hash *dbToLabel = hashNew(0);
 struct slName *hubDbUrl;
 for (hubDbUrl = hubDbUrlList;  hubDbUrl != NULL;  hubDbUrl = hubDbUrl->next)
     {
-    char *comma = strchr(hubDbUrl->name, ',');
-    if (comma)
+    char *tab = strchr(hubDbUrl->name, '\t');
+    if (tab)
         {
         char *db = hubDbUrl->name;
-        *comma = '\0';
-        char *hubUrl = comma+1;
+        *tab = '\0';
+        char *label = tab+1;
+        char *url = strchr(label, '\t');
+        if (url)
+            {
+            *url = '\0';
+            char *hubUrl = url+1;
             struct hashEl *hel = hashLookup(hubToDb, hubUrl);
             struct slName *dbList = hel ? hel->val : NULL;
             slAddHead(&dbList, slNameNew(db));
             if (hel == NULL)
                 hashAdd(hubToDb, hubUrl, dbList);
             else
                 hel->val = dbList;
             }
+            hashAdd(dbToLabel, db, label);
+        }
     }
+*labelHash = dbToLabel;
 return hubToDb;
 }
 
 static struct aHubMatch *filterHubSearchTextMatches(struct dbDb *dbDbList,
                                                     struct slName *hubDbUrlList)
 /* Collect the assembly hub matches (not track hub matches) from a search in hubSearchText. */
 {
 if (hubDbUrlList == NULL)
     return NULL;
 struct aHubMatch *aHubMatchList = NULL;
 // Make a hash of local dbs so we can tell which hub dbs must be assembly hubs
 // not track hubs.
 struct hash *localDbs = hashNew(0);
 struct dbDb *dbDb;
 for (dbDb = dbDbList;  dbDb != NULL;  dbDb = dbDb->next)
     hashStore(localDbs, dbDb->name);
-struct hash *hubToDb = unpackHubDbUrlList(hubDbUrlList);
+struct hash *dbLabel = NULL;
+struct hash *hubToDb = unpackHubDbUrlList(hubDbUrlList, &dbLabel);
 // Build up a query to find shortLabel and dbList for each hubUrl.
 struct dyString *query = sqlDyStringCreate("select shortLabel,hubUrl,dbList from %s "
                                            "where hubUrl in (",
                                            hubPublicTableName());
 struct hashEl *hel;
 struct hashCookie cookie = hashFirst(hubToDb);
 boolean isFirst = TRUE;
 while ((hel = hashNext(&cookie)) != NULL)
     {
     if (isFirst)
         isFirst = FALSE;
     else
         dyStringAppend(query, ", ");
     dyStringPrintf(query, "'%s'", hel->name);
     }
 dyStringAppendC(query, ')');
 struct sqlConnection *conn = hConnectCentral();
 struct sqlResult *sr = sqlGetResult(conn, query->string);
 char **row;
 while ((row = sqlNextRow(sr)) != NULL)
     {
     char *shortLabel = row[0];
     char *hubUrl = row[1];
     struct slName *dbName, *matchDbList = hashFindVal(hubToDb, hubUrl);
     struct slName *hubDbList = slNameListFromComma(row[2]);
     if (slCount(matchDbList) == 1 && isEmpty(matchDbList->name))
         {
         // top-level hub match, no specific db match; add all of hub's assembly dbs
         for (dbName = hubDbList;  dbName != NULL;  dbName = dbName->next)
             if (! hashLookup(localDbs, dbName->name))
-                slAddHead(&aHubMatchList, aHubMatchNew(shortLabel, hubUrl, dbName->name));
+                slAddHead(&aHubMatchList, aHubMatchNew(shortLabel, hubUrl, dbName->name, NULL));
         }
     else
         {
         // Add matching assembly dbs that are found in hubDbList
         for (dbName = matchDbList;  dbName != NULL;  dbName = dbName->next)
             if (! hashLookup(localDbs, dbName->name) && slNameInList(hubDbList, dbName->name))
-                slAddHead(&aHubMatchList, aHubMatchNew(shortLabel, hubUrl, dbName->name));
+                {
+                char *label = hashFindVal(dbLabel, dbName->name);
+                if (label)
+                    slAddHead(&aHubMatchList, aHubMatchNew(shortLabel, hubUrl, dbName->name, label));
+                else
+                    slAddHead(&aHubMatchList, aHubMatchNew(shortLabel, hubUrl, dbName->name, NULL));
+                }
         }
     }
 slReverse(&aHubMatchList);
 hDisconnectCentral(&conn);
 return aHubMatchList;
 }
 
 static void writeAssemblyHubMatches(struct jsonWrite *jw, struct aHubMatch *aHubMatchList)
 /* Write out JSON for each assembly in each assembly hub that matched the search term. */
 {
 struct aHubMatch *aHubMatch;
 for (aHubMatch = aHubMatchList;  aHubMatch != NULL;  aHubMatch = aHubMatch->next)
     {
     jsonWriteObjectStart(jw, NULL);
     jsonWriteString(jw, "genome", aHubMatch->shortLabel);
     jsonWriteString(jw, "db", aHubMatch->aDb);
     jsonWriteString(jw, "hubUrl", aHubMatch->hubUrl);
     jsonWriteString(jw, "hubName", hubNameFromUrl(aHubMatch->hubUrl));
     // Add a category label for customized autocomplete-with-categories.
     char category[PATH_LEN*4];
     safef(category, sizeof(category), "Assembly Hub: %s", aHubMatch->shortLabel);
     jsonWriteString(jw, "category", category);
     jsonWriteString(jw, "value", aHubMatch->aDb);
     // Use just the db as label, since shortLabel is included in the category label.
-    jsonWriteString(jw, "label", aHubMatch->aDb);
+    jsonWriteString(jw, "label", aHubMatch->label);
     jsonWriteObjectEnd(jw);
     }
 }
 
 static struct aHubMatch *searchPublicHubs(struct dbDb *dbDbList, char *term)
 /* Search for term in public hubs -- return a list of matches to assembly hubs
  * (i.e. hubs that host an assembly with 2bit etc as opposed to only providing tracks.) */
 {
 struct aHubMatch *aHubMatchList = NULL;
 char *hubSearchTableName = cfgOptionDefault("hubSearchTextTable", "hubSearchText");
 struct sqlConnection *conn = hConnectCentral();
 if (sqlTableExists(conn, hubSearchTableName))
     {
     char query[1024];
-    sqlSafef(query, sizeof(query), "select distinct(concat(db, concat(',', hubUrl))) from %s "
+    sqlSafef(query, sizeof(query), "select distinct(concat(db, concat(concat('\t', label), concat('\t', hubUrl)))) from %s "
              "where track = '' and "
              "(db like '%s%%' or label like '%%%s%%' or text like '%s%%')",
              hubSearchTableName, term, term, term);
     struct slName *hubDbUrlList = sqlQuickList(conn, query);
     aHubMatchList = filterHubSearchTextMatches(dbDbList, hubDbUrlList);
     if (aHubMatchList == NULL)
         {
         // Try a looser query
-        sqlSafef(query, sizeof(query), "select distinct(concat(db, concat(',', hubUrl))) from %s "
+        sqlSafef(query, sizeof(query), "select distinct(concat(db, concat(concat('\t', label), concat('\t', hubUrl))) from %s "
                  "where track = '' and text like '%% %s%%'",
                  hubSearchTableName, term);
         hubDbUrlList = sqlQuickList(conn, query);
         aHubMatchList = filterHubSearchTextMatches(dbDbList, hubDbUrlList);
         }
     }
 hDisconnectCentral(&conn);
 return aHubMatchList;
 }
 
 static char *getSearchTermUpperCase()
 /* If we don't have the SEARCH_TERM cgi param, exit with an HTTP Bad Request response.
  * If we do, convert it to upper case for case-insensitive matching and return it. */
 {
 pushWarnHandler(htmlVaBadRequestAbort);