7864ddf3a6d058dbe29f706519921cd55ccc4c67
chmalee
Thu May 2 09:04:45 2024 -0700
Work in progress on building form for choosing db and hub along with files to submit
diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js
index 2859570..dff2ea5 100644
--- src/hg/js/hgMyData.js
+++ src/hg/js/hgMyData.js
@@ -52,32 +52,30 @@
let li = document.getElementById(liId);
return li;
}
function newButton(text) {
/* Creates a new button with some text as the label */
let newBtn = document.createElement("label");
newBtn.classList.add("button");
newBtn.textContent = text;
return newBtn;
}
function createInput() {
/* Create a new input element for a file picker */
let input = document.createElement("input");
- //input.style.opacity = 0;
- //input.style.float = "right";
input.multiple = true;
input.type = "file";
input.id = "hiddenFileInput";
input.style = "display: none";
input.addEventListener("change", listPickedFiles);
return input;
}
function requestsPending() {
/* Return true if requests are still pending, which means it needs to
* have been sent(). aborted requests are considered done for this purpose */
for (let [req, f] of uiState.pendingQueue) {
if (req._req !== null) {
xreq = req._req._xhr;
if (xreq.readyState != XMLHttpRequest.DONE && xreq.readyState != XMLHttpRequest.UNSENT) {
@@ -150,30 +148,31 @@
ele.appendChild(progMeter);
progMeter.ctx = progMeter.getContext('2d');
progMeter.ctx.fillStyle = 'orange';
progMeter.updateProgress = (percent) => {
// update the progress meter for this elem
if (percent === 100) {
progMeter.ctx.fillStyle = 'green';
}
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) {
// 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;
@@ -263,53 +262,102 @@
submitBtn.id = "submitPicked";
submitBtn.classList.add("button");
submitBtn.textContent = "Submit";
submitBtn.addEventListener("click", submitPickedFiles);
btnRow.append(submitBtn);
}
}
function removeClearSubmitButtons() {
let btn = document.getElementById("clearPicked");
btn.parentNode.removeChild(btn);
btn = document.getElementById("submitPicked");
btn.parentNode.removeChild(btn);
}
+ function makeGenomeSelect(formName, fileName) {
+ let genomeInp = document.createElement("select");
+ genomeInp.classList.add("genomePicker");
+ genomeInp.name = `${fileName}#genomeInput`;
+ genomeInp.id = `${fileName}#genomeInput`;
+ genomeInp.form = formName;
+ return genomeInp;
+ }
+
+ function makeTypeSelect(formName, fileName) {
+ let typeInp = document.createElement("select");
+ typeInp.classList.add("typePicker");
+ typeInp.name = `${fileName}#typeInput`;
+ typeInp.id = `${fileName}#typeInput`;
+ let choices = ["hub.txt", "bigBed", "bam", "vcf", "bigWig"];
+ choices.forEach( (e) => {
+ let choice = document.createElement("option");
+ choice.id = e;
+ choice.label = e;
+ choice.value = e;
+ typeInp.appendChild(choice);
+ });
+ typeInp.form = formName;
+ return typeInp;
+ }
+
+ function makeHubSelect(formName, fileName) {
+ let hubInp = document.createElement("select");
+ hubInp.classList.add("hubPicker");
+ hubInp.name = `${fileName}#hubInput`;
+ hubInp.id = `${fileName}#hubInput`;
+ hubInp.form = formName;
+ }
+
+ function makeFormControlsForFile(li, formName, fileName) {
+ typeInp = makeTypeSelect(formName, fileName);
+ genomeInp = makeGenomeSelect(formName, fileName);
+ hubInp = makeGenomeSelect(formName, fileName);
+ li.append(typeInp);
+ li.append(genomeInp);
+ li.append(hubInp);
+ }
+
function listPickedFiles() {
- //uiState.input.click(); // let the user choose files:
+ // let the user choose files:
if (uiState.input.files.length === 0) {
console.log("not input");
return;
- //togglePickStateMessage(true);
- //removeClearSubmitButtons();
} else {
- let displayList = document.getElementsByClassName("pickedFiles");
- if (displayList.length === 0) {
+ let displayList;
+ let displayListForm = document.getElementsByClassName("pickedFilesForm");
+ if (displayListForm.length === 0) {
+ displayListForm = document.createElement("form");
+ displayListForm.id = "displayListForm";
+ displayListForm.classList.add("pickedFilesForm");
displayList = document.createElement("ul");
displayList.classList.add("pickedFiles");
- uiState.pickedList.appendChild(displayList);
+ displayListForm.appendChild(displayList);
+ uiState.pickedList.appendChild(displayListForm);
} else {
- displayList = displayList[0];
+ displayList = displayListForm[0].firstChild;
}
for (let file of uiState.input.files ) {
if (file.name in uiState.toUpload) { continue; }
// create a list for the user to see
let li = document.createElement("li");
li.classList.add("pickedFile");
li.id = `${file.name}#li`;
li.textContent = `File name: ${file.name}, file size: ${prettyFileSize(file.size)}`;
+ // Add the form controls for this file:
+ makeFormControlsForFile(li, "displayListForm", file.name);
+
displayList.appendChild(li);
// finally add it for us
uiState.toUpload[file.name] = file;
}
togglePickStateMessage(false);
addClearSubmitButtons();
}
// always clear the input element
uiState.input = createInput();
}
function dataTablePrintSize(data, type, row, meta) {
return prettyFileSize(data);
}
@@ -328,31 +376,31 @@
// 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();
deleteFileFromTable(rowIx, fname);
delete pendingDeletes[endpoint];
}
}
function viewInGenomeBrowser(rowIx, fname) {
- // redirect to hgTracks with this track as a custom track
+ // 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);
return false;
}
}
}
}
@@ -370,111 +418,103 @@
let tableInitOptions = {
//columnDefs: [{orderable: false, targets: [0,1]}],
columnDefs: [
{
orderable: false, targets: 0,
title: "",
render: function(data, type, row) {
return "";
}
},
{
orderable: false, targets: 1,
data: "action", title: "Action",
render: function(data, type, row) {
- // TODO: add event handler on delete button
// click to call hgHubDelete file
return "";
}
},
{
targets: 3,
render: function(data, type, row) {
return dataTablePrintSize(data);
}
}
],
columns: [
{data: "", },
{data: "", },
+ {data: "hub", title: "Hub"},
+ {data: "genome", title: "Genome"},
{data: "name", title: "File name"},
{data: "size", title: "File size", render: dataTablePrintSize},
{data: "createTime", title: "Creation Time"},
],
- order: [[4, 'desc']],
+ 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;
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;
btns[i].addEventListener("click", (e) => {
viewInGenomeBrowser(i, fname);
});
}
},
};
function showExistingFiles(d) {
// Make the DataTable for each file
- //$(document).on("draw.dt", function() {alert("table redrawn");});
tableInitOptions.data = d;
let table = $("#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) {
console.log('from server:\n', jsonData);
}
return true;
}
return false;
}
function updateStateAndPage(jsonData, doSaveHistory) {
// Update uiState with new values and update the page.
_.assign(uiState, jsonData);
- /*
- urlVars = {"db": db, "search": uiState.search, "showSearchResults": ""};
- // changing the url allows the history to be associated to a specific url
- var urlParts = changeUrl(urlVars);
- if (doSaveHistory)
- saveHistory(uiState, urlParts);
- changeSearchResultsLabel();
- */
}
function handleRefreshState(jsonData) {
if (checkJsonData(jsonData, 'handleRefreshState')) {
updateStateAndPage(jsonData, true);
}
$("#spinner").remove();
}
function init() {
cart.setCgi('hgMyData');
cart.debug(debugCartJson);
if (!useTus) {
console.log("tus is not supported, falling back to XMLHttpRequest");
}