5a39815b8ab378d38285b805538121c591f82e07 kate Tue Jan 20 13:01:44 2015 -0800 Add 'subGroupMetaTables' setting to trackDb. This setting allows specification of a metadata table (minimally description+url) describing terms in a subgroup (e.g. hgFixed.wgEncodeCell for the 'cellType' subgroup in ENCODE tracks. This ia aimed at providing basic metadata functionality with lower overhead than the cv.ra + metaDb table used during ENCODE2. refs #14353 diff --git src/hg/lib/hui.c src/hg/lib/hui.c index fb55966..e4f8e89 100644 --- src/hg/lib/hui.c +++ src/hg/lib/hui.c @@ -4174,30 +4174,88 @@ else printf("<TD colspan=%d> ",columnCount); // Count of subtracks is filled in by javascript. if (subCount > 5) printf("<span class='subCBcount'></span>\n"); // Restriction policy needs a link if (restrictions && sortOrder != NULL) printf("</TD><TH><A HREF='%s' TARGET=BLANK style='font-size:.9em;'>Restriction Policy</A>", ENCODE_DATA_RELEASE_POLICY); printf("</TD></TR></TFOOT>\n"); } } +/********************/ +/* Metadata for subgroups */ + +struct meta { + char *term; + char *description; + char *url; +}; + +static struct hash *metaForAllSubGroupsGet(struct trackDb *parentTdb, struct cart *cart) +/* Get description and URL for all subgroupMetaTables. Returns a hash of hashes */ +{ +char *setting = trackDbSetting(parentTdb, "subGroupMetaTables"); +if (!setting) + return NULL; +struct slPair *metaTables = slPairFromString(setting); +struct hash *tableHash = hashNew(0); +struct slPair *metaTable; +struct sqlResult *sr; +char **row; +char query[256]; +char *database = cartString(cart, "db"); +char *db = database; +for (metaTable = metaTables; metaTable != NULL; metaTable = metaTables->next) + { + char *tableName = chopPrefix(cloneString(metaTable->val)); + if (differentString(tableName, metaTable->val)) + { + chopSuffix(metaTable->val); + db = metaTable->val; + } + struct sqlConnection *conn = hAllocConn(db); + boolean hasUrl = FALSE; + struct hash *subgroupHash = hashNew(0); + hashAdd(tableHash, metaTable->name, subgroupHash); + if (hHasField(db, tableName, "url")) + { + sqlSafef(query, sizeof(query), "select term, description, url from %s", tableName); + hasUrl = TRUE; + } + else + sqlSafef(query, sizeof(query), "select term, description from %s", tableName); + sr = sqlGetResult(conn, query); + while ((row = sqlNextRow(sr)) != NULL) + { + struct meta *meta = NULL; + AllocVar(meta); + meta->term = cloneString(row[0]); + meta->description = cloneString(row[1]); + if (hasUrl) + meta->url = cloneString(row[2]); + hashAdd(subgroupHash, meta->term, meta); + } +sqlFreeResult(&sr); + hFreeConn(&conn); + } +return tableHash; +} static void printSubtrackTableBody(struct trackDb *parentTdb, struct slRef *subtrackRefList, struct subtrackConfigSettings *settings, struct cart *cart) /* Print list of subtracks */ { sortOrder_t *sortOrder = settings->sortOrder; boolean useDragAndDrop = settings->useDragAndDrop; boolean restrictions = settings->restrictions; struct dyString *dyHtml = newDyString(SMALLBUF); char buffer[SMALLBUF]; char *db = cartString(cart, "db"); // The subtracks need to be sorted by priority but only sortable and dragable will have // non-default (cart) priorities to sort on boolean preSorted = FALSE; @@ -4205,30 +4263,31 @@ { // preserves user's prev sort/drags preSorted = tdbRefSortPrioritiesFromCart(cart, &subtrackRefList); printf("<TBODY class='%saltColors'>\n", (sortOrder != NULL ? "sortable " : "") ); } else { slSort(&subtrackRefList, trackDbRefCmp); // straight from trackDb.ra preSorted = TRUE; puts("<TBODY>"); } // Finally the big "for loop" to list each subtrack as a table row. printf("\n<!-- ----- subtracks list ----- -->\n"); membersForAll_t* membersForAll = membersForAllSubGroupsGet(parentTdb,NULL); +struct hash *subgroupMetaHash = metaForAllSubGroupsGet(parentTdb, cart); struct slRef *subtrackRef; /* Color handling ?? */ //char *colors[2] = { COLOR_BG_DEFAULT, // COLOR_BG_ALTDEFAULT }; char *colors[2] = { "bgLevel1", "bgLevel1" }; int colorIx = settings->bgColorIx; for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next) { struct trackDb *subtrack = subtrackRef->val; int ix; // Determine whether subtrack is checked, visible, configurable, has group membership, etc. @@ -4374,39 +4433,62 @@ } } printf("</TD>"); // If sortable, then there must be a column per sortable dimension if (sortOrder != NULL) { int sIx=0; for (sIx=0; sIx <sortOrder->count; sIx++) { char *col = sortOrder->column[sIx]; ix = stringArrayIx(col, membership->subgroups, membership->count); // TODO: Sort needs to expand from subGroups to labels as well if (ix >= 0) { + char *term = membership->membership[ix]; + char *title = membership->titles[ix]; char *titleRoot=NULL; - if (cvTermIsEmpty(col, membership->titles[ix])) + if (cvTermIsEmpty(col, title)) titleRoot = cloneString(" "); else - titleRoot = labelRoot(membership->titles[ix],NULL); + titleRoot = labelRoot(title, NULL); // Each sortable column requires hidden goop (in the "abbr" field currently) // which is the actual sort on value - printf("<TD id='%s_%s' abbr='%s' align='left'> ", - subtrack->track, col, membership->membership[ix]); + printf("<TD id='%s_%s' abbr='%s' align='left'>", subtrack->track, col, term); + printf(" "); + boolean printed = FALSE; + if (subgroupMetaHash) + { + struct hash *colHash = hashFindVal(subgroupMetaHash, col); + if (colHash) + { + struct meta *meta = hashFindVal(colHash, term); + if (meta != NULL) + { + if (meta->url == NULL || strlen(meta->url) == 0) + /* add pointer to suggest hover */ + printf("<A title='%s' style='cursor: pointer;'>%s</A>", + meta->description, titleRoot); + else + printf("<A target='_blank' class='cv' title='%s' href='%s'>%s</A>\n", + meta->description, meta->url, titleRoot); + printed = TRUE; + } + } + } + if (!printed) printf("%s",titleRoot); puts("</TD>"); freeMem(titleRoot); } else if (sameString(col, SUBTRACK_COLOR_SUBGROUP)) { char *hue = subtrackColorToCompare(subtrack); printf("<TD id='%s_%s' abbr='%s' bgcolor='#%02X%02X%02X'>" " </TD>", subtrack->track, col, hue, subtrack->colorR, subtrack->colorG, subtrack->colorB); } } } else // Non-sortable tables do not have sort by columns but will display a short label