d033cea2063e9362949baf5b4d8b837597173a0d max Thu Sep 10 05:16:05 2026 -0700 Address the code review of the Sep 9 commits Faceted composite: text that comes from a hub - a metadata column's description, the name and title of a data type, and the values quoted back in the "could not load the metadata" row - is put on the page as text rather than as markup. The three places built their markup from template strings, so a value carrying angle brackets or a quote was read as HTML: the column description now goes through the shared htmlEncode() once where the header is parsed, and the other two build their elements as nodes. The error row reads better for it as well, since a value with brackets in it used to disappear from the message that was meant to show it. The saved UI state keys on the assembly as well as the metadata id. localStorage is per-origin, so two assemblies whose tracks share a name were sharing one entry, and a row order dragged on one came back on the other over a different set of samples. hgTrackUi passes the database down for it. State saved under the old key is dropped, which costs a facet selection or a page length. Imprinting: the five subtrack description pages link back to the container as hgTrackUi?db=$db&g=$parentTrack, without the hgsid. Native trackDb html is substituted by hgTrackDb as it loads the table, where there is no cart, so ${hgsid} came out empty and the link read 'hgsid=&g=...'. Matches what the Fiber-seq pages already do. The makeDoc note that described the old form is updated with the reason. UniProt otto: README.txt lists all eight things that reach runLog.txt. It had four, and was missing LOCKED, along with PREFLIGHT-FAIL, END and INTERRUPTED. refs #36210 refs #37599 refs #38300 diff --git src/hg/hgTrackUi/hgTrackUi.c src/hg/hgTrackUi/hgTrackUi.c index f38e4fb47ba..7c2f3306e9e 100644 --- src/hg/hgTrackUi/hgTrackUi.c +++ src/hg/hgTrackUi/hgTrackUi.c @@ -3294,30 +3294,34 @@ const char *nameStart = el->name + metaDataIdLen + 1; const char *nameEnd = strstr(nameStart, "_sel"); if (nameEnd && nameEnd > nameStart) { char *name = cloneStringZ(nameStart, nameEnd - nameStart); jsonWriteString(jw, NULL, name); freeMem(name); } } } hashElFreeList(&elList); } jsonWriteListEnd(jw); jsonWriteString(jw, "mdid", (char *)metaDataId); +// The javascript keys its saved UI state (facets, page length, dragged row +// order) on the assembly plus the metadata id, so two assemblies using the +// same track name do not share one entry in localStorage. +jsonWriteString(jw, "db", database); jsonWriteString(jw, "primaryKey", (char *)primaryKey); // must exist if (maxCheckboxes) // only if present in trackDb.settings entry jsonWriteString(jw, "maxCheckboxes", (char *)maxCheckboxes); if (colorSettingsUrl) // only if present in trackDb.settings entry jsonWriteString(jw, "colorSettingsUrl", cgiEncode((char *)colorSettingsUrl)); jsonWriteString(jw, "metadataUrl", cgiEncode((char *)metaDataUrl)); jsonWriteString(jw, "track", tdb->track); char *defaultSortField = trackDbSetting(tdb, "defaultSortField"); if (isNotEmpty(defaultSortField)) jsonWriteString(jw, "defaultSortField", defaultSortField); // How the user last sorted the faceted table, if they have. This overrides // defaultSortField in the javascript, which is the only side that can act on it - // turning field names into column positions needs the metadata file. The value // comes back from the cart, so it's untrusted, and this JSON lands inside a //