ea1508d83bb99583cb9ec1ff630b938187a44006 chmalee Tue Nov 26 08:13:06 2019 -0800 Change 'validate hub' to 'Hub Development' and display custom help explaining that this tab is for running hubCheck. Also add a button to load the hub on hgTracks, and a dropdown with extra checkboxes for turning on udcTimeout and measureTiming. refs #24599 diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c index 0d8266f..318effe 100644 --- src/hg/hgHubConnect/hgHubConnect.c +++ src/hg/hgHubConnect/hgHubConnect.c @@ -375,84 +375,141 @@ ourPrintCell(""); puts("</tr>"); } printf("</tbody></TABLE>\n"); printf("</div>"); } void doValidateNewHub(char *hubUrl) /* Run hubCheck on a hub. */ { struct dyString *cmd = dyStringNew(0); udcSetCacheTimeout(1); dyStringPrintf(cmd, "loader/hubCheck -htmlOut -noTracks %s", hubUrl); -printf("</table>"); printf("<div id=\"validateHubResult\" class=\"hubTdbTree\" style=\"overflow: auto\"></div>"); FILE *f = popen(cmd->string, "r"); if (f == NULL) errAbort("popen: error running command: \"%s\"", cmd->string); char buf[1024]; while (fgets(buf, sizeof(buf), f)) { jsInlineF("%s", buf); } if (pclose(f) == -1) errAbort("pclose: error for command \"%s\"", cmd->string); // the 'false' below prevents a few hub-search specific jstree configuration options jsInline("hubSearchTree.init(false);"); dyStringFree(&cmd); } -void hgHubConnectValidateNewHub() +void hgHubConnectDeveloperMode() { // put out the top of our page char *hubUrl = cartOptionalString(cart, "validateHubUrl"); -printf("<div id=\"validateHub\" class=\"hubList\"> \n" - "<table id=\"validateHub\"> \n" - "<thead><tr> \n"); -printf("<th colspan=\"6\" id=\"addHubBar\"><label for=\"validateHubUrl\">URL:</label> \n"); +boolean doHubValidate = cartVarExists(cart, hgHubDoHubCheck); + +// the outer div for all the elements in the tab +printf("\n<div id=\"hubDeveloper\" class=\"hubList\">\n"); + +// the row to enter in the url and the button and settings to validate/load +printf("<div class=\"addHubBar roundCorners\" id=\"validateHubUrlRow\">\n"); +printf("<label for=\"validateHubUrl\"><b>URL:</b></label>\n"); if (hubUrl != NULL) { printf("<input name=\"validateText\" id=\"validateHubUrl\" class=\"hubField\" " "type=\"text\" size=\"65\" value=\"%s\"> \n", hubUrl); } else { printf("<input name=\"validateText\" id=\"validateHubUrl\" class=\"hubField\" " "type=\"text\" size=\"65\"> \n"); } printf("<input name=\"hubValidateButton\" id='hubValidateButton' " - "class=\"hubField\" type=\"button\" value=\"Validate Hub\">\n" - "</th> \n" - "</tr> \n"); + "class=\"hubField\" type=\"button\" value=\"Check Hub settings\">\n"); +printf(" or \n"); +printf("<input name=\"hubLoadMaybeTiming\" id='hubLoadMaybeTiming' " + "class=\"hubField\" type=\"button\" value=\"Load Hub\">\n"); +printf("</div>\n"); // validateHubUrlRow div + +printf("<div id=\"extraSettingsContainer\" class=\"addHubBar\">\n"); +printf("<img id=\"advancedSettingsButton\" src=\"../images/add_sm.gif\">\n"); +printf("Advanced Settings"); + +char *measureTiming = cartCgiUsualString(cart, "measureTiming", NULL); +char *udcTimeout = cartCgiUsualString(cart, "udcTimeout", NULL); + +printf("<div id=\"extraSettingsList\" style=\"display: none\">\n"); +printf("<ul style=\"list-style-type:none\">\n<li>\n"); +// measureTiming first +printf("<input name=\"addMeasureTiming\" id=\"addMeasureTiming\" " + "class=\"hubField\" type=\"checkbox\" %s>", measureTiming != NULL ? "checked": ""); +printf("<label for=\"addMeasureTiming\">Display load times</label>\n"); + +// and a tooltip explaining this checkbox +printf("<div class=\"tooltip\"> (?)\n"); +printf("<span class=\"tooltiptext\">" + "Checking this box shows the timing measurements below the Genome Browser image. " + "Useful for determining slowdowns to loading or drawing tracks." + "</span>\n"); +printf("</div></li>\n"); // tooltip div + +printf("<li>\n"); +// udcTimeout enable/disable +printf("<input name=\"disableUdcTimeout\" id=\"disableUdcTimeout\" " + "class=\"hubField\" type=\"checkbox\" %s >", udcTimeout != NULL ? "checked" : ""); +printf("<label for=\"disableUdcTimeout\">Enable hub refresh</label>\n"); +// add a tooltip explaining these checkboxes +printf("<div class=\"tooltip\"> (?)\n"); +printf("<span class=\"tooltiptext\">" + "Checking this box changes the cache expiration time (default of 5 minutes) " + "and allows the Genome Browser to reload Hub configuration files with each refresh." + "</span>\n"); +printf("</div></li>\n"); // tooltip div +printf("</ul>\n"); +printf("</div>\n"); // extraSettingsList div +printf("</div>\n"); // extraSettingsContainer div -if (hubUrl == NULL) - printf("<tr><td>Enter URL to hub to check settings</td></tr> \n"); -else +if (hubUrl != NULL && doHubValidate) doValidateNewHub(hubUrl); -printf("</table></div>"); +else + printf("<div id=\"hubDeveloperInstructions\">Enter URL to hub to check configuration settings " + "or load hub </div> \n"); +printf("</div>"); // hubDeveloper div jsOnEventById("click", "hubValidateButton", "var validateText = document.getElementById('validateHubUrl');" "validateText.value=$.trim(validateText.value);" "if(validateUrl($('#validateHubUrl').val())) { " " document.validateHubForm.elements['validateHubUrl'].value=validateText.value;" + " document.validateHubForm.elements['" hgHubDoHubCheck "'].value='on';" " document.validateHubForm.submit(); return true; }" "else { return false; }" ); +jsOnEventById("click", "hubLoadMaybeTiming", + "var validateText = document.getElementById('validateHubUrl');" + "var udcTimeout = document.getElementById('disableUdcTimeout').checked === true;" + "var doMeasureTiming = document.getElementById('addMeasureTiming').checked === true;" + "validateText.value=$.trim(validateText.value);" + "if(validateUrl($('#validateHubUrl').val())) {" + " loc = \"../cgi-bin/hgTracks?&hgHub_do_firstDb=on\" + \"&hubUrl=\" + validateText.value;" + " if (doMeasureTiming) { loc += \"&measureTiming=1\";} else { loc += \"&measureTiming=[]\"; }" + " if (udcTimeout) { loc += \"&udcTimeout=5\"; } else { loc += \"&udcTimeout=[]\"; }" + " window.location.href=loc; " + "} else { return false; }" + ); } 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]; @@ -599,30 +656,31 @@ "<input name=\"hubSearchButton\" id='hubSearchButton' " "class=\"hubField\" type=\"button\" value=\"Search Public Hubs\">\n", hgHubDbFilter, dbFilter!=NULL?dbFilter:""); jsOnEventById("click", "hubSearchButton", event); puts("<br><br>\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 <B>restricted by search terms:</B> %s\n", hubSearchTerms); puts("<input name=\"hubDeleteSearchButton\" id='hubDeleteSearchButton' " "class=\"hubField\" type=\"button\" value=\"Show All Hubs\">\n"); + jsOnEventById("click", "hubDeleteSearchButton", "document.searchHubForm.elements['hubSearchTerms'].value='';" "document.searchHubForm.elements['hubDbFilter'].value='';" "document.searchHubForm.submit();return true;"); puts("<BR><BR>\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("<BR><BR>\n"); } void printHubListHeader() /* Write out the header for a list of hubs in its own table */ { puts("<I>Clicking Connect redirects to the gateway page of the selected hub's default assembly.</I><BR>"); @@ -1595,43 +1653,63 @@ printf( "<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/themes/default/style.min.css\" />\n" "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js\"></script>\n" "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js\"></script>\n" "<style>.jstree-default .jstree-anchor { height: initial; } </style>\n" ); jsIncludeFile("utils.js", NULL); jsIncludeFile("jquery-ui.js", NULL); webIncludeResourceFile("jquery-ui.css"); jsIncludeFile("ajax.js", NULL); jsIncludeFile("hgHubConnect.js", NULL); webIncludeResourceFile("hgHubConnect.css"); jsIncludeFile("jquery.cookie.js", NULL); jsIncludeFile("spectrum.min.js", NULL); +boolean doHubDevMode = cfgOptionBooleanDefault("hgHubConnect.validateHub", FALSE); printf("<div id=\"hgHubConnectUI\"> <div id=\"description\"> \n"); printf( "<P>Track data hubs are collections of external tracks that can be imported into the UCSC Genome Browser. " "Hub tracks show up under the hub's own blue label bar on the main browser page, " "as well as on the configure page. For more information, including where to " "<A HREF=\"../goldenPath/help/hgTrackHubHelp.html#Hosting\">host</A> your track hub, see the " "<A HREF=\"../goldenPath/help/hgTrackHubHelp.html\" TARGET=_blank>" "User's Guide</A>." "To import a public hub click its \"Connect\" button below.</P>" "<P><B>NOTE: Because Track Hubs are created and maintained by external sources," " UCSC is not responsible for their content.</B></P>" ); printf("</div>\n"); +if (doHubDevMode) + { + printf("<div id=\"developerModeDescription\" style=\"display:none\"> \n"); + printf("<p>Check the configuration settings for a hub, including the settings " + "in the hub.txt, genomes.txt, and trackDb.txt files. If there are errors in the hub " + "setup, a heirarchal tree of tracks is presented with the errors in red text. A hub " + "with no errors still has the tree present but needs to be clicked to be expanded to " + " explore the track heirarchy.</p>\n" + "<p>Also present are buttons to load the hub with track timing measuring turned on " + "in order to profile slow loading tracks, and an option to disable the track caching " + "mechanism so the Genome Browser picks up changes to the configuration files or " + "track data files. For more information on making track hubs, please see the following links: \n " + "<ul>\n" + "<li><a href=\"../goldenPath/help/trackDb/trackDbHub.html\">Track Hub Settings</a></li> \n" + "<li><a href=\"../goldenPath/help/hgTrackHubHelp#Hosting\">Where to host your track hub</a></li> \n" + "</ul> \n" + "</div>\n " + ); + } // this variable is used by hub search and hub validate, initialize here so we don't // overwrite it unintentionally depending on which path the CGI takes jsInline("trackData = [];\n"); getDbAndGenome(cart, &database, &organism, oldVars); char *survey = cfgOptionEnv("HGDB_HUB_SURVEY", "hubSurvey"); char *surveyLabel = cfgOptionEnv("HGDB_HUB_SURVEY_LABEL", "hubSurveyLabel"); if (survey && differentWord(survey, "off")) hPrintf("<span style='background-color:yellow;'><A HREF='%s' TARGET=_BLANK><EM><B>%s</EM></B></A></span>\n", survey, surveyLabel ? surveyLabel : "Take survey"); hPutc('\n'); // grab all the hubs that are listed in the cart @@ -1670,72 +1748,103 @@ // this is the form for the reset hub button printf("<FORM ACTION=\"%s\" NAME=\"resetHubForm\">\n", "../cgi-bin/hgHubConnect"); cgiMakeHiddenVar(hgHubCheckUrl, ""); cartSaveSession(cart); 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"); cgiMakeHiddenVar(hgHubDbFilter, ""); cartSaveSession(cart); puts("</FORM>"); // this is the form for the validate button -boolean doValidate = cfgOptionBooleanDefault("hgHubConnect.validateHub", FALSE); -if (doValidate) +if (doHubDevMode) { printf("<FORM ACTION=\"%s\" NAME=\"validateHubForm\">\n", "../cgi-bin/hgHubConnect"); cgiMakeHiddenVar("validateHubUrl", ""); + // allows saving the old url in the search bar but not run hubCheck on it right away + // mostly for when you come back to hgHubConnect after just looking at hgTracks + cgiMakeHiddenVar(hgHubDoHubCheck, "off"); cartSaveSession(cart); puts("</FORM>"); } // ... and now the main form printf("<FORM ACTION=\"%s\" METHOD=\"POST\" NAME=\"mainForm\">\n", "../cgi-bin/hgGateway"); 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> "); -if (doValidate) // put up the validate tab if hg.conf statement present - printf("<li><a href=\"#validateHub\">Validate Hub</a></li>"); + "<ul> <li><a class=\"defaultDesc\" href=\"#publicHubs\">Public Hubs</a></li>" + "<li><a class=\"defaultDesc\" href=\"#unlistedHubs\">My Hubs</a></li> "); +if (doHubDevMode) // put up the validate tab if hg.conf statement present + printf("<li><a class=\"hubDeveloperDesc\" href=\"#hubDeveloper\">Hub Development</a></li>"); printf("</ul> "); struct hash *publicHash = hgHubConnectPublic(); hgHubConnectUnlisted(hubList, publicHash); -if (doValidate) - hgHubConnectValidateNewHub(); +if (doHubDevMode) + hgHubConnectDeveloperMode(); +// add the event listener for toggling the right description text +jsInline( + "var oldDesc = document.getElementById('description');\n" + "var newDesc = document.getElementById('developerModeDescription');\n" + "if (location.hash === \"#hubDeveloper\") {\n" + " toggleTwoDivs(newDesc, oldDesc);\n" + "}\n" + "window.addEventListener('hashchange', function() {\n" + " if (location.hash === \"#hubDeveloper\") {" + " toggleTwoDivs(newDesc, oldDesc);\n" + " } else {\n" + " toggleTwoDivs(oldDesc, newDesc);\n" + " }\n" + "});\n" + "var plusButton = document.getElementById('advancedSettingsButton');\n" + "plusButton.addEventListener('click', function() {\n" + " var advancedSettingsDiv = document.getElementById('extraSettingsContainer');\n" + " var extraSettingsList = document.getElementById('extraSettingsList');\n" + " if (extraSettingsList.style.display != 'none') {\n" + " extraSettingsList.style.display = 'none';\n" + " imgTag = advancedSettingsDiv.getElementsByTagName('img')[0];\n" + " imgTag.src = \"../images/add_sm.gif\";\n" + " } else {\n" + " extraSettingsList.style.display = 'block';\n" + " imgTag = advancedSettingsDiv.getElementsByTagName('img')[0];\n" + " imgTag.src = \"../images/remove_sm.gif\";\n" + " }\n" + "});" + ); printf("</div>"); printf("<div class=\"tabFooter\">"); printf("<span class=\"small\">" "Contact <a href=\"../contacts.html\">us</A> to add a public hub." "</span>\n"); printf("</div>"); cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on"); puts("</FORM>"); printf("</div>\n"); cartWebEnd(); } -char *excludeVars[] = {"Submit", "submit", "hc_one_url", "validateHubUrl", +char *excludeVars[] = {"Submit", "submit", "hc_one_url", hgHubDoHubCheck, hgHubCheckUrl, hgHubDoClear, hgHubDoDisconnect,hgHubDoRedirect, hgHubDataText, hgHubConnectRemakeTrackHub, NULL}; int main(int argc, char *argv[]) /* Process command line. */ { long enteredMainTime = clock1000(); oldVars = hashNew(10); cgiSpoof(&argc, argv); cartEmptyShell(doMiddle, hUserCookie(), excludeVars, oldVars); cgiExitTime("hgHubConnect", enteredMainTime); return 0; }