e59588ca7baf37936bc6c07f9ed49a08251ed474 chmalee Wed Nov 22 09:45:17 2017 -0800 Adding a link to hosting section to hgCustom and hgHubConnect diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c index 3a2271b..0cea06c 100644 --- src/hg/hgHubConnect/hgHubConnect.c +++ src/hg/hgHubConnect/hgHubConnect.c @@ -1,1466 +1,1467 @@ /* hgHubConnect - the CGI web-based program to select track data hubs to connect with. */ /* Copyright (C) 2014 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "common.h" #include "hash.h" #include "linefile.h" #include "errAbort.h" #include "errCatch.h" #include "hCommon.h" #include "dystring.h" #include "jksql.h" #include "cheapcgi.h" #include "htmshell.h" #include "hdb.h" #include "hui.h" #include "cart.h" #include "dbDb.h" #include "web.h" #include "trackHub.h" #include "hubConnect.h" #include "dystring.h" #include "hPrint.h" #include "jsHelper.h" #include "obscure.h" #include "hgConfig.h" #include "trix.h" #include "net.h" #include "hubSearchText.h" struct cart *cart; /* The user's ui state. */ struct hash *oldVars = NULL; static char *pageTitle = "Track Data Hubs"; char *database = NULL; char *organism = NULL; struct hubOutputStructure { struct hubOutputStructure *next; struct dyString *descriptionMatch; struct genomeOutputStructure *genomes; int genomeCount; struct hash *genomeOutHash; }; struct genomeOutputStructure { struct genomeOutputStructure *next; struct dyString *shortLabel; struct dyString *descriptionMatch; struct tdbOutputStructure *tracks; struct dyString *assemblyLink; char *genomeName; char *positionString; int trackCount; struct hash *tdbOutHash; int hitCount; }; struct tdbOutputStructure { struct tdbOutputStructure *next; struct dyString *shortLabel; struct dyString *descriptionMatch; struct dyString *configUrl; struct tdbOutputStructure *children; int childCount; }; struct hubEntry // for entries pulled from hubPublic { struct hubEntry *next; char *hubUrl; char *shortLabel; char *longLabel; char *dbList; char *errorMessage; int id; char *descriptionUrl; bool tableHasDescriptionField; }; struct hubEntry *hubEntryTextLoad(char **row, bool hasDescription) { struct hubEntry *ret; AllocVar(ret); ret->hubUrl = cloneString(row[0]); ret->shortLabel = cloneString(row[1]); ret->longLabel = cloneString(row[2]); ret->dbList = cloneString(row[3]); ret->errorMessage = cloneString(row[4]); ret->id = sqlUnsigned(row[5]); if (hasDescription) ret->descriptionUrl = cloneString(row[6]); else ret->descriptionUrl = NULL; return ret; } static void ourCellStart() { fputs("", stdout); // do not add a newline } static void ourCellEnd() { puts(""); } static void ourPrintCellLink(char *str, char *url) { ourCellStart(); printf("\n", url); if (str != NULL) fputs(str, stdout); // do not add a newline -- was causing trailing blanks get copied in cut and paste puts(""); ourCellEnd(); } static void ourPrintCell(char *str) { ourCellStart(); if (str != NULL) fputs(str, stdout); // do not add a newline -- was causing trailing blanks get copied in cut and paste ourCellEnd(); } static char *removeLastComma(char *string) { if (string != NULL) { int len = strlen(string); if ( string[len - 1] == ',') string[len - 1] = 0; else if (len > 2 && endsWith(string,", ")) string[len - 2] = 0; } return string; } #define GENLISTWIDTH 40 static void printGenomeList(struct slName *genomes, int row) /* print supported assembly names from sl list */ { /* List of associated genomes. */ struct dyString *dy = newDyString(100); struct dyString *dyShort = newDyString(100); char *trimmedName = NULL; for(; genomes; genomes = genomes->next) { trimmedName = trackHubSkipHubName(genomes->name); dyStringPrintf(dy,"%s, ", trimmedName); if (dyShort->stringSize == 0 || (dyShort->stringSize+strlen(trimmedName)<=GENLISTWIDTH)) dyStringPrintf(dyShort,"%s, ", trimmedName); } char *genomesString = removeLastComma( dyStringCannibalize(&dy)); char *genomesShort = removeLastComma( dyStringCannibalize(&dyShort)); char tempHtml[1024+strlen(genomesString)+strlen(genomesShort)]; if (strlen(genomesShort) > GENLISTWIDTH) // If even the first element is too long, truncate it. genomesShort[GENLISTWIDTH] = 0; if (strlen(genomesShort)==strlen(genomesString)) { safef(tempHtml, sizeof tempHtml, "%s", genomesString); } else { char id[256]; safef(tempHtml, sizeof tempHtml, "[+] %s..." "[-]
%s
" , row, genomesShort , row, genomesString); safef(id, sizeof id, "Short%d", row); jsOnEventByIdF("click", id, "document.getElementById('Short%d').style.display='none';" "document.getElementById('Full%d').style.display='inline';" "return false;" , row, row); safef(id, sizeof id, "Full%d", row); jsOnEventByIdF("click", id, "document.getElementById('Full%d').style.display='none';" "document.getElementById('Short%d').style.display='inline';" "return false;" , row, row); } ourPrintCell(tempHtml); } static void printGenomes(struct trackHub *thub, int row) /* print supported assembly names from trackHub */ { /* List of associated genomes. */ struct trackHubGenome *genomes = thub->genomeList; struct slName *list = NULL, *el; for(; genomes; genomes = genomes->next) { el = slNameNew(genomes->name); slAddHead(&list, el); } slReverse(&list); printGenomeList(list, row); } static void hgHubConnectUnlisted(struct hubConnectStatus *hubList, struct hash *publicHash) /* Put up the list of unlisted hubs and other controls for the page. */ /* uses publicHash to distingusih public hubs from unlisted ones */ /* NOTE: Destroys hubList */ { // put out the top of our page printf("
\n" " \n" " \n" " \n" " \n"); jsOnEventById("click", "hubAddButton", "var hubText = document.getElementById('hubUrl');" "hubText.value=$.trim(hubText.value);" "if(validateUrl($('#hubUrl').val())) { " " document.addHubForm.elements['hubUrl'].value=hubText.value;" " document.addHubForm.submit(); return true; } " "else { return false; }" ); // count up the number of unlisted hubs we currently have int unlistedHubCount = 0; struct hubConnectStatus *unlistedHubList = NULL; struct hubConnectStatus *hub, *nextHub; for(hub = hubList; hub; hub = nextHub) { nextHub = hub->next; // if url is not in publicHash, it's unlisted */ if (!((publicHash != NULL) && hashLookup(publicHash, hub->hubUrl))) { unlistedHubCount++; slAddHead(&unlistedHubList, hub); } } hubList = NULL; // hubList no longer valid if (unlistedHubCount == 0) { // nothing to see here printf(""); printf("
\n" " \n" "\n" "
No Unlisted Track Hubs
"); return; } // time to output the big table. First the header printf( " " "Display " "Hub Name " "Description " "Assemblies " "\n" "\n"); // start first row printf(""); char id[256]; int count = 0; for(hub = unlistedHubList; hub; hub = hub->next) { char hubName[64]; safef(hubName, sizeof(hubName), "%s%u", hgHubConnectHubVarPrefix, hub->id); if (!cartUsualBoolean(cart, hubName, FALSE)) continue; if (count) webPrintLinkTableNewRow(); // ends last row and starts a new one count++; puts(""); ourCellStart(); safef(id, sizeof id, "hubDisconnectButtonU%d", count); printf("\n", id); jsOnEventByIdF("click", id, "document.disconnectHubForm.elements['hubId'].value='%d';" "document.disconnectHubForm.submit(); return true;", hub->id); ourCellEnd(); if (hub->trackHub != NULL) { ourPrintCellLink(hub->trackHub->shortLabel, hub->hubUrl); } else ourPrintCell(""); if (!isEmpty(hub->errorMessage)) { ourCellStart(); printf("ERROR: %s " "Debug Help\n", hub->errorMessage); safef(id, sizeof id, "hubClearButton%d", count); // give people a chance to clear the error printf("" , id); jsOnEventByIdF("click", id, "document.resetHubForm.elements['hubCheckUrl'].value='%s';" "document.resetHubForm.submit(); return true;", hub->hubUrl); ourCellEnd(); } else if (hub->trackHub != NULL) { if (hub->trackHub->descriptionUrl != NULL) ourPrintCellLink(hub->trackHub->longLabel, hub->trackHub->descriptionUrl); else ourPrintCell(hub->trackHub->longLabel); } else ourPrintCell(""); if (hub->trackHub != NULL) printGenomes(hub->trackHub, count); else ourPrintCell(""); puts(""); } printf("\n"); printf(""); } static void addPublicHubsToHubStatus(struct sqlConnection *conn, char *publicTable, char *statusTable) /* Add urls in the hubPublic table to the hubStatus table if they aren't there already */ { char query[1024]; sqlSafef(query, sizeof(query), "select %s.hubUrl from %s left join %s on %s.hubUrl = %s.hubUrl where %s.hubUrl is NULL", publicTable, publicTable, statusTable, publicTable, statusTable, statusTable); struct sqlResult *sr = sqlGetResult(conn, query); char **row; while ((row = sqlNextRow(sr)) != NULL) { char *errorMessage = NULL; char *url = row[0]; // add this url to the hubStatus table hubFindOrAddUrlInStatusTable(database, cart, url, &errorMessage); } } char *modifyTermsForHubSearch(char *hubSearchTerms, bool isStrictSearch) /* This won't exactly be pretty. MySQL treats any sequence of alphanumerics and underscores * as a word, and single apostrophes are allowed as long as they don't come back-to-back. * Cut down to those characters, then add initial + (for requiring word) and * (for word * expansion) as appropriate. */ { char *cloneTerms = cloneString(hubSearchTerms); struct dyString *modifiedTerms = dyStringNew(0); if (isNotEmpty(cloneTerms)) { int i; for (i=0; itextLength == hubSearchTextLong) && isEmpty(hst->text)) continue; char *hubUrl = hst->hubUrl; struct hubEntry *hubInfo = hashFindVal(hubLookup, hubUrl); if (hubInfo == NULL) continue; // Search table evidently includes a hub that's not on this server. Skip it. char *db = cloneString(hst->db); tolowers(db); if (isNotEmpty(dbFilter)) { if (isNotEmpty(db)) { if (stringIn(dbFilter, db) == NULL) continue; } else { // no db in the hubSearchText means this is a top-level hub hit. // filter by the db list associated with the hub instead char *dbList = cloneString(hubInfo->dbList); tolowers(dbList); if (stringIn(dbFilter, dbList) == NULL) continue; } } // Add hst to the list to be returned slAddHead(&hubSearchResultsList, hst); } slReverse(&hubSearchResultsList); return hubSearchResultsList; } void printSearchAndFilterBoxes(int searchEnabled, char *hubSearchTerms, char *dbFilter) /* Create the text boxes for search and database filtering along with the required * javscript */ { char event[4096]; if (searchEnabled) { safef(event, sizeof(event), "document.searchHubForm.elements['hubSearchTerms'].value=$('#hubSearchTerms').val();" "document.searchHubForm.elements['hubDbFilter'].value=$('#hubDbFilter').val();" "document.searchHubForm.submit();return true;"); printf("Enter search terms to find in public track hub description pages:
" " \n", hubSearchTerms!=NULL?hubSearchTerms:""); printf("
\n"); } else { safef(event, sizeof(event), "document.searchHubForm.elements['hubDbFilter'].value=$('#hubDbFilter').val();" "document.searchHubForm.submit();return true;"); } printf("Filter hubs by assembly: " " \n" "\n", hgHubDbFilter, dbFilter!=NULL?dbFilter:""); jsOnEventById("click", "hubSearchButton", event); puts("

