c4ebea6f863d96a9e9dbfe40ac67193ece91b346
braney
  Tue May 13 17:26:39 2014 -0700
adding the ability to search hubs for content.
diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c
index e45fd8f..4e28b57 100644
--- src/hg/hgHubConnect/hgHubConnect.c
+++ src/hg/hgHubConnect/hgHubConnect.c
@@ -10,55 +10,68 @@
 #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"
 
 #define hgHub             "hgHub_"  /* prefix for all control variables */
 #define hgHubDo            hgHub   "do_"    /* prefix for all commands */
 #define hgHubDoClear       hgHubDo "clear"
 #define hgHubDoDisconnect  hgHubDo "disconnect"
 #define hgHubDoReset       hgHubDo "reset"
+#define hgHubDoSearch      hgHubDo "search"
+#define hgHubDoDeleteSearch      hgHubDo "deleteSearch"
 
 struct cart *cart;	/* The user's ui state. */
 struct hash *oldVars = NULL;
 
 static char *destUrl = "../cgi-bin/hgTracks";
 static char *pageTitle = "Track Data Hubs";
 char *database = NULL;
 char *organism = NULL;
 
 static void ourCellStart()
 {
 fputs("<TD>", stdout);  // do not add a newline
 }
 
 static void ourCellEnd()
 {
 puts("</TD>");
 }
 
+static void ourPrintCellLink(char *str, char *url)
+{
+ourCellStart();
+printf("<A HREF=\"%s\" TARGET=_BLANK>\n", url);
+if (str != NULL)
+    fputs(str, stdout); // do not add a newline -- was causing trailing blanks get copied in cut and paste 
+puts("</A>");
+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] == ',')
@@ -211,31 +224,40 @@
 	ourCellEnd();
 	}
     else
 	{
 	// give people a chance to clear the error 
 	ourCellStart();
 	printf(
 	"<input name=\"hubClearButton\""
 	    "onClick=\"document.resetHubForm.elements['hubUrl'].value='%s';"
 		"document.resetHubForm.submit();return true;\" "
 		"class=\"hubField\" type=\"button\" value=\"check hub\">\n"
 		, hub->hubUrl);
 	ourCellEnd();
 	}
     if (hub->trackHub != NULL)
+	{
+	if (hub->trackHub->descriptionUrl != NULL)
+	    {
+	    printf("<A href=%s>\n", hub->trackHub->descriptionUrl);
 	    ourPrintCell(hub->trackHub->shortLabel);
+	    puts("</A>");
+	    }
+	else
+	    ourPrintCell(hub->trackHub->shortLabel);
+	}
     else
 	ourPrintCell("");
 
     if (!isEmpty(hub->errorMessage))
 	printf("<TD><span class=\"hubError\">ERROR: %s </span>"
 	    "<a href=\"../goldenPath/help/hgTrackHubHelp.html#Debug\">Debug</a></TD>\n", 
 	    hub->errorMessage);
     else if (hub->trackHub != NULL)
 	ourPrintCell(hub->trackHub->longLabel);
     else
 	ourPrintCell("");
 
     if (hub->trackHub != NULL)
 	printGenomes(hub->trackHub, count);
     else
@@ -261,56 +283,114 @@
 {
 char query[1024];
 sqlSafef(query, sizeof(query), "select hubUrl from %s where hubUrl not in (select hubUrl from %s)\n", publicTable, 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);
     }
 }
 
