513ff234094b883276ecb289fd9839792e2ddb20 chmalee Tue Nov 3 16:39:53 2020 -0800 First cut of custom table on hgc, no styling diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c index ba387101..de5d206 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -1538,85 +1538,157 @@ for (count = 0; col != NULL && count < fieldCount; col = col->next) { struct slPair *field; AllocVar(field); char *fieldName = col->name; char *fieldVal = row[count]; field->name = fieldName; field->val = fieldVal; slAddHead(&fields, field); count++; } slReverse(fields); return fields; } +void printExtraDetailsTable(char *trackName, char *tableName, char *fileName, struct dyString *tableText) +// convert a tab-sep table to HTML +{ +struct lineFile *lf = lineFileOnString(fileName, TRUE, tableText->string); +char *description = tableName != NULL ? tableName : "Additional Details"; +printf(""); +jsBeginCollapsibleSection(cart, trackName, "extraTbl", description, FALSE); +printf("
\n"); +char *line; +while (lineFileNext(lf, &line, NULL)) + { + printf("\n"); + } +printf("
"); + char *toPrint = replaceChars(line, "\t", ""); + printf("%s", toPrint); + printf("
\n"); // closes bedExtraTbl +jsEndCollapsibleSection(); +printf("\n"); // close wrapper table +} + +static struct slName *findFieldsInExtraFile(char *detailsTableUrl, struct asColumn *col, struct dyString *ds) +// return a list of the ${}-enclosed fields from an extra file +{ +struct slName *foundFields = NULL; +char *table = netReadTextFileIfExists(hReplaceGbdb(detailsTableUrl)); +if (table) + { + for (; col != NULL; col = col->next) + { + char field[256]; + safef(field, sizeof(field), "${%s}", col->name); + if (stringIn(field, table)) + { + struct slName *replaceField = slNameNew(col->name); + slAddHead(&foundFields, replaceField); + } + } + dyStringPrintf(ds, "%s", table); + slReverse(foundFields); + } +return foundFields; +} + int extraFieldsPrintAs(struct trackDb *tdb,struct sqlResult *sr,char **fields,int fieldCount, struct asObject *as) // Any extra bed or bigBed fields (defined in as and occurring after N in bed N + types. // sr may be null for bigBeds. // Returns number of extra fields actually printed. { // We are trying to print extra fields so we need to figure out how many fields to skip int start = extraFieldsStart(tdb, fieldCount, as); struct asColumn *col = as->columnList; char *urlsStr = trackDbSettingClosestToHomeOrDefault(tdb, "urls", NULL); struct hash* fieldToUrl = hashFromString(urlsStr); boolean skipEmptyFields = trackDbSettingOn(tdb, "skipEmptyFields"); // make list of fields to skip char *skipFieldsStr = trackDbSetting(tdb, "skipFields"); struct slName *skipIds = NULL; if (skipFieldsStr) skipIds = slNameListFromComma(skipFieldsStr); // make list of fields that are separated from other fields char *sepFieldsStr = trackDbSetting(tdb, "sepFields"); struct slName *sepFields = NULL; if (sepFieldsStr) sepFields = slNameListFromComma(sepFieldsStr); +// make list of fields that we want to substitute +// this setting has format description|URLorFilePath, with the stuff before the pipe optional +char *extraDetailsTableName = NULL, *extraDetails = cloneString(trackDbSetting(tdb, "extraDetailsTable")); +if (extraDetails && strchr(extraDetails,'|')) + { + extraDetailsTableName = extraDetails; + extraDetails = strchr(extraDetails,'|'); + *extraDetails++ = 0; + } +struct dyString *extraTblStr = dyStringNew(0); +struct slName *detailsTableFields = NULL; +if (extraDetails) + detailsTableFields = findFieldsInExtraFile(extraDetails, col, extraTblStr); + // iterate over fields, print as table rows int count = 0; for (;col != NULL && count < fieldCount;col=col->next) { if (start > 0) // skip past already known fields { start--; continue; } int ix = count; if (sr != NULL) { ix = sqlFieldColumn(sr, col->name); // If sr provided, name must match sql columnn name! if (ix == -1 || ix > fieldCount) // so extraField really just provides a label continue; } char *fieldName = col->name; if (count == 0) printf("
"); count++; // do not print a row if the fieldName from the .as file is in the "skipFields" list // or if a field name starts with _. This maked bigBed extra fields consistent with // external extra fields in that _ field names have some meaning and are not shown if (startsWith("_", fieldName) || (skipIds && slNameInList(skipIds, fieldName))) continue; + // don't print this field if we are gonna print it later in a custom table + if (detailsTableFields && slNameInList(detailsTableFields, fieldName)) + { + int fieldLen = strlen(fieldName); + char *replaceField = needMem(fieldLen+4); + replaceField[0] = '$'; + replaceField[1] = '{'; + strcpy(replaceField+2, fieldName); + replaceField[fieldLen+2] = '}'; + replaceField[fieldLen+3] = 0; + extraTblStr = dyStringSub(extraTblStr->string, replaceField, fields[ix]); + continue; + } + // skip this row if it's empty and "skipEmptyFields" option is set if (skipEmptyFields && isEmpty(fields[ix])) continue; // split this table to separate current row from the previous one, if the trackDb option is set if (sepFields && slNameInList(sepFields, fieldName)) printf("
\n

\n"); // field description char *entry; if (sameString(fieldName, "cdsStartStat") && sameString("enum('none','unk','incmpl','cmpl')", col->comment)) entry = "Status of CDS start annotation (none, unknown, incomplete, or complete)"; else if (sameString(fieldName, "cdsEndStat") && sameString("enum('none','unk','incmpl','cmpl')", col->comment)) entry = "Status of CDS end annotation (none, unknown, incomplete, or complete)"; else @@ -1632,30 +1704,36 @@ printf("\n", valDouble); else printf("\n", fields[ix]); // decided not to print error } else printf("\n", fields[ix]); } if (skipIds) slFreeList(skipIds); if (sepFields) slFreeList(sepFields); if (count > 0) printf("
%g
%s
%s
\n"); +if (detailsTableFields) + { + printf("
\n"); + printExtraDetailsTable(tdb->track, extraDetailsTableName, extraDetails, extraTblStr); + } + return count; } int extraFieldsPrint(struct trackDb *tdb,struct sqlResult *sr,char **fields,int fieldCount) // Any extra bed or bigBed fields (defined in as and occurring after N in bed N + types. // sr may be null for bigBeds. // Returns number of extra fields actually printed. { struct asObject *as = asForDb(tdb, database); if (as == NULL) return 0; int ret = extraFieldsPrintAs(tdb, sr, fields,fieldCount, as); //asObjectFree(&as);