26f820467afa323064eb88e948348545e9dc010b max Fri Jul 29 14:31:08 2016 -0700 Adding a "Download All" button to the CIRM CDW. No redmine. diff --git src/hg/lib/tablesTables.c src/hg/lib/tablesTables.c index 2ec4a51..cdcfc0b 100644 --- src/hg/lib/tablesTables.c +++ src/hg/lib/tablesTables.c @@ -19,42 +19,44 @@ /* Return fieldedTable from a database query */ { struct sqlResult *sr = sqlGetResult(conn, query); char **fields; int fieldCount = sqlResultFieldArray(sr, &fields); struct fieldedTable *table = fieldedTableNew(query, fields, fieldCount); char **row; int i = 0; while ((row = sqlNextRow(sr)) != NULL) fieldedTableAdd(table, row, fieldCount, ++i); sqlFreeResult(&sr); return table; } static void showTableFilterInstructionsEtc(struct fieldedTable *table, - char *itemPlural, struct fieldedTableSegment *largerContext) + char *itemPlural, struct fieldedTableSegment *largerContext, void (*addFunc)(void)) /* Print instructional text, and basic summary info on who passes filter, and a submit * button just in case user needs it */ { /* Print info on matching */ int matchCount = slCount(table->rowList); if (largerContext != NULL) // Need to page? matchCount = largerContext->tableSize; cgiMakeButton("submit", "search"); printf("   "); printf("%d %s found. ", matchCount, itemPlural); +if (addFunc) + addFunc(); printf("<BR>\n"); printf("You can further filter search results field by field below. "); printf("Wildcard * and ? characters are allowed in text fields. "); printf(">min or <max are allowed in numerical fields.<BR>\n"); } static void printSuggestScript(char *id, struct slName *suggestList) /* Print out a little javascript to wrap auto-suggester around control with given ID */ { printf("<script>\n"); printf("$(document).ready(function() {\n"); printf(" $('#%s').autocomplete({\n", id); printf(" delay: 100,\n"); printf(" minLength: 0,\n"); @@ -279,89 +281,81 @@ char pageVar[64]; safef(pageVar, sizeof(pageVar), "%s_page", varPrefix); cgiMakeIntVar(pageVar, curPage+1, 3); printf(" of %d", totalPages); } } } void webFilteredFieldedTable(struct cart *cart, struct fieldedTable *table, char *returnUrl, char *varPrefix, int maxLenField, struct hash *tagOutputWrappers, void *wrapperContext, boolean withFilters, char *itemPlural, - int pageSize, struct fieldedTableSegment *largerContext, struct hash *suggestHash) + int pageSize, struct fieldedTableSegment *largerContext, struct hash *suggestHash, + void (*addFunc)(void) ) /* Show a fielded table that can be sorted by clicking on column labels and optionally * that includes a row of filter controls above the labels . * The maxLenField is maximum character length of field before truncation with ... * Pass in 0 for no max */ { if (strchr(returnUrl, '?') == NULL) errAbort("Expecting returnUrl to include ? in showFieldedTable\nIt's %s", returnUrl); if (withFilters) - showTableFilterInstructionsEtc(table, itemPlural, largerContext); + showTableFilterInstructionsEtc(table, itemPlural, largerContext, addFunc); /* Set up our table within table look. */ webPrintLinkTableStart(); /* Draw optional filters cells ahead of column labels*/ if (withFilters) showTableFilterControlRow(table, cart, varPrefix, maxLenField, suggestHash); showTableSortingLabelRow(table, cart, varPrefix, returnUrl); showTableDataRows(table, pageSize, maxLenField, tagOutputWrappers, wrapperContext); /* Get rid of table within table look */ webPrintLinkTableEnd(); if (largerContext != NULL) showTablePaging(table, cart, varPrefix, largerContext, pageSize); } void webSortableFieldedTable(struct cart *cart, struct fieldedTable *table, char *returnUrl, char *varPrefix, int maxLenField, struct hash *tagOutputWrappers, void *wrapperContext) /* Display all of table including a sortable label row. The tagOutputWrappers * is an optional way to enrich output of specific columns of the table. It is keyed * by column name and has for values functions of type webTableOutputWrapperType. */ { webFilteredFieldedTable(cart, table, returnUrl, varPrefix, maxLenField, tagOutputWrappers, wrapperContext, FALSE, NULL, - slCount(table->rowList), NULL, NULL); + slCount(table->rowList), NULL, NULL, NULL); } -void webFilteredSqlTable(struct cart *cart, struct sqlConnection *conn, - char *fields, char *from, char *initialWhere, - char *returnUrl, char *varPrefix, int maxFieldWidth, - struct hash *tagOutWrappers, void *wrapperContext, - boolean withFilters, char *itemPlural, int pageSize, struct hash *suggestHash) -/* Given a query to the database in conn that is basically a select query broken into - * separate clauses, construct and display an HTML table around results. This HTML table has - * column names that will sort the table, and optionally (if withFilters is set) - * it will also allow field-by-field wildcard queries on a set of controls it draws above - * the labels. - * Much of the functionality rests on the call to webFilteredFieldedTable. This function - * does the work needed to bring in sections of potentially huge results sets into - * the fieldedTable. */ +void webTableBuildQuery(struct cart *cart, char *from, char *initialWhere, + char *varPrefix, char *fields, boolean withFilters, + struct dyString **retQuery, struct dyString **retWhere) +/* Construct select, from and where clauses in query, keeping an additional copy of where + * Returns the SQL query and the SQL where expression as two dyStrings (need to be freed) */ { -/* Construct select, from and where clauses in query, keeping an additional copy of where */ struct dyString *query = dyStringNew(0); struct dyString *where = dyStringNew(0); struct slName *field, *fieldList = commaSepToSlNames(fields); boolean gotWhere = FALSE; sqlDyStringPrintf(query, "%s", ""); // TODO check with Galt on how to get reasonable checking back. dyStringPrintf(query, "select %s from %s", fields, from); if (!isEmpty(initialWhere)) { dyStringPrintf(where, " where "); sqlSanityCheckWhere(initialWhere, where); gotWhere = TRUE; } /* If we're doing filters, have to loop through the row of filter controls */ if (withFilters) @@ -413,48 +407,71 @@ } dyStringAppend(query, where->string); /* We do order here so as to keep order when working with tables bigger than a page. */ char orderVar[256]; safef(orderVar, sizeof(orderVar), "%s_order", varPrefix); char *orderFields = cartUsualString(cart, orderVar, ""); if (!isEmpty(orderFields)) { if (orderFields[0] == '-') dyStringPrintf(query, " order by %s desc", orderFields+1); else dyStringPrintf(query, " order by %s", orderFields); } +// return query and where expression +*retQuery = query; +*retWhere = where; +} + +void webFilteredSqlTable(struct cart *cart, struct sqlConnection *conn, + char *fields, char *from, char *initialWhere, + char *returnUrl, char *varPrefix, int maxFieldWidth, + struct hash *tagOutWrappers, void *wrapperContext, + boolean withFilters, char *itemPlural, int pageSize, struct hash *suggestHash, void (*addFunc)(void) ) +/* Given a query to the database in conn that is basically a select query broken into + * separate clauses, construct and display an HTML table around results. This HTML table has + * column names that will sort the table, and optionally (if withFilters is set) + * it will also allow field-by-field wildcard queries on a set of controls it draws above + * the labels. + * Much of the functionality rests on the call to webFilteredFieldedTable. This function + * does the work needed to bring in sections of potentially huge results sets into + * the fieldedTable. */ +{ +struct dyString *query; +struct dyString *where; +webTableBuildQuery(cart, from, initialWhere, varPrefix, fields, withFilters, &query, &where); + /* Figure out size of query result */ struct dyString *countQuery = dyStringNew(0); sqlDyStringPrintf(countQuery, "%s", ""); // TODO check with Galt on how to get reasonable checking back. dyStringPrintf(countQuery, "select count(*) from %s", from); dyStringAppend(countQuery, where->string); int resultsSize = sqlQuickNum(conn, countQuery->string); dyStringFree(&countQuery); char pageVar[64]; safef(pageVar, sizeof(pageVar), "%s_page", varPrefix); int page = 0; struct fieldedTableSegment context = { .tableSize=resultsSize}; if (resultsSize > pageSize) { page = cartUsualInt(cart, pageVar, 0) - 1; if (page < 0) page = 0; int lastPage = (resultsSize-1)/pageSize; if (page > lastPage) page = lastPage; context.tableOffset = page * pageSize; dyStringPrintf(query, " limit %d offset %d", pageSize, context.tableOffset); } struct fieldedTable *table = fieldedTableFromDbQuery(conn, query->string); webFilteredFieldedTable(cart, table, returnUrl, varPrefix, maxFieldWidth, - tagOutWrappers, wrapperContext, withFilters, itemPlural, pageSize, &context, suggestHash); + tagOutWrappers, wrapperContext, withFilters, itemPlural, pageSize, &context, suggestHash, addFunc); fieldedTableFree(&table); dyStringFree(&query); dyStringFree(&where); }