+struct hash *getUrlSearchHash(char *trixFile, char *hubSearchTerms)
+/* find hubs that match search term in trixFile */
+{
+struct hash *urlSearchHash = newHash(5);
+struct trix *trix = trixOpen(trixFile);
+int trixWordCount = chopString(hubSearchTerms, " ", NULL, 0);
+char *trixWords[trixWordCount];
+trixWordCount = chopString(hubSearchTerms, " ", trixWords, trixWordCount);
+
+struct trixSearchResult *tsList = trixSearch(trix, trixWordCount, trixWords, TRUE);
+for ( ; tsList != NULL; tsList = tsList->next)
+    hashStore(urlSearchHash, tsList->itemId);
+
+return urlSearchHash;
+}
+
 static struct hash *outputPublicTable(struct sqlConnection *conn, char *publicTable, char *statusTable)
 /* Put up the list of public hubs and other controls for the page. */
 {
+char *trixFile = cfgOptionEnvDefault("HUBSEARCHTRIXFILE", "hubSearchTrixFile", "/gbdb/hubs/public.ix");
+char *hubSearchTerms = cartOptionalString(cart, hgHubSearchTerms);
+boolean haveTrixFile = fileExists(trixFile);
+struct hash *urlSearchHash = NULL;
+
+if (haveTrixFile && !isEmpty(hubSearchTerms))
+    urlSearchHash = getUrlSearchHash(trixFile, hubSearchTerms);
+
 addPublicHubsToHubStatus(conn, publicTable, statusTable);
 
 struct hash *publicHash = NULL;
 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;
 int count = 0;
 
+if (!isEmpty(hubSearchTerms))
+    {
+    printf("<BR>List restricted by search terms : %s\n", hubSearchTerms);
+    puts("<input name=\"hubDeleteSearchButton\""
+	"onClick="
+	"\" document.searchHubForm.elements['hubSearchTerms'].value=\'\';"
+	"document.searchHubForm.submit();return true;\" "
+	"class=\"hubField\" type=\"button\" value=\"Delete Search Terms\">\n");
+    printf("<BR>\n");
+    }
+
+if (haveTrixFile)
+    {
+    puts("<input name=\"hubSearchTerms\" id=\"hubSearchTerms\" class=\"hubField\""
+	"type=\"text\" size=\"65\"> \n"
+    "<input name=\"hubSearchButton\""
+	"onClick="
+	"\" document.searchHubForm.elements['hubSearchTerms'].value=hubSearchTerms.value;"
+	    "document.searchHubForm.submit();return true;\" "
+	    "class=\"hubField\" type=\"button\" value=\"Search Public Hubs\">\n");
+    }
+
 boolean gotAnyRows = FALSE;
 while ((row = sqlNextRow(sr)) != NULL)
     {
     ++count;
     char *url = row[0], *shortLabel = row[1], *longLabel = row[2], 
-    	  *dbList = row[3], *errorMessage = row[4];
+    	  *dbList = row[3], *errorMessage = row[4], *descriptionUrl = row[6];
     int id = atoi(row[5]);
+
+    if ((urlSearchHash != NULL) && (hashLookup(urlSearchHash, url) == NULL))
+	continue;
+
     if (gotAnyRows)
 	webPrintLinkTableNewRow();
     else
 	{
 	/* output header */
 	printf("<div id=\"publicHubs\" class=\"hubList\"> \n");
+
 	printf("<table id=\"publicHubsTable\"> "
 	    "<thead><tr> "
 		"<th>Display</th> "
 		"<th>Hub Name</th> "
 		"<th>Description</th> "
 		"<th>Assemblies</th> "
 		"<th>URL</th> "
 	    "</tr></thead>\n");
 
 	// start first row
 	printf("<tbody> <tr>");
 	gotAnyRows = TRUE;
 
 	// allocate the hash to store hubUrl's
 	publicHash = newHash(5);
@@ -327,30 +407,37 @@
     else if (!isEmpty(errorMessage))
 	{
 	// give user a chance to clear the error
 	ourCellStart();
 	printf(
 	"<input name=\"hubClearButton\""
 	    "onClick=\"document.resetHubForm.elements['hubUrl'].value='%s';"
 		"document.resetHubForm.submit();return true;\" "
 		"class=\"hubField\" type=\"button\" value=\"check hub\">"
 		, url);
 	ourCellEnd();
 	}
     else
 	errAbort("cannot get id for hub with url %s\n", url);
 
+    if (hasDescription && !isEmpty(descriptionUrl))
+	{
+	printf("<A HREF=\"%s\">\n", descriptionUrl);
+	ourPrintCellLink(shortLabel, descriptionUrl);
+	puts("</A>");
+	}
+    else
 	ourPrintCell(shortLabel);
     if (isEmpty(errorMessage))
 	ourPrintCell(longLabel);
     else
 	printf("<TD><span class=\"hubError\">ERROR: %s </span>"
 	    "<a href=\"../goldenPath/help/hgTrackHubHelp.html#Debug\">Debug</a></TD>", 
 	    errorMessage);
 
     printGenomeList(slNameListFromComma(dbList), count); // Leaking a bit of memory
     ourPrintCell(url);
 
     hashStore(publicHash, url);
     }
 sqlFreeResult(&sr);
 
@@ -364,31 +451,31 @@
 
 
 struct hash *hgHubConnectPublic()
 /* Put up the list of public hubs and other controls for the page. */
 {
 struct hash *retHash = NULL;
 struct sqlConnection *conn = hConnectCentral();
 char *publicTable = cfgOptionEnvDefault("HGDB_HUB_PUBLIC_TABLE", 
 	hubPublicTableConfVariable, defaultHubPublicTableName);
 char *statusTable = cfgOptionEnvDefault("HGDB_HUB_STATUS_TABLE", 
 	hubStatusTableConfVariable, defaultHubStatusTableName);
 if (!(sqlTableExists(conn, publicTable) && 
 	(retHash = outputPublicTable(conn, publicTable,statusTable)) != NULL ))
     {
     printf("<div id=\"publicHubs\" class=\"hubList\"> \n");
-    printf("No Public Track Hubs for this genome assembly<BR>");
+    printf("No Public Track Hubs<BR>");
     printf("</div>");
     }
 hDisconnectCentral(&conn);
 
 return retHash;
 }
 
 static void tryHubOpen(unsigned id)
 /* try to open hub, leaks trackHub structure */
 {
 /* try opening this again to reset error */
 struct sqlConnection *conn = hConnectCentral();
 struct errCatch *errCatch = errCatchNew();
 struct hubConnectStatus *hub = NULL;
 if (errCatchStart(errCatch))
@@ -531,44 +618,49 @@
 
 // check to see if we have any new hubs
 hubCheckForNew(cart);
 
 // grab all the hubs that are listed in the cart
 struct hubConnectStatus *hubList =  hubConnectStatusListFromCartAll(cart);
 
 checkTrackDbs(hubList);
 
 // here's a little form for the add new hub button
 printf("<FORM ACTION=\"%s\" NAME=\"addHubForm\">\n",  "../cgi-bin/hgHubConnect");
 cgiMakeHiddenVar("hubUrl", "");
 cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on");
 puts("</FORM>");
 
-// this the form for the disconnect hub button
+// this is the form for the disconnect hub button
 printf("<FORM ACTION=\"%s\" NAME=\"disconnectHubForm\">\n",  "../cgi-bin/hgHubConnect");
 cgiMakeHiddenVar("hubId", "");
 cgiMakeHiddenVar(hgHubDoDisconnect, "on");
 cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on");
 puts("</FORM>");
 
-// this the form for the reset hub button
+// this is the form for the reset hub button
 printf("<FORM ACTION=\"%s\" NAME=\"resetHubForm\">\n",  "../cgi-bin/hgHubConnect");
 cgiMakeHiddenVar("hubUrl", "");
 cgiMakeHiddenVar(hgHubDoReset, "on");
 cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on");
 puts("</FORM>");
 
+// this is the form for the search hub button
+printf("<FORM ACTION=\"%s\" NAME=\"searchHubForm\">\n",  "../cgi-bin/hgHubConnect");
+cgiMakeHiddenVar(hgHubSearchTerms, "");
+cgiMakeHiddenVar(hgHubDoSearch, "on");
+puts("</FORM>");
 
 // ... and now the main form
 if (cartVarExists(cart, hgHubConnectCgiDestUrl))
     destUrl = cartOptionalString(cart, hgHubConnectCgiDestUrl);
 printf("<FORM ACTION=\"%s\" METHOD=\"POST\" NAME=\"mainForm\">\n", destUrl);
 cartSaveSession(cart);
 
 // we have two tabs for the public and unlisted hubs
 printf("<div id=\"tabs\">"
        "<ul> <li><a href=\"#publicHubs\">Public Hubs</a></li>"
        "<li><a href=\"#unlistedHubs\">My Hubs</a></li> "
        "</ul> ");
 
 struct hash *publicHash = hgHubConnectPublic();
 hgHubConnectUnlisted(hubList, publicHash);