1a2011f25ac0bd4ce02ed0eb093ff169724f9047 angie Mon May 2 16:39:23 2016 -0700 Added trackDb setting "tableBrowser noGenome", which allows tables to appear in TB and DI menus, unlike "tableBrowser off", but does not allow genome-wide queries on the tables. The new "noGenome" setting is used for OMIM tracks -- OMIM gave the OK for non-genome-wide queries on their tables. See #4458#note-53 for details of UI & functional changes to the TB and DI for noGenome tracks. hg/lib/cartTrackDb.c handles access control based on trackDb tableBrowser settings (and the seldom-used tableAccessControl database tables that restrict tables to be viewed only by certain hosts). As before, 'tableBrowser off' means that the track is removed from the trackList so the TB & DI don't even know that it exists. 'tableBrowser noGenome' tracks are included in the trackList, but the tracks and any tables listed after 'noGenome' are hashed for later use by cartTrackDbIsNoGenome(). The hash used to contain permitted-host lists, but now contains structs that combine the permitted-host lists with a noGenome flag. hgIntegrator.c now includes a 'noGenome' flag in the JSONified groupedTrackDb, which the JS code uses to identify noGenome tracks. When executing a query, if the query region is genome but hgi_querySpec has noGenome related tables left over from past position-only queries, those related table settings are removed from the parsed JSON querySpec->config->relatedTables that is passed down into annoStreamDb. If one of the dataSources is noGenome but the region is genome (should be possible only by URL-tweaking), the region is forced to position. In hgTables, when region is genome, correlation and intersection track menu options for noGenome tracks are disabled. On the main page, JS code controls whether options are disabled depending on the current region. When listing related tables for filtering or selected fields output, if region is genome then the checkboxes for noGenome tables are disabled. If the cart has noGenome related table or intersection settings left over from past searches, they are ignored. If a noGenome query URL is tweaked to have hgta_region=genome, the TB errors out. hgIntegratorModel.js handles disabling of menu options and related table field settings for noGenome tracks when region is genome. refs #4458 diff --git src/hg/hgTables/mainPage.c src/hg/hgTables/mainPage.c index 51c9ce3..624acf0 100644 --- src/hg/hgTables/mainPage.c +++ src/hg/hgTables/mainPage.c @@ -85,35 +85,42 @@ dyStringPrintf(dy, " document.hiddenForm.%s.value=0;", hgtaTable); return jsOnChangeEnd(&dy); } static char *onChangeTable() /* Return javascript executed when they change group. */ { struct dyString *dy = onChangeStart(); jsDropDownCarryOver(dy, "clade"); jsDropDownCarryOver(dy, "db"); jsDropDownCarryOver(dy, "org"); jsDropDownCarryOver(dy, hgtaTable); return jsOnChangeEnd(&dy); } +void makeRegionButtonExtraHtml(char *val, char *selVal, char *extraHtml) +/* Make region radio button including a little Javascript to save selection state + * and optional extra html attributes. */ +{ +jsMakeTrackingRadioButtonExtraHtml(hgtaRegionType, "regionType", val, selVal, extraHtml); +} + void makeRegionButton(char *val, char *selVal) /* Make region radio button including a little Javascript * to save selection state. */ { -jsMakeTrackingRadioButton(hgtaRegionType, "regionType", val, selVal); +makeRegionButtonExtraHtml(val, selVal, NULL); } struct grp *showGroupField(char *groupVar, char *groupScript, struct sqlConnection *conn, boolean allTablesOk) /* Show group control. Returns selected group. */ { struct grp *group, *groupList = fullGroupList; struct grp *selGroup = findSelectedGroup(groupList, groupVar); hPrintf("<B>group:</B>\n"); hPrintf("<SELECT NAME=%s %s>\n", groupVar, groupScript); for (group = groupList; group != NULL; group = group->next) { if (allTablesOk || differentString(group->name, "allTables")) hPrintf(" <OPTION VALUE=%s%s>%s\n", group->name, (group == selGroup ? " SELECTED" : ""), @@ -144,32 +151,32 @@ addIfExists(hash, &dbList, "ultra"); return dbList; } char *findSelDb() /* Find user selected database (as opposed to genome database). */ { struct slName *dbList = getDbListForGenome(); char *selDb = cartUsualString(cart, hgtaTrack, NULL); if (!slNameInList(dbList, selDb)) selDb = cloneString(dbList->name); slFreeList(&dbList); return selDb; } -struct trackDb *showTrackField(struct grp *selGroup, - char *trackVar, char *trackScript) +struct trackDb *showTrackField(struct grp *selGroup, char *trackVar, char *trackScript, + boolean disableNoGenome) /* Show track control. Returns selected track. */ { struct trackDb *track, *selTrack = NULL; if (trackScript == NULL) trackScript = ""; if (sameString(selGroup->name, "allTables")) { char *selDb = findSelDb(); struct slName *dbList = getDbListForGenome(), *db; hPrintf("<B>database:</B>\n"); hPrintf("<SELECT NAME=%s %s>\n", trackVar, trackScript); for (db = dbList; db != NULL; db = db->next) { hPrintf(" <OPTION VALUE=%s%s>%s\n", db->name, (sameString(db->name, selDb) ? " SELECTED" : ""), @@ -179,39 +186,54 @@ } else { boolean allTracks = sameString(selGroup->name, "allTracks"); hPrintf("<B>track:</B>\n"); hPrintf("<SELECT NAME=\"%s\" %s>\n", trackVar, trackScript); if (allTracks) { selTrack = findSelectedTrack(fullTrackList, NULL, trackVar); slSort(&fullTrackList, trackDbCmpShortLabel); } else { selTrack = findSelectedTrack(fullTrackList, selGroup, trackVar); } + boolean selTrackIsDisabled = FALSE; + struct trackDb *firstEnabled = NULL; for (track = fullTrackList; track != NULL; track = track->next) { if (allTracks || sameString(selGroup->name, track->grp)) { - hPrintf(" <OPTION VALUE=\"%s\"%s>%s\n", track->track, - (track == selTrack ? " SELECTED" : ""), - track->shortLabel); + hPrintf(" <OPTION VALUE=\"%s\"", track->track); + if (cartTrackDbIsNoGenome(database, track->table)) + hPrintf(NO_GENOME_CLASS); + if (disableNoGenome && isNoGenomeDisabled(database, track->table)) + { + hPrintf(" DISABLED"); + if (track == selTrack) + selTrackIsDisabled = TRUE; + } + else if (firstEnabled == NULL) + firstEnabled = track; + if (track == selTrack && !selTrackIsDisabled) + hPrintf(" SELECTED"); + hPrintf(">%s</OPTION>", track->shortLabel); } } + if (selTrackIsDisabled) + selTrack = firstEnabled; hPrintf("</SELECT>\n"); } hPrintf("\n"); return selTrack; } char *unsplitTableName(char *table) /* Convert chr*_name to name */ { if (startsWith("chr", table)) { char *s = strrchr(table, '_'); if (s != NULL) { table = s + 1; @@ -222,48 +244,48 @@ struct slName *tablesForDb(char *db) /* Find tables associated with database. */ { boolean isGenomeDb = sameString(db, database); struct sqlConnection *conn = hAllocConn(db); struct slName *raw, *rawList = sqlListTables(conn); struct slName *cooked, *cookedList = NULL; struct hash *uniqHash = newHash(0); hFreeConn(&conn); for (raw = rawList; raw != NULL; raw = raw->next) { + if (cartTrackDbIsAccessDenied(db, raw->name)) + continue; if (isGenomeDb) { /* Deal with tables split across chromosomes. */ char *root = unsplitTableName(raw->name); - if (cartTrackDbIsAccessDenied(db, root) || cartTrackDbIsAccessDenied(db, raw->name)) + if (cartTrackDbIsAccessDenied(db, root)) continue; if (!hashLookup(uniqHash, root)) { hashAdd(uniqHash, root, NULL); cooked = slNameNew(root); slAddHead(&cookedList, cooked); } } else { char dbTable[256]; - if (cartTrackDbIsAccessDenied(db, raw->name)) - continue; safef(dbTable, sizeof(dbTable), "%s.%s", db, raw->name); cooked = slNameNew(dbTable); slAddHead(&cookedList, cooked); } } hashFree(&uniqHash); slFreeList(&rawList); slSort(&cookedList, slNameCmp); return cookedList; } char *showTableField(struct trackDb *track, char *varName, boolean useJoiner) /* Show table control and label. */ { struct slName *name, *nameList = NULL; @@ -278,31 +300,36 @@ * then revert to first in list. */ selTable = cartUsualString(cart, varName, nameList->name); if (!slNameInListUseCase(nameList, selTable)) selTable = nameList->name; /* Print out label and drop-down list. */ hPrintf("<B>table: </B>"); hPrintf("<SELECT NAME=\"%s\" %s>\n", varName, onChangeTable()); struct trackDb *selTdb = NULL; for (name = nameList; name != NULL; name = name->next) { struct trackDb *tdb = NULL; if (track != NULL) tdb = findTdbForTable(database,track,name->name, ctLookupName); hPrintf("<OPTION VALUE=\"%s\"", name->name); - if (sameString(selTable, name->name)) + // Disable options for related tables that are noGenome -- if a non-positional table + // is selected then we output its entire contents. + if (cartTrackDbIsNoGenome(database, name->name) && + (track == NULL || differentString(track->table, name->name))) + hPrintf(" DISABLED"NO_GENOME_CLASS); + else if (sameString(selTable, name->name)) { hPrintf(" SELECTED"); selTdb = tdb; } if (tdb != NULL) if ((curTrack == NULL) || differentWord(tdb->shortLabel, curTrack->shortLabel)) hPrintf(">%s (%s)\n", tdb->shortLabel, name->name); else hPrintf(">%s\n", name->name); else hPrintf(">%s\n", name->name); } hPrintf("</SELECT>\n"); if (!trackHubDatabase(database)) { @@ -515,31 +542,31 @@ { hPrintf("<TR><TD><B>genome:</B>\n"); printGenomeListHtml(database, onChangeOrg()); } nbSpaces(3); hPrintf("<B>assembly:</B>\n"); printAssemblyListHtml(database, onChangeDb()); hPrintf("</TD></TR>\n"); } /* Print group and track line. */ { hPrintf("<TR><TD>"); selGroup = showGroupField(hgtaGroup, onChangeGroupOrTrack(), conn, hAllowAllTables()); nbSpaces(3); - curTrack = showTrackField(selGroup, hgtaTrack, onChangeGroupOrTrack()); + curTrack = showTrackField(selGroup, hgtaTrack, onChangeGroupOrTrack(), FALSE); nbSpaces(3); boolean hasCustomTracks = FALSE; struct trackDb *t; for (t = fullTrackList; t != NULL; t = t->next) { if (isCustomTrack(t->table)) { hasCustomTracks = TRUE; break; } } hOnClickButton("document.customTrackForm.submit();return false;", hasCustomTracks ? CT_MANAGE_BUTTON_LABEL : CT_ADD_BUTTON_LABEL); hPrintf(" "); @@ -599,33 +626,47 @@ char *range = cartUsualString(cart, hgtaRange, ""); if (isPositional) { boolean doEncode = FALSE; if (!trackHubDatabase(database)) doEncode = sqlTableExists(conn, "encodeRegions"); hPrintf("<TR><TD><B>region:</B>\n"); /* If regionType not allowed force it to "genome". */ if ((sameString(regionType, hgtaRegionTypeUserRegions) && userRegionsFileName() == NULL) || (sameString(regionType, hgtaRegionTypeEncode) && !doEncode)) regionType = hgtaRegionTypeGenome; + // Is "genome" is not allowed because of tdb 'tableBrowser noGenome'? + boolean disableGenome = ((curTrack && cartTrackDbIsNoGenome(database, curTrack->table)) || + (curTable && cartTrackDbIsNoGenome(database, curTable))); + // If "genome" is selected but not allowed, force it to "range": + if (sameString(regionType, hgtaRegionTypeGenome) && disableGenome) + regionType = hgtaRegionTypeRange; jsTrackingVar("regionType", regionType); + if (disableGenome) + { + makeRegionButtonExtraHtml(hgtaRegionTypeGenome, regionType, "DISABLED"); + hPrintf(" <span"NO_GENOME_CLASS">genome</span> "); + } + else + { makeRegionButton(hgtaRegionTypeGenome, regionType); hPrintf(" genome "); + } if (doEncode) { makeRegionButton(hgtaRegionTypeEncode, regionType); hPrintf(" ENCODE Pilot regions "); } makeRegionButton(hgtaRegionTypeRange, regionType); hPrintf(" position "); hPrintf("<INPUT TYPE=TEXT NAME=\"%s\" SIZE=26 VALUE=\"%s\" onFocus=\"%s\">\n", hgtaRange, range, jsRadioUpdate(hgtaRegionType, "regionType", "range")); cgiMakeButton(hgtaDoLookupPosition, "lookup"); hPrintf(" "); if (userRegionsFileName() != NULL) { makeRegionButton(hgtaRegionTypeUserRegions, regionType); hPrintf(" defined regions "); @@ -713,31 +754,31 @@ } else if (canIntersect(database, curTable)) { hPrintf("<TR><TD><B>intersection:</B>\n"); cgiMakeButton(hgtaDoIntersectPage, "create"); } hPrintf("</TD></TR>\n"); } /* Correlation line. */ struct trackDb *tdb = findTdbForTable(database, curTrack, curTable, ctLookupName); if (correlateTrackTableOK(tdb, curTable)) { char *table2 = cartUsualString(cart, hgtaCorrelateTable, "none"); hPrintf("<TR><TD><B>correlation:</B>\n"); - if (differentWord(table2,"none") && strlen(table2)) + if (differentWord(table2, "none") && strlen(table2) && ! isNoGenomeDisabled(database, table2)) { struct grp *groupList = fullGroupList; struct grp *selGroup = findSelectedGroup(groupList, hgtaCorrelateGroup); struct trackDb *tdb2 = findSelectedTrack(fullTrackList, selGroup,hgtaCorrelateTrack); if (tdbIsComposite(tdb2)) { struct slRef *tdbRefList = trackDbListGetRefsToDescendantLeaves(tdb2->subtracks); struct slRef *tdbRef; for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next) { struct trackDb *subTdb = tdbRef->val; if (sameString(table2, subTdb->table)) { tdb2 = subTdb; break; @@ -884,39 +925,52 @@ "MySQL server</A>. " "To examine the biological function of your set through annotation " "enrichments, send the data to " "<A HREF=\"http://great.stanford.edu\" target=_BLANK>GREAT</A>. " "%s" "Refer to the " "<A HREF=\"../goldenPath/credits.html\">Credits</A> page for the list of " "contributors and usage restrictions associated with these data. " "All tables can be downloaded in their entirety from the " "<A HREF=\"http://hgdownload.cse.ucsc.edu/downloads.html\"" ">Sequence and Annotation Downloads</A> page." , getGenomeSpaceText() ); hPrintf("<script type=\"text/javascript\">\n"); +// When GREAT is selected, disable the other checkboxes and force output to BED hPrintf("function onSelectGreat() {\n"); hPrintf("document.getElementById('checkboxGalaxy').checked=false;\n"); if (isGenomeSpaceEnabled()) hPrintf("document.getElementById('checkboxGenomeSpace').checked=false;\n"); hPrintf("document.getElementById('outBed').selected=true;\n"); hPrintf("return true;\n"); hPrintf("}\n"); -hPrintf("</script>\n"); - +// Disable/enable noGenome tracks depending on whether region is genome. +hPrintf("function maybeDisableNoGenome() {\n" + " var regionTypeSelected = $('input[name=\"hgta_regionType\"]:checked').val();\n" + " var regionIsGenome = (regionTypeSelected === 'genome');\n" + " var $noGenomeOptions = $('select[name=\"hgta_track\"] option.hgtaNoGenome');\n" + " $noGenomeOptions.attr('disabled', regionIsGenome)\n" + " .css('color', regionIsGenome ? '' : 'black');\n" + "}\n" + "$(document).ready(function() {\n" + // once when the page loads, and every time the user changes the region type: + " maybeDisableNoGenome();\n" + " $('input[name=\"hgta_regionType\"]').change(maybeDisableNoGenome);\n" + "});\n" + "</script>\n"); /* Main form. */ hPrintf("<FORM ACTION=\"%s\" NAME=\"mainForm\" METHOD=%s>\n", getScriptName(), cartUsualString(cart, "formMethod", "POST")); cartSaveSession(cart); jsInit(); showMainControlTable(conn); hPrintf("</FORM>\n"); /* Hidden form - for benefit of javascript. */ { static char *saveVars[] = { "clade", "org", "db", hgtaGroup, hgtaTrack, hgtaTable, hgtaRegionType, hgtaRange, hgtaOutputType, hgtaOutFileName}; jsCreateHiddenForm(cart, getScriptName(), saveVars, ArraySize(saveVars));