524d04aa83224bad2d1dcda060506694c858db0f chmalee Thu Nov 14 16:22:50 2024 -0800 Style the batch change selectors better, add a batch change hub name input diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js index 9c6ccb4..61d16a5 100644 --- src/hg/js/hgMyData.js +++ src/hg/js/hgMyData.js @@ -1,33 +1,34 @@ /* jshint esnext: true */ var debugCartJson = true; var hubNameDefault = "MyFirstHub"; function prettyFileSize(num) { if (!num) {return "n/a";} if (num < (1000 * 1024)) { - return `${(num/1000).toFixed(1)}kb`; + return `${(num/1000).toFixed(1)}KB`; } else if (num < (1000 * 1000 * 1024)) { - return `${((num/1000)/1000).toFixed(1)}mb`; + return `${((num/1000)/1000).toFixed(1)}MB`; } else { - return `${(((num/1000)/1000)/1000).toFixed(1)}gb`; + return `${(((num/1000)/1000)/1000).toFixed(1)}GB`; } } // 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; for (let [key, file] of Object.entries(files)) { if (!file.meta.genome) { uppy.info(`Error: No genome selected for file ${file.name}!`, 'error', 2000); doUpload = false; continue; } else if (!file.meta.fileType) { uppy.info(`Error: File type not supported, please rename file: ${file.name}!`, 'error', 2000); doUpload = false; continue; } uppy.setFileMeta(file.id, { fileName: file.name, @@ -900,59 +901,113 @@ */ } } removeBatchSelectsFromDashboard() { let batchSelectDiv = document.getElementById("batch-selector-div"); if (batchSelectDiv) { batchSelectDiv.remove(); } } addBatchSelectsToDashboard() { if (!document.getElementById("batch-selector-div")) { let batchSelectDiv = document.createElement("div"); batchSelectDiv.id = "batch-selector-div"; - let batchDbSelect = document.createElement("select"); - //let batchTypeSelect = document.createElement("select"); - this.createOptsForSelect(batchDbSelect, makeGenomeSelectOptions()); - //this.createOptsForSelect(batchTypeSelect, makeTypeSelectOptions()); - batchSelectDiv.textContent = "Change options for all files"; - batchSelectDiv.appendChild(batchDbSelect); - //batchSelectDiv.appendChild(batchTypeSelect); - batchSelectDiv.style.display = "flex"; - batchSelectDiv.style.justifyContent = "center"; + batchSelectDiv.style.display = "grid"; + batchSelectDiv.style.width = "80%"; + // the grid syntax is 2 columns, 3 rows + batchSelectDiv.style.gridTemplateColumns = "50% 50%"; + batchSelectDiv.style.gridTemplateRows = "25px 25px 25px"; + batchSelectDiv.style.margin = "10px auto"; // centers this div if (window.matchMedia("(prefers-color-scheme: dark)").matches) { batchSelectDiv.style.color = "#eaeaea"; } + + // first just explanatory text: + let batchSelectText = document.createElement("div"); + batchSelectText.textContent = "Change options for all files:"; + // syntax here is rowStart / columnStart / rowEnd / columnEnd + batchSelectText.style.gridArea = "1 / 1 / 1 / 2"; + + // the batch change db select + let batchDbSelect = document.createElement("select"); + this.createOptsForSelect(batchDbSelect, makeGenomeSelectOptions()); + batchDbSelect.id = "batchDbSelect"; + batchDbSelect.style.gridArea = "2 / 2 / 2 / 2"; + batchDbSelect.style.margin = "1px 1px auto"; + let batchDbLabel = document.createElement("label"); + batchDbLabel.textContent = "Genome"; + batchDbLabel.for = "batchDbSelect"; + batchDbLabel.style.gridArea = "2 / 1 / 2 / 1"; + + // the batch change hub name + let batchParentDirInput = document.createElement("input"); + batchParentDirInput.id = "batchParentDir"; + batchParentDirInput.value = hubNameDefault; + batchParentDirInput.style.gridArea = "3 / 2 / 3 / 2"; + batchParentDirInput.style.margin= "1px 1px auto"; + let batchParentDirLabel = document.createElement("label"); + batchParentDirLabel.textContent = "Hub Name"; + batchParentDirLabel.for = "batchParentDir"; + batchParentDirLabel.style.gridArea = "3 / 1 / 3 / 1"; + + // add event handlers to change metadata, use an arrow function + // because otherwise 'this' keyword will be the element instead of + // our class + batchDbSelect.addEventListener("change", (ev) => { + let files = this.uppy.getFiles(); + let val = ev.target.value; + for (let [key, file] of Object.entries(files)) { + this.uppy.setFileMeta(file.id, {genome: val}); + } + }); + batchParentDirInput.addEventListener("change", (ev) => { + let files = this.uppy.getFiles(); + let val = ev.target.value; + for (let [key, file] of Object.entries(files)) { + this.uppy.setFileMeta(file.id, {parentDir: val}); + } + }); + + batchSelectDiv.appendChild(batchSelectText); + batchSelectDiv.appendChild(batchDbLabel); + batchSelectDiv.appendChild(batchDbSelect); + batchSelectDiv.appendChild(batchParentDirLabel); + batchSelectDiv.appendChild(batchParentDirInput); + // append the batch changes to the bottom of the file list, for some reason // I can't append to the actual Dashboard-files, it must be getting emptied // and re-rendered or something let uppyFilesDiv = document.querySelector(".uppy-Dashboard-progressindicators"); if (uppyFilesDiv) { uppyFilesDiv.insertBefore(batchSelectDiv, uppyFilesDiv.firstChild); } } } install() { this.uppy.on("file-added", (file) => { // add default meta data for genome and fileType console.log("file-added"); this.uppy.setFileMeta(file.id, {"genome": defaultDb(), "fileType": defaultFileType(file.name), "parentDir": hubNameDefault}); if (this.uppy.getFiles().length > 1) { this.addBatchSelectsToDashboard(); + } else { + // only open the file editor when there is one file + const dash = uppy.getPlugin("Dashboard"); + dash.toggleFileCard(true, file.id); } }); this.uppy.on("file-removed", (file) => { // remove the batch change selects if now <2 files present if (this.uppy.getFiles().length < 2) { this.removeBatchSelectsFromDashboard(); } }); this.uppy.on("dashboard:modal-open", () => { // check if there were already files chosen from before: if (this.uppy.getFiles().length > 2) { this.addBatchSelectsToDashboard(); } if (this.uppy.getFiles().length < 2) { @@ -987,78 +1042,68 @@ value: value, onChange: e => { onChange(e.target.value); file.meta.fileType = detectFileType(e.target.value); }, required: required, form: form, } ); }, }, { id: 'genome', name: 'Genome', render: ({value, onChange}, h) => { - return h('select', - {onChange: e => onChange(e.target.value)}, - makeGenomeSelectOptions().map( (genomeObj) => { - return h('option', genomeObj, genomeObj.label); - }) - ); - }, - }, - /* - fields.push({ - id: 'fileType', - name: 'File Type', - render: ({value, onChange}, h) => { - return h( 'select', - {onChange: e => { - if (e.target.value === "Auto-detect from extension") { - onChange(detectFileType(file.name)); - } else { + return h('select', { + onChange: e => { onChange(e.target.value); + file.meta.genome = e.target.value; } - }}, - makeTypeSelectOptions().map( (typeObj) => { - return h('option', typeObj, typeObj.label); + }, + makeGenomeSelectOptions().map( (genomeObj) => { + return h('option', { + value: genomeObj.value, + label: genomeObj.label, + selected: file.meta.genome !== null ? genomeObj.value === file.meta.genome : genomeObj.value === defaultDb() + }); }) ); }, - }); - */ + }, { id: 'parentDir', name: 'Hub Name', render: ({value, onChange, required, form}, h) => { return h('input', {type: 'text', + value: value, + onChange: e => { + onChange(e.target.value); + }, required: required, form: form, - value: hubNameDefault, } ); }, }]; return fields; }, restricted: {requiredMetaFields: ["genome"]}, closeModalOnClickOutside: true, closeAfterFinish: true, theme: 'auto', - autoOpen: "metaEditor", }; let tusOptions = { endpoint: getTusdEndpoint(), withCredentials: true, retryDelays: null, }; uppy.use(Uppy.Dashboard, uppyOptions); uppy.use(Uppy.Tus, tusOptions); uppy.use(BatchChangePlugin, {target: Uppy.Dashboard}); uppy.on('upload-success', (file, response) => { const metadata = file.meta; const d = new Date(metadata.lastModified); newReqObj = { "uploadTime": Date.now(), "lastModified": d.toJSON(),