0f1759077310950597e9c3da02fd41aea006ed98
chmalee
  Fri Mar 21 10:28:03 2025 -0700
Remove the delete button when a hub.txt row was explicitly selected so users cannot delete them without deleting the entire hub, otherwise they can delete hub.txt files and then have no easy way to view their track files, refs #31058

diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js
index d94658e4b84..46f2e79e207 100644
--- src/hg/js/hgMyData.js
+++ src/hg/js/hgMyData.js
@@ -306,63 +306,70 @@
         _.forEach(data, (d) => {
             cartData.deleteFile.fileList.push({
                 fileName: d.fileName,
                 fileType: d.fileType,
                 parentDir: d.parentDir,
                 genome: d.genome,
                 fullPath: d.fullPath,
             });
         });
         cart.send(cartData, deleteFileSuccess);
         cart.flush();
     }
 
     function updateSelectedFileDiv(data, isFolderSelect = false) {
         // update the div that shows how many files are selected
-        let numSelected = data !== null ? Object.entries(data).length : 0;
+        let numSelected = data !== null ? data.length : 0;
+        // if a hub.txt file is in data, disable the delete button
+        let disableDelete = data.filter((obj) => obj.fileType === "hub.txt").length > 0;
         let infoDiv = document.getElementById("selectedFileInfo");
         let span = document.getElementById("numberSelectedFiles");
         let spanParentDiv = span.parentElement;
         if (numSelected > 0) {
             if (isFolderSelect || span.textContent.endsWith("hub") || span.textContent.endsWith("hubs")) {
                 span.textContent = `${numSelected} ${numSelected > 1 ? "hubs" : "hub"}`;
             } else {
                 span.textContent = `${numSelected} ${numSelected > 1 ? "files" : "file"}`;
             }
             // (re) set up the handlers for the selected file info div:
             let viewBtn = document.getElementById("viewSelectedFiles");
             viewBtn.addEventListener("click", viewAllInGenomeBrowser);
             viewBtn.textContent = "View selected";
+            if (!disableDelete) {
                 let deleteBtn = document.getElementById("deleteSelectedFiles");
+                deleteBtn.style.display = "inline-block";
                 deleteBtn.addEventListener("click", deleteFileList);
                 deleteBtn.textContent = "Delete selected";
+            } else {
+                // delete the old button:
+                let deleteBtn = document.getElementById("deleteSelectedFiles");
+                deleteBtn.style.display = "none";
+            }
         } else {
             span.textContent = "";
         }
 
         // set the visibility of the placeholder text and info text
         spanParentDiv.style.display = numSelected === 0 ? "none": "block";
         let placeholder = document.getElementById("placeHolderInfo");
         placeholder.style.display = numSelected === 0 ? "block" : "none";
     }
 
     function handleCheckboxSelect(evtype, table, selectedRow) {
         // depending on the state of the checkbox, we will be adding information
         // to the div, or removing information. We also potentially checked/unchecked
-        // all of the checkboxes if the selectAll box was clicked. If isFolderSelect
-        // is true, then in the info div, display that a hub was selected and not just
-        // a file(s)
+        // all of the checkboxes if the selectAll box was clicked.
 
         // The data variable will hold all the information we want to keep visible in the info div
         let data = [];
         // The selectedData global holds the actual information needed for the view/delete buttons
         // to work, so data plus any child rows
         selectedData = {};
 
         // get all of the currently selected rows (may be more than just the one that
         // was most recently clicked)
         table.rows({selected: true}).data().each(function(row, ix) {
             data.push(row);
             selectedData[row.fullPath] = row;
             // add any newly checked rows children to the selectedData structure for the view/delete
             if (row.children) {
                 row.children.forEach(function(child) {