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);