06a403144f20a2aa46ff4ee5f810f06e27869ef5 chmalee Tue Feb 10 16:05:26 2026 -0800 Fix visual bug in hubSpaceUI, sometimes when adding new rows to the DataTable, we get confused and show the directory row and table headers twice, refs #36830 diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js index 834372566c2..9dd31e0fa85 100644 --- src/hg/js/hgMyData.js +++ src/hg/js/hgMyData.js @@ -1089,30 +1089,47 @@ } } } function deleteFileFromTable(pathList) { // req is an object with properties of an uploaded file, make a new row // for it in the filesTable let table = $("#filesTable").DataTable(); let rows = table.rows((idx, data) => pathList.includes(data.fullPath)); rows.remove().draw(); let toKeep = (elem) => !pathList.includes(elem.fullPath); pathList.forEach((f) => { updateQuota(-uiState.filesHash[f].fileSize); }); uiState.fileList = uiState.fileList.filter(toKeep); + // Rebuild filesHash from remaining fileList to remove stale entries + uiState.filesHash = {}; + parseFileListIntoHash(uiState.fileList); + // If the currently viewed hub directory was deleted (its data is in oldRowData + // because dataTableCustomOrder moved it to the header), clean up that stale state + if (oldRowData && pathList.includes(oldRowData.fullPath)) { + let thead = document.querySelector( + ".dt-scroll-headInner > table:nth-child(1) > thead:nth-child(1)"); + if (thead && thead.childNodes.length > 1) { + thead.removeChild(thead.lastChild); + } + oldRowData = null; + dataTableShowTopLevel(table); + dataTableEmptyBreadcrumb(table); + table.order([{name: "uploadTime", dir: "desc"}]); + table.draw(); + } history.replaceState(uiState, "", document.location.href); } function addFileToHub(rowData) { // a file has been uploaded and a hub has been created, present a modal // to choose which hub to associate this track to // backend wise: move the file into the hub directory // update the hubSpace row with the hub name // frontend wise: move the file row into a 'child' of the hub row console.log(`sending addToHub req for ${rowData.fileName} to `); cart.setCgiAndUrl(fileListEndpoint); cart.send({addToHub: {hubName: "", dataFile: ""}}); cart.flush(); } @@ -1155,31 +1172,36 @@ if (rowData.fullPath === obj.fullPath) { table.row(allRows[j]).invalidate(); break; } } } } // show all the new rows we just added, note the double draw, we need // to have the new rows rendered to do the order because the order // will copy the actual DOM node parseFileListIntoHash(uiState.fileList); dataTableShowDir(table, hubDirData.fileName, hubDirData.fullPath); table.draw(); dataTableCustomOrder(table, hubDirData); - table.columns.adjust().draw(); + // Flush dataTableCustomOrder's row.remove() so DataTables internal state is clean, + // then defer columns.adjust() to allow browser reflow after header DOM manipulation + table.draw(); + setTimeout(function() { + table.columns.adjust(); + }, 0); } function doRowSelect(evtype, table, indexes) { let selectedRow = table.row(indexes); let rowTr = selectedRow.node(); if (rowTr) { handleCheckboxSelect(evtype, table, selectedRow); } } function indentActionButton(rowTr, rowData) { let numIndents = "0px"; //data.parentDir !== "" ? data.fullPath.split('/').length - 1: 0; if (rowData.fileType !== "dir") { numIndents = "10px"; }