a727404f38d39890a83e81426cfe24ea940eaac6
chmalee
  Thu Jan 9 15:02:35 2025 -0800
Make tracks with period, and other 'forbidden' characters turn on when selecting them from the hubspace UI

diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js
index 53c271f..adbbadd 100644
--- src/hg/js/hgMyData.js
+++ src/hg/js/hgMyData.js
@@ -188,37 +188,43 @@
             choice.id = e;
             choice.label = e;
             choice.value = e;
             ret.push(choice);
         });
         return ret;
     }
 
     function viewInGenomeBrowser(fname, ftype, genome, hubName) {
         // redirect to hgTracks with this track open in the hub
         if (typeof uiState.userUrl !== "undefined" && uiState.userUrl.length > 0) {
             if (ftype in extensionMap) {
                 // TODO: tusd should return this location in it's response after
                 // uploading a file and then we can look it up somehow, the cgi can
                 // write the links directly into the html directly for prev uploaded files maybe?
-                let url = "../cgi-bin/hgTracks?hgsid=" + getHgsid() + "&db=" + genome + "&hubUrl=" + uiState.userUrl + hubName + "/hub.txt&" + fname + "=pack";
+                let url = "../cgi-bin/hgTracks?hgsid=" + getHgsid() + "&db=" + genome + "&hubUrl=" + uiState.userUrl + hubName + "/hub.txt&" + trackHubFixName(fname) + "=pack";
                 window.location.assign(url);
                 return false;
             }
         }
     }
 
+    const regex = /[^A-Za-z0-9_-]+/g;
+    function trackHubFixName(trackName) {
+        // replace everything but alphanumeric, underscore and dash with underscore
+        return trackName.replaceAll(regex, "_");
+    }
+
     // helper object so we don't need to use an AbortController to update
     // the data this function is using
     let selectedData = {};
     function viewAllInGenomeBrowser(ev) {
         // redirect to hgTracks with these tracks/hubs open
         let data = selectedData;
         if (typeof uiState.userUrl !== "undefined" && uiState.userUrl.length > 0) {
             let url = "../cgi-bin/hgTracks?hgsid=" + getHgsid();
             let genome; // may be multiple genomes in list, just redirect to the first one
                         // TODO: this should probably raise an alert to click through
             let hubsAdded = {};
             _.forEach(data, (d) => {
                 if (!genome) {
                     genome = d.genome;
                     url += "&db=" + genome;
@@ -229,31 +235,31 @@
                     // write the links directly into the html directly for prev uploaded files maybe?
                     if (!(d.parentDir in hubsAdded)) {
                         // NOTE: hubUrls get added regardless of whether they are on this assembly
                         // or not, because multiple genomes may have been requested. If this user
                         // switches to another genome we want this hub to be connected already
                         url += "&hubUrl=" + uiState.userUrl + d.parentDir;
                         if (d.parentDir.endsWith("/")) {
                             url += "hub.txt";
                         } else {
                             url += "/hub.txt";
                         }
                     }
                     hubsAdded[d.parentDir] = true;
                     if (d.genome == genome) {
                         // turn the track on if its for this db
-                        url += "&" + d.fileName + "=pack";
+                        url += "&" + trackHubFixName(d.fileName) + "=pack";
                     }
                 } else if (d.fileType === "hub.txt") {
                     url += "&hubUrl=" + uiState.userUrl + d.fullPath;
                 } 
             });
             window.location.assign(url);
             return false;
         }
     }
 
     function deleteFileSuccess(jqXhr, textStatus) {
         deleteFileFromTable(jqXhr.deletedList);
         updateSelectedFileDiv(null);
     }