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 ""; } }, { 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) {