102c601cb4dfad3f72902f38cd28d2d0ce803528 chmalee Wed Mar 19 15:41:09 2025 -0700 When files come in from hubtools, display the files and hub names decoded. Prevent hub names from having spaces in them, too tricky to get apache to play nice with those urls, refs #31058 diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js index 507bd807871..aed680bbca2 100644 --- src/hg/js/hgMyData.js +++ src/hg/js/hgMyData.js @@ -72,58 +72,58 @@ apiKeyInstr.style.display = "none"; document.getElementById("spinner").remove(); let generateDiv = document.getElementById("generateDiv"); generateDiv.style.display = "block"; let revokeDiv = document.getElementById("revokeDiv"); revokeDiv.style.display = "none"; }; let cartData = {revokeApiKey: {}}; cart.setCgi("hgHubConnect"); cart.send(cartData, handleSuccess); cart.flush(); } const fileNameRegex = /[0-9a-zA-Z._\-+]+/g; // allowed characters in file names -const parentDirRegex = /[0-9a-zA-Z._\-+ ]+/g; // allowed characters in hub names, spaces allowed +const parentDirRegex = /[0-9a-zA-Z._\-+]+/g; // allowed characters in hub names // make our Uppy instance: const uppy = new Uppy.Uppy({ debug: true, allowMultipleUploadBatches: false, onBeforeUpload: (files) => { // set all the fileTypes and genomes from their selects let doUpload = true; let thisQuota = 0; for (let [key, file] of Object.entries(files)) { let fileNameMatch = file.meta.name.match(fileNameRegex); let parentDirMatch = file.meta.parentDir.match(parentDirRegex); if (!fileNameMatch || fileNameMatch[0] !== file.meta.name) { - uppy.info(`Error: File name has special characters, please rename file: ${file.meta.name} to only include alpha-numeric characters, period, dash, underscore or plus.`, 'error', 2000); + uppy.info(`Error: File name has special characters, please rename file: ${file.meta.name} to only include alpha-numeric characters, period, dash, underscore or plus.`, 'error', 5000); doUpload = false; continue; } if (!parentDirMatch || parentDirMatch[0] !== file.meta.parentDir) { - uppy.info(`Error: Hub name has special characters, please rename file: ${file.meta.parentDir} to only include alpha-numeric characters, period, dash, underscore, plus or space.`, 'error', 2000); + uppy.info(`Error: Hub name has special characters, please rename file: ${file.meta.parentDir} to only include alpha-numeric characters, period, dash, underscore, or plus.`, 'error', 5000); doUpload = false; continue; } if (!file.meta.genome) { - uppy.info(`Error: No genome selected for file ${file.meta.name}!`, 'error', 2000); + uppy.info(`Error: No genome selected for file ${file.meta.name}!`, 'error', 5000); doUpload = false; continue; } else if (!file.meta.fileType) { - uppy.info(`Error: File type not supported, file: ${file.meta.name}!`, 'error', 2000); + uppy.info(`Error: File type not supported, file: ${file.meta.name}!`, 'error', 5000); doUpload = false; continue; } uppy.setFileMeta(file.id, { fileName: file.meta.name, fileSize: file.size, lastModified: file.data.lastModified, }); thisQuota += file.size; } if (thisQuota + hubCreate.uiState.userQuota > hubCreate.uiState.maxQuota) { uppy.info(`Error: this file batch exceeds your quota. Please delete some files to make space or email genome-www@soe.ucsc.edu if you feel you need more space.`); doUpload = false; } return doUpload; @@ -223,31 +223,31 @@ 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&" + trackHubFixName(fname) + "=pack"; + let url = "../cgi-bin/hgTracks?hgsid=" + getHgsid() + "&db=" + genome + "&hubUrl=" + uiState.userUrl + cgiEncode(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 encodeURIComponent(trackName).replaceAll(regex, "_"); } // helper object so we don't need to use an AbortController to update // the data this function is using let selectedData = {}; @@ -260,31 +260,31 @@ // TODO: this should probably raise an alert to click through let hubsAdded = {}; _.forEach(data, (d) => { if (!genome) { genome = d.genome; url += "&db=" + genome; } if (d.fileType 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? 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; + url += "&hubUrl=" + uiState.userUrl + cgiEncode(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 += "&" + trackHubFixName(d.fileName) + "=pack"; } } else if (d.fileType === "hub.txt") { url += "&hubUrl=" + uiState.userUrl + d.fullPath; } }); @@ -742,30 +742,39 @@ if (type === "display") { return dataTablePrintSize(data, type, row, meta); } return data; } }, { targets: 5, render: function(data, type, row) { if (type === "display") { return dataTablePrintGenome(data); } return data; } }, + { + targets: 6, + render: function(data, type, row) { + if (type === "display") { + return cgiDecode(data); + } + return data; + } + }, { // The upload time column targets: 8, visible: true, searchable: false, orderable: true, }, { targets: 9, visible: false, searchable: false, orderable: true, } ], columns: [