3a88c02326aadbb1df3436cd519f7b8a4df6ae5b
chmalee
  Thu Jun 6 15:32:15 2024 -0700
Work in progress using the mysql table for hubSpace on client side

diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js
index 2c1377b..23d174b 100644
--- src/hg/js/hgMyData.js
+++ src/hg/js/hgMyData.js
@@ -156,82 +156,91 @@
             progMeter.ctx.fillRect(0, 0, (progMeterWidth * percent) / 100, progMeterHeight);
         };
         progMeter.updateProgress(0);
         return progMeter;
     }
 
     function submitPickedFiles() {
         
         let tusdServer = getTusdEndpoint();
 
         let onBeforeRequest = function(req) {
             let xhr = req.getUnderlyingObject(req);
             xhr.withCredentials = true;
         };
 
-        let onSuccess = function(req) {
+        let onSuccess = function(req, metadata) {
             // remove the selected file from the input element and the ul list
             // FileList is a read only setting, so we have to make
             // a new one without this req
             delete uiState.toUpload[req.name];
             let i, newReqObj = {};
             for (i = 0; i < uiState.pendingQueue.length; i++) {
                 fname = uiState.pendingQueue[i][1].name;
                 if (fname === req.name) {
                     // remove the successful tusUpload off
                     uiState.pendingQueue.splice(i, 1);
                 }
             }
             // remove the file from the list the user can see
             let li = document.getElementById(req.name+"#li");
             li.parentNode.removeChild(li);
             if (uiState.pendingQueue.length === 0) {
                 removeCancelAllButton();
             }
             const d = new Date(req.lastModified);
-            newReqObj = {"createTime": d.toJSON(), "name": req.name, "size": req.size};
+            newReqObj = {
+                "createTime": d.toJSON(),
+                "fileName": metadata.fileName,
+                "fileSize": metadata.fileSize,
+                "fileType": metadata.fileType,
+                "genome": metadata.genome,
+                "hub": ""
+            };
             addNewUploadedFileToTable(newReqObj);
         };
 
         let onError = function(err) {
             removeCancelAllButton();
             if (err.originalResponse !== null) {
                 alert(err.originalResponse._xhr.responseText);
             } else {
                 alert(err);
             }
         };
 
         let onProgress = function(bytesSent, bytesTotal) {
             this.updateProgress((bytesSent / bytesTotal) * 100);
         };
 
         for (let f in uiState.toUpload) {
             file = uiState.toUpload[f];
             if (useTus) {
                 let progMeter = makeNewProgMeter(file.name);
-                let tusOptions = {
-                    endpoint: tusdServer,
-                    metadata: {
-                        filename: file.name,
+                let metadata = {
+                    fileName: file.name,
                     fileSize: file.size,
                     fileType: document.getElementById(`${file.name}#typeInput`).selectedOptions[0].value,
                     genome: document.getElementById(`${file.name}#genomeInput`).selectedOptions[0].value,
-                    },
+                    lastModified: file.lastModified,
+                };
+                let tusOptions = {
+                    endpoint: tusdServer,
+                    metadata: metadata,
                     onProgress: onProgress.bind(progMeter),
                     onBeforeRequest: onBeforeRequest,
-                    onSuccess: onSuccess.bind(null, file),
+                    onSuccess: onSuccess.bind(null, file, metadata),
                     onError: onError,
                     retryDelays: null,
                 };
                 // TODO: get the uploadUrl from the tusd server
                 // use a pre-create hook to validate the user
                 // and get an uploadUrl
                 let tusUpload = new tus.Upload(file, tusOptions);
                 uiState.pendingQueue.push([tusUpload, file]);
                 tusUpload.start();
             } else {
                 // make a new XMLHttpRequest for each file, if tusd-tusclient not supported
                 new sendFile(file);
             }
         }
         addCancelAllButton();
@@ -366,62 +375,58 @@
             togglePickStateMessage(false);
             addClearSubmitButtons();
         }
         // always clear the input element
         uiState.input = createInput();
     }
 
     function dataTablePrintSize(data, type, row, meta) {
         return prettyFileSize(data);
     }
 
     function deleteFileFromTable(rowIx, fname) {
         // req is an object with properties of an uploaded file, make a new row
         // for it in the filesTable
         let table = $("#filesTable").DataTable();
-        let row = table.row((idx, data) => data.name === fname);
+        let row = table.row((idx, data) => data.fileName === fname);
         row.remove().draw();
     }
 
-    let pendingDeletes = {};
     function deleteFile(rowIx, fname) {
         // Send an async request to hgHubConnect to delete the file
         // Note that repeated requests, like from a bot, will return 404 as a correct response
         console.log(`sending delete req for ${fname}`);
-        const endpoint = "../cgi-bin/hgHubConnect?deleteFile=" + fname;
-        if (!(endpoint in pendingDeletes)) {
-            const xhr = new XMLHttpRequest();
-            pendingDeletes[endpoint] = xhr;
-            this.xhr = xhr;
-            this.xhr.open("DELETE", endpoint, true);
-            this.xhr.send();
+        cart.setCgi("hgHubConnect");
+        cart.send({deleteFile: {fileNameList: [fname]}});
+        cart.flush();
         deleteFileFromTable(rowIx, fname);
-            delete pendingDeletes[endpoint];
     }
+
+    function deleteFileList() {
     }
 
-    function viewInGenomeBrowser(rowIx, fname) {
+    function viewInGenomeBrowser(fname, genome) {
         // redirect to hgTracks with this track open in the hub
         if (typeof uiState.userUrl !== "undefined" && uiState.userUrl.length > 0) {
             bigBedExts = [".bb", ".bigBed", ".vcf.gz", ".vcf", ".bam", ".bw", ".bigWig"];
             let i;
             for (i = 0; i < bigBedExts.length; i++) {
                 if (fname.toLowerCase().endsWith(bigBedExts[i].toLowerCase())) {
                     // 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?
-                    window.location.assign("../cgi-bin/hgTracks?db=hg38&hgt.customText=" + uiState.userUrl + fname);
+                    window.location.assign("../cgi-bin/hgTracks?db=" + genome + "&hgt.customText=" + uiState.userUrl + fname);
                     return false;
                 }
             }
         }
     }
 
     function addNewUploadedFileToTable(req) {
         // req is an object with properties of an uploaded file, make a new row
         // for it in the filesTable
         let table = null;
         if ($.fn.dataTable.isDataTable("#filesTable")) {
             table = $("#filesTable").DataTable();
             let newRow = table.row.add(req).draw();
         } else {
             showExistingFiles([req]);
@@ -444,63 +449,63 @@
                 render: function(data, type, row) {
                     // click to call hgHubDelete file
                     return "<button class='deleteFileBtn'>Delete</button><button class='viewInBtn'>View In GB</button>";
                 }
             },
             {
                 targets: 3,
                 render: function(data, type, row) {
                     return dataTablePrintSize(data);
                 }
             }
         ],
         columns: [
             {data: "", },
             {data: "", },
+            {data: "fileName", title: "File name"},
+            {data: "fileSize", title: "File size", render: dataTablePrintSize},
+            {data: "fileType", title: "File type"},
             {data: "genome", title: "Genome"},
-            {data: "name", title: "File name"},
-            {data: "size", title: "File size", render: dataTablePrintSize},
+            {data: "hub", title: "Hubs"},
             {data: "createTime", title: "Creation Time"},
         ],
         order: [[6, 'desc']],
         drawCallback: function(settings) {
-            let btns = document.querySelectorAll('.deleteFileBtn');
-            let i;
-            for (i = 0; i < btns.length; i++) {
-                let fnameNode = btns[i].parentNode.nextElementSibling.childNodes[0];
-                if (fnameNode.nodeName !== "#text") {continue;}
-                let fname = fnameNode.nodeValue;
+            let table = this.DataTable();
+            btns = document.querySelectorAll('.deleteFileBtn');
+            let i, numRows= table.rows().data().length;
+            for (i = 0; i < numRows; i++) {
+                let fname = table.cell(i, 2).data();
                 btns[i].addEventListener("click", (e) => {
                     deleteFile(i, fname);
                 });
             }
             btns = document.querySelectorAll('.viewInBtn');
-            for (i = 0; i < btns.length; i++) {
-                let fnameNode = btns[i].parentNode.nextElementSibling.childNodes[0];
-                if (fnameNode.nodeName !== "#text") {continue;}
-                let fname = fnameNode.nodeValue;
+            for (i = 0; i < numRows; i++) {
+                let fname = table.cell(i, 2).data();
+                let genome = table.cell(i, 5).data();
                 btns[i].addEventListener("click", (e) => {
-                    viewInGenomeBrowser(i, fname);
+                    viewInGenomeBrowser(fname, genome);
                 });
             }
         },
     };
 
     function showExistingFiles(d) {
         // Make the DataTable for each file
         tableInitOptions.data = d;
-        let table = $("#filesTable").DataTable(tableInitOptions);
+        $("#filesTable").DataTable(tableInitOptions);
     }
 
     function checkJsonData(jsonData, callerName) {
         // Return true if jsonData isn't empty and doesn't contain an error;
         // otherwise complain on behalf of caller.
         if (! jsonData) {
             alert(callerName + ': empty response from server');
         } else if (jsonData.error) {
             console.error(jsonData.error);
             alert(callerName + ': error from server: ' + jsonData.error);
         } else if (jsonData.warning) {
             alert("Warning: " + jsonData.warning);
             return true;
         } else {
             if (debugCartJson) {