a66704e3ade50461e9be68288199903410f4f31e braney Fri Oct 11 12:36:01 2019 -0700 remove EXTRA_FIELDS support which was a failed experiment, support "." syntax with FILTER_TEXT, suppress automatic filter if text filter is set. diff --git src/hg/lib/hui.c src/hg/lib/hui.c index f1edce5..f053484 100644 --- src/hg/lib/hui.c +++ src/hg/lib/hui.c @@ -3626,31 +3626,30 @@ strSwapChar(chipper,'_',' '); // Title does not have underscores } else if (filterBy->valueAndLabel) errAbort("filterBy values either all have labels in form of value|label " "or none do."); } } } char *extractFieldName(char *cartVariable, char *filterType) /* Extract field name from a filter cart variable. Variables can either be * <columnName>Filter* or <columnName>.Filter* */ { char *field = cloneString(cartVariable); int ix = strlen(field) - strlen(filterType); -assert(ix > 1); field[ix] = '\0'; if (field[ix - 1] == '.') field[ix - 1] = '\0'; return field; } filterBy_t *buildFilterBy(struct trackDb *tdb, struct cart *cart, struct asObject *as, char *filterName, char *name) /* Build a filterBy_t structure from a <column>FilterValues statement. */ { char *field = extractFieldName(filterName, FILTER_VALUES_NAME); char *setting = trackDbSetting(tdb, filterName); if (isEmpty(setting)) errAbort("FilterValues setting of field '%s' must have a value.", field); @@ -3979,31 +3978,37 @@ filterBy_t *filterBy = NULL; if (cartOptionalString(cart, "ajax") == NULL) { webIncludeResourceFile("ui.dropdownchecklist.css"); jsIncludeFile("ui.dropdownchecklist.js",NULL); jsIncludeFile("ddcl.js",NULL); } int ix=0; for(filterBy = filterBySet;filterBy != NULL; filterBy = filterBy->next, ix++) { char settingString[4096]; safef(settingString, sizeof settingString, "%s%s", filterBy->column, FILTER_TYPE_NAME); - char *setting = cartOrTdbString(cart, tdb, settingString, FILTERBY_MULTIPLE_LIST_AND); + char *setting = cartOrTdbString(cart, tdb, settingString, NULL); + if (setting == NULL) + { + safef(settingString, sizeof settingString, "%s.%s", filterBy->column, FILTER_TYPE_NAME); + setting = cartOrTdbString(cart, tdb, settingString, FILTERBY_MULTIPLE_LIST_AND); + } + boolean isMultiple = sameString(setting, FILTERBY_MULTIPLE) ||sameString(setting, FILTERBY_MULTIPLE_LIST_OR) ||sameString(setting, FILTERBY_MULTIPLE_LIST_AND); puts("<TD>"); char selectStatement[4096]; if (isMultiple) safef(selectStatement, sizeof selectStatement, " (select multiple items - %s)", FILTERBY_HELP_LINK); else selectStatement[0] = 0; if(count == 1) printf("<B>%s by %s</B>%s",filterTypeTitle,filterBy->title,selectStatement); else printf("<B>%s</B>",filterBy->title); printf("<BR>\n"); if (isMultiple && tdbIsBigBed(tdb)) @@ -5945,97 +5950,73 @@ } return FALSE; } static int numericFiltersShowAll(char *db, struct cart *cart, struct trackDb *tdb, boolean *opened, boolean boxed, boolean parentLevel,char *name, char *title) // Shows all *Filter style filters. Note that these are in random order and have no graceful title { int count = 0; struct slName *filterSettings = trackDbSettingsWildMatch(tdb, FILTER_NUMBER_WILDCARD); if (filterSettings) { puts("<BR>"); struct slName *filter = NULL; -#ifdef EXTRA_FIELDS_SUPPORT - struct extraField *extras = extraFieldsGet(db,tdb); -#else///ifndef EXTRA_FIELDS_SUPPORT struct sqlConnection *conn = NULL; if (!isHubTrack(db)) conn = hAllocConnTrack(db, tdb); struct asObject *as = asForTdb(conn, tdb); hFreeConn(&conn); -#endif///ndef EXTRA_FIELDS_SUPPORT while ((filter = slPopHead(&filterSettings)) != NULL) { if (differentString(filter->name,NO_SCORE_FILTER)) { // Determine floating point or integer char *setting = trackDbSetting(tdb, filter->name); boolean isFloat = (strchr(setting,'.') != NULL); char *scoreName = cloneString(filter->name); char *field = extractFieldName(filter->name, FILTER_NUMBER_NAME); - #ifdef EXTRA_FIELDS_SUPPORT - if (extras != NULL) - { - struct extraField *extra = extraFieldsFind(extras, field); - if (extra != NULL) - { // Found label so replace field - field = extra->label; - if (!isFloat) - isFloat = (extra->type == ftFloat); - } - } - #else///ifndef EXTRA_FIELDS_SUPPORT if (as != NULL) { struct asColumn *asCol = asColumnFind(as, field); if (asCol != NULL) { // Found label so replace field field = asCol->comment; if (!isFloat) isFloat = asTypesIsFloating(asCol->lowType->type); } else errAbort("Building filter on field %s which is not in AS file.", field); } - #endif///ndef EXTRA_FIELDS_SUPPORT - // FIXME: Label munging should be localized to showScoreFilter() - // when that function is simplified char varName[256]; char label[128]; safef(varName, sizeof(varName), "%s%s", scoreName, _BY_RANGE); boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, varName); safef(label, sizeof(label),"%s%s", filterByRange ? "": "Minimum ", field); showScoreFilter(cart,tdb,opened,boxed,parentLevel,name,title,label,scoreName,isFloat); freeMem(scoreName); count++; } slNameFree(&filter); } -#ifdef EXTRA_FIELDS_SUPPORT - if (extras != NULL) - extraFieldsFree(&extras); -#else///ifndef EXTRA_FIELDS_SUPPORT if (as != NULL) asObjectFree(&as); -#endif///ndef EXTRA_FIELDS_SUPPORT } if (count > 0) puts("</TABLE>"); return count; } boolean bedScoreHasCfgUi(struct trackDb *tdb) // Confirms that this track has a bedScore Cfg UI { // Assumes that cfgType == cfgBedScore if (trackDbSettingClosestToHome(tdb, FILTER_BY)) return TRUE; if (trackDbSettingClosestToHome(tdb, GRAY_LEVEL_SCORE_MIN)) return TRUE; @@ -6057,83 +6038,93 @@ one = TRUE; break; } } slNameFreeList(&filterSettings); if (one) return TRUE; } if (!blocked) // scoreFilter is implicit unless NO_SCORE_FILTER return TRUE; return FALSE; } -void textFiltersShowAll(char *db, struct cart *cart, struct trackDb *tdb) +static int textFiltersShowAll(char *db, struct cart *cart, struct trackDb *tdb) /* Show all the text filters for this track. */ { +int count = 0; struct slName *filter, *filterSettings = trackDbSettingsWildMatch(tdb, FILTER_TEXT_WILDCARD); if (filterSettings) { struct sqlConnection *conn = NULL; if (!isHubTrack(db)) conn = hAllocConnTrack(db, tdb); while ((filter = slPopHead(&filterSettings)) != NULL) { char *setting = trackDbSetting(tdb, filter->name); char *value = cartUsualStringClosestToHome(cart, tdb, FALSE, filter->name, setting); char *field = extractFieldName(filter->name, FILTER_TEXT_NAME); struct asObject *as = asForTdb(conn, tdb); struct asColumn *asCol = asColumnFind(as, field); if (asCol == NULL) errAbort("Building filter on field %s which is not in AS file.", field); + count++; printf("<P><B>Filter items in '%s' field: ", field); char cgiVar[128]; safef(cgiVar,sizeof(cgiVar),"%s.%s",tdb->track,filter->name); cgiMakeTextVar(cgiVar, value, 45); char settingString[4096]; safef(settingString, sizeof settingString, "%s%s", field, FILTER_TYPE_NAME); + setting = cartOrTdbString(cart, tdb, settingString, NULL); + if (setting == NULL) + { + safef(settingString, sizeof settingString, "%s.%s", field, FILTER_TYPE_NAME); setting = cartOrTdbString(cart, tdb, settingString, FILTERTEXT_WILDCARD); + } safef(cgiVar,sizeof(cgiVar),"%s.%s",tdb->track,settingString); printf(" using "); printf("<SELECT name='%s'> ", cgiVar); printf("<OPTION %s>%s</OPTION>", sameString(setting, FILTERTEXT_WILDCARD) ? "SELECTED" : "", FILTERTEXT_WILDCARD ); printf("<OPTION %s>%s</OPTION>", sameString(setting, FILTERTEXT_REGEXP) ? "SELECTED" : "", FILTERTEXT_REGEXP ); printf("</SELECT>"); printf("</P>"); } } + +return count; } void scoreCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *name, char *title, int maxScore, boolean boxed) // Put up UI for filtering bed track based on a score { char option[256]; boolean parentLevel = isNameAtParentLevel(tdb,name); boolean skipScoreFilter = FALSE; // Numeric filters are first boolean isBoxOpened = FALSE; if (numericFiltersShowAll(db, cart, tdb, &isBoxOpened, boxed, parentLevel, name, title) > 0) skipScoreFilter = TRUE; -textFiltersShowAll(db, cart, tdb); +if (textFiltersShowAll(db, cart, tdb)) + skipScoreFilter = TRUE; // Add any multi-selects next filterBy_t *filterBySet = filterBySetGet(tdb,cart,name); if (filterBySet != NULL) { if (!tdbIsComposite(tdb) && cartOptionalString(cart, "ajax") == NULL) jsIncludeFile("hui.js",NULL); if (!isBoxOpened) // Note filterBy boxes are not double "boxed", printf("<BR>"); // if there are no other filters filterBySetCfgUi(cart,tdb,filterBySet,TRUE, name); filterBySetFree(&filterBySet); skipScoreFilter = TRUE; } @@ -8936,137 +8927,30 @@ if (tableName) { char *date = firstWordInLine(sqlTableUpdate(conn, tableName)); if (date != NULL) printf("<B>Data last updated: </B>%s<BR>\n", date); } hFreeConn(&conn); } void printBbiUpdateTime(time_t *timep) /* for bbi files, print out the timep value */ { printf("<B>Data last updated: </B>%s<BR>\n", sqlUnixTimeToDate(timep, FALSE)); } -#ifdef EXTRA_FIELDS_SUPPORT -static struct extraField *asFieldsGet(char *db, struct trackDb *tdb) -// returns the as style fields from a table or remote data file -{ -struct extraField *asFields = NULL; -struct sqlConnection *conn = hAllocConnTrack(db, tdb); -struct asObject *as = asForTdb(conn, tdb); -hFreeConn(&conn); -if (as != NULL) - { - struct asColumn *asCol = as->columnList; - for (;asCol != NULL; asCol = asCol->next) - { - struct extraField *asField = NULL; - AllocVar(asField); - asField->name = cloneString(asCol->name); - if (asCol->comment != NULL && strlen(asCol->comment) > 0) - asField->label = cloneString(asCol->comment); - else - asField->label = cloneString(asField->name); - asField->type = ftString; // default - if (asTypesIsInt(asCol->lowType->type)) - asField->type = ftInteger; - else if (asTypesIsFloating(asCol->lowType->type)) - asField->type = ftFloat; - slAddHead(&asFields,asField); - } - if (asFields != NULL) - slReverse(&asFields); - asObjectFree(&as); - } -return asFields; -} - -struct extraField *extraFieldsGet(char *db, struct trackDb *tdb) -// returns any extraFields defined in trackDb -{ -char *fields = trackDbSetting(tdb, "extraFields"); // showFileds pValue=P_Value qValue=qValue -if (fields == NULL) - return asFieldsGet(db, tdb); - -char *field = NULL; -struct extraField *extras = NULL; -struct extraField *extra = NULL; -while (NULL != (field = cloneNextWord(&fields))) - { - AllocVar(extra); - extra->name = field; - extra->label = field; // defaults to name - char *equal = strchr(field,'='); - if (equal != NULL) - { - *equal = '\0'; - extra->label = equal + 1; - assert(*(extra->label)!='\0'); - } - - extra->type = ftString; - if (*(extra->label) == '[') - { - if (startsWith("[i",extra->label)) - extra->type = ftInteger; - else if (startsWith("[f",extra->label)) - extra->type = ftFloat; - extra->label = strchr(extra->label,']'); - assert(extra->label != NULL); - extra->label += 1; - } - // clone independently of 'field' and swap in blanks - extra->label = cloneString(strSwapChar(extra->label,'_',' ')); - slAddHead(&extras,extra); - } - -if (extras != NULL) - slReverse(&extras); -return extras; -} - -struct extraField *extraFieldsFind(struct extraField *extras, char *name) -// returns the extraField matching the name (case insensitive). Note: slNameFind does NOT work. -{ -struct extraField *extra = extras; -for (; extra != NULL; extra = extra->next) - { - if (sameWord(name, extra->name)) - break; - } -return extra; -} - -void extraFieldsFree(struct extraField **pExtras) -// frees all mem for extraFields list -{ -if (pExtras != NULL) - { - struct extraField *extra = NULL; - while (NULL != (extra = slPopHead(pExtras))) - { - freeMem(extra->name); - freeMem(extra->label); - freeMem(extra); - } - *pExtras = NULL; - } -} -#endif///def EXTRA_FIELDS_SUPPORT - static boolean tableDescriptionsExists(struct sqlConnection *conn) /* Cache flag for whether tableDescriptions exists in conn, in case we will need to * fetch a lot of descriptions from tableDescriptions. */ { static struct hash *hash = NULL; if (hash == NULL) hash = hashNew(0); char *db = sqlGetDatabase(conn); int exists = hashIntValDefault(hash, db, -1); if (exists < 0) { exists = sqlTableExists(conn, "tableDescriptions"); hashAddInt(hash, db, exists); } return (boolean)exists;