\n"); } void printSearchTerms(char *hubSearchTerms) /* Write out a reminder about the current search terms and a note about * how to navigate detailed search results */ { printf("Displayed list restricted by search terms: %s\n", hubSearchTerms); puts("\n"); jsOnEventById("click", "hubDeleteSearchButton", "document.searchHubForm.elements['hubSearchTerms'].value='';" "document.searchHubForm.elements['hubDbFilter'].value='';" "document.searchHubForm.submit();return true;"); puts("

\n"); printf("When exploring the detailed search results for a hub, you may right-click " "on an assembly or track line to open it in a new window.\n"); puts("

\n"); } void printHubListHeader() /* Write out the header for a list of hubs in its own table */ { puts("Clicking Connect redirects to the gateway page of the selected hub's default assembly.
"); printf(" " " " " " " " " " " " "
DisplayHub NameDescriptionAssemblies
\n"); } struct hash *buildPublicLookupHash(struct sqlConnection *conn, char *publicTable, char *statusTable, struct hash **pHash) /* Return a hash linking hub URLs to struct hubEntries. Also make pHash point to a hash that just stores * the names of the public hubs (for use later when determining if hubs were added by the user) */ { struct hash *hubLookup = newHash(5); struct hash *publicLookup = newHash(5); char query[512]; bool hasDescription = sqlColumnExists(conn, publicTable, "descriptionUrl"); if (hasDescription) sqlSafef(query, sizeof(query), "select p.hubUrl,p.shortLabel,p.longLabel,p.dbList," "s.errorMessage,s.id,p.descriptionUrl from %s p,%s s where p.hubUrl = s.hubUrl", publicTable, statusTable); else sqlSafef(query, sizeof(query), "select p.hubUrl,p.shortLabel,p.longLabel,p.dbList," "s.errorMessage,s.id from %s p,%s s where p.hubUrl = s.hubUrl", publicTable, statusTable); struct sqlResult *sr = sqlGetResult(conn, query); char **row; while ((row = sqlNextRow(sr)) != NULL) { struct hubEntry *hubInfo = hubEntryTextLoad(row, hasDescription); hubInfo->tableHasDescriptionField = hasDescription; hashAddUnique(hubLookup, hubInfo->hubUrl, hubInfo); hashStore(publicLookup, hubInfo->hubUrl); } sqlFreeResult(&sr); *pHash = publicLookup; return hubLookup; } void outputPublicTableRow(struct hubEntry *hubInfo, int count) /* Prints out a table row with basic information about a hub and a button * to connect to that hub */ { int id = hubInfo->id; char jsId[256]; struct slName *dbListNames = slNameListFromComma(hubInfo->dbList); printf("\n"); if (id != 0) { ourCellStart(); char hubName[32]; safef(hubName, sizeof(hubName), "%s%u", hgHubConnectHubVarPrefix, id); if (cartUsualBoolean(cart, hubName, FALSE)) { safef(jsId, sizeof jsId, "hubDisconnectButtonP%d", count); printf("\n", jsId); jsOnEventByIdF("click", jsId, "document.disconnectHubForm.elements['hubId'].value= '%d';" "document.disconnectHubForm.submit();return true;", id); } else { // get first name off of list of supported databases char * name = dbListNames->name; // if the name isn't currently loaded, we assume it's a hub if (!hDbExists(name)) { char buffer[512]; safef(buffer, sizeof buffer, "hub_%d_%s", id, name); name = cloneString(buffer); } safef(jsId, sizeof jsId, "hubConnectButton%d", count); printf("\n", jsId); jsOnEventByIdF("click", jsId, "document.connectHubForm.elements['hubUrl'].value= '%s';" "document.connectHubForm.elements['db'].value= '%s';" "document.connectHubForm.submit();return true;", hubInfo->hubUrl,name); } ourCellEnd(); } else errAbort("cannot get id for hub with url %s\n", hubInfo->hubUrl); ourPrintCellLink(hubInfo->shortLabel, hubInfo->hubUrl); if (isEmpty(hubInfo->errorMessage)) { if (hubInfo->tableHasDescriptionField && !isEmpty(hubInfo->descriptionUrl)) ourPrintCellLink(hubInfo->longLabel, hubInfo->descriptionUrl); else ourPrintCell(hubInfo->longLabel); } else { ourCellStart(); printf("ERROR: %s " "Debug Help", hubInfo->errorMessage); safef(jsId, sizeof jsId, "hubClearButton%d", count); printf( "" , jsId); jsOnEventByIdF("click", jsId, "document.resetHubForm.elements['hubCheckUrl'].value='%s';" "document.resetHubForm.submit();return true;", hubInfo->hubUrl); ourCellEnd(); } printGenomeList(dbListNames, count); printf("\n"); } void printSearchOutputForTrack(struct tdbOutputStructure *tdbOut) /* Write out a
  • entry for a search hit on a track, along with a nested *