2f4dc5368794ef8eb09e43c27420703b7cf6135f
chmalee
  Mon Feb 23 11:22:17 2026 -0800
Save ucsc databases to 'Genomes' menu bar recents list when adding genomes to the recents list from not hgGateway. Make urls to genark hubs correct, refs #36535

diff --git src/hg/js/utils.js src/hg/js/utils.js
index 4351a59028a..596622cb539 100644
--- src/hg/js/utils.js
+++ src/hg/js/utils.js
@@ -4497,47 +4497,67 @@
     if (!stored) return;
     let recentObj = JSON.parse(stored);
     let newStack = [];
     for (let key of recentObj.stack) {
         let item = recentObj.results[key];
         if (item && item.hubUrl === hubUrl) {
             delete recentObj.results[key];
         } else {
             newStack.push(key);
         }
     }
     recentObj.stack = newStack;
     window.localStorage.setItem("recentGenomes", JSON.stringify(recentObj));
 }
 
+function recentGenomeHref(res) {
+    // Build an hgTracks URL for a recent genome entry. GenArk assemblies need
+    // db=, genome=, and a fully qualified hubUrl= so that fixUpDb() and
+    // hubConnectLoadHubs() in cartNew() can connect the hub. UCSC native
+    // databases just need db=.
+    let db = res.db || res.genome;
+    let url = new URL("../cgi-bin/hgTracks", window.location.href);
+    url.searchParams.set("hgsid", getHgsid());
+    url.searchParams.set("db", db);
+    url.searchParams.set("position", "lastDbPos");
+    if (res.hubUrl) {
+        // The findGenome API returns a relative hubUrl (e.g. GCA/.../hub.txt)
+        // while hgGateway stores it already prefixed (e.g. /gbdb/genark/GCA/.../hub.txt).
+        let hubUrl = res.hubUrl;
+        if (!hubUrl.startsWith("/gbdb/genark/")) {
+            hubUrl = "/gbdb/genark/" + hubUrl;
+        }
+        url.searchParams.set("genome", db);
+        url.searchParams.set("hubUrl", window.location.origin + hubUrl);
+    }
+    return url.toString();
+}
+
 function addRecentGenomesToMenuBar() {
     // Retrieve recent genome selections from localStorage and add them to the "Genomes" menu heading
     // Tries not add duplicate genomes
     let stored = window.localStorage.getItem("recentGenomes");
     if (!stored) return;
 
     let recentObj = JSON.parse(stored);
     let results = [];
     for (let genome of recentObj.stack) {
         if (recentObj.results[genome]) {
             let item = document.createElement("li");
             let link = document.createElement("a");
-            // TODO: these links need to work if the result (ie: genark) does not have a db
-            let res = recentObj.results[genome];
-            dbOrGenome = 'hubUrl' in res ? res.hubName + "_" + res.db : res.db;
-            link.href = "../cgi-bin/hgTracks?hgsid=" + getHgsid() + "&db=" + dbOrGenome + "&position=lastDbPos";
-            link.textContent = res.label;
+            link.href = recentGenomeHref(recentObj.results[genome]);
+            link.textContent = recentObj.results[genome].label;
             item.appendChild(link);
             results.push(item);
         }
     }
 
     // construct the current list of labels
     const labelList = [];
     document.querySelectorAll("#tools1 > ul > li > a").forEach( (a) => {
         labelList.push(a.textContent);
     });
 
     // filter our list of recents against the list of "Genomes"
     let finalResult = results.filter( (result) => {
         return !labelList.includes(result.firstChild.textContent);
     });
@@ -4752,35 +4772,35 @@
     // process the hubApi/findGenome?q= result set into somthing
     // jquery-ui autocomplete can use
     let data = [];
     let apiSkipList = new Set(["downloadTime", "downloadTimeStamp", "availableAssemblies", "browser", "elapsedTimeMs", "itemCount", "q", "totalMatchCount", "liftable"]);
     Object.keys(result).forEach((key) => {
         if (!(apiSkipList.has(key))) {
             let val = result[key];
             let d = {
                 "genome": key,
                 "label": `${val.commonName} (${key})`,
             };
 
             Object.keys(val).forEach((vkey) => {
                 d[vkey] = val[vkey];
             });
+            // Set db to the key (database name or accession) so the autocomplete
+            // select handler can save it to recent genomes
+            d.db = key;
             if (val.hubUrl !== null) {
                 d.category = "UCSC GenArk - bulk annotated assemblies from NCBI GenBank / Refseq";
-                // For GenArk items, ensure db is set to the accession (key) for consistent
-                // identification in recent genomes storage (avoids duplicate entries)
-                d.db = key;
             } else {
                 d.category = "UCSC Genome Browser assemblies - annotation tracks curated by UCSC";
             }
             data.push(d);
         }
     });
     return data;
 }
 
 function initSpeciesAutoCompleteDropdown(inputId, selectFunction, baseUrl = null,
         watermark = null, onServerReply = null, onError = null) {
 /* Generic function for turning an <input> element into a species search bar with an autocomplete
  * list separating results by category.
  * Required arguments:
  *     inputId: id of the input element itself, not created here