dc34085c59de1a3a941e2c34318d9fd8af753579 chmalee Fri Jul 17 14:27:46 2026 -0700 hubSpace: rename share buttons to Share hub, keep share banner always present, refs #37705 Co-Authored-By: Claude Opus 4.8 (1M context) diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js index 64728facd16..3f1ac0a5e3e 100644 --- src/hg/js/hgMyData.js +++ src/hg/js/hgMyData.js @@ -1706,57 +1706,63 @@ } span.textContent = label; bannerSpan.textContent = label; // (re) set up the handlers for the selected file info div: let viewBtn = document.getElementById("viewSelectedFiles"); viewBtn.addEventListener("click", viewAllInGenomeBrowser); viewBtn.textContent = "View selected"; let deleteBtn = document.getElementById("deleteSelectedFiles"); deleteBtn.style.display = "inline-block"; deleteBtn.addEventListener("click", deleteFileList); deleteBtn.textContent = "Delete selected"; // mirror the controls in the banner above the table let bannerViewBtn = document.getElementById("viewSelectedFilesBanner"); bannerViewBtn.addEventListener("click", viewAllInGenomeBrowser); bannerViewBtn.textContent = "View selected"; + bannerViewBtn.style.display = "inline-block"; let bannerDeleteBtn = document.getElementById("deleteSelectedFilesBanner"); bannerDeleteBtn.addEventListener("click", deleteFileList); bannerDeleteBtn.textContent = "Delete selected"; + bannerDeleteBtn.style.display = "inline-block"; // when exactly one hub is selected, offer a shareable connect link let copyBtn = document.getElementById("copyHubLinkBanner"); let singleHub = (data.length === 1 && data[0].fileType === "dir" && !data[0].parentDir && hubHasHubTxt(data[0].fullPath)) ? data[0].fullPath : null; let singleHubLink = singleHub ? hubShareLink(singleHub) : null; if (singleHubLink) { - copyBtn.textContent = "Copy link to hub"; + copyBtn.textContent = "Share hub"; copyBtn.setAttribute("data-url", singleHubLink); copyBtn.addEventListener("click", copyHubLinkFromBanner); copyBtn.style.display = "inline-block"; } else { copyBtn.style.display = "none"; } } else { span.textContent = ""; - bannerSpan.textContent = ""; + // banner stays present at the top level, so show a zero count and no buttons + bannerSpan.textContent = "0 hub"; + document.getElementById("viewSelectedFilesBanner").style.display = "none"; + document.getElementById("deleteSelectedFilesBanner").style.display = "none"; document.getElementById("copyHubLinkBanner").style.display = "none"; } // 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"; - banner.style.display = (numSelected === 0 || !atTopLevel) ? "none" : ""; + // the share banner is always shown at the top level, hidden inside a hub + banner.style.display = atTopLevel ? "" : "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. // 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 = {}; // Track only the rows the user directly selected (not children) directlySelected = {}; @@ -1828,57 +1834,59 @@ let currSearches = table.search.fixed().toArray(); currSearches.forEach((name) => table.search.fixed(name, null)); } function dataTableShowTopLevel(table) { // show all the "root" files, which are files (probably mostly directories) // with no parentDir clearSearch(table); // deselect any selected rows like Finder et al when moving into/upto a directory table.rows({selected: true}).deselect(); table.search.fixed("showRoot", function(searchStr, rowData, rowIx) { return !rowData.parentDir; }); uiState.currentHub = ""; hideHubBanner(); + updateSelectedFileDiv(null); } function dataTableShowDir(table, dirName, dirFullPath) { // show the directory and all immediate children of the directory clearSearch(table); // deselect any selected rows like Finder et al when moving into/upto a directory table.rows({selected: true}).deselect(); // Callers must call table.draw() after this so filter + order changes // from showDir/customOrder render in a single redraw. table.search.fixed("oneHub", function(searchStr, rowData, rowIx) { // calculate the fullPath of this rows parentDir in case the dirName passed // to this function has the same name as a parentDir further up in the // listing. For example, consider a test/test/tmp.txt layout, where "test" // is the parentDir of tmp.txt and the test subdirectory let parentDirFull = rowData.fullPath.split("/").slice(0,-1).join("/"); if (rowData.parentDir === dirName && parentDirFull === dirFullPath) { return true; } else if (rowData.fullPath === dirFullPath) { // also return the directory itself return true; } else { return false; } }); uiState.currentHub = dirName; dataTableCreateBreadcrumb(table, dirName, dirFullPath); showHubBanner(dirName); + updateSelectedFileDiv(null); } // when we move into a new directory, we remove the row from the table // and add it's html into the header, keep the row object around so // we can add it back in later let oldRowData = null; function dataTableCustomOrder(table, dirData) { // figure out the order the rows of the table should be in // if dirData is null, sort on uploadTime first // if dirData exists, that is the first row, followed by everything else // in uploadTime order if (!dirData) { // make sure the old row can show up again in the table let thead = document.querySelector(".dt-scroll-headInner > table:nth-child(1) > thead:nth-child(1)"); if (thead.childNodes.length > 1) {