7fe593ea07a74ee88c5ad5a7c09763f4e86b2a7a
chmalee
  Thu Aug 14 13:53:15 2025 -0700
Change displayed quota upon deleting/uploading file sucess, refs #31058

diff --git src/hg/js/hgMyData.js src/hg/js/hgMyData.js
index a362f1b2df5..1f6ad8ce51b 100644
--- src/hg/js/hgMyData.js
+++ src/hg/js/hgMyData.js
@@ -1069,46 +1069,56 @@
                 container.appendChild(viewBtn);
                 return container;
             } else {
                 return null;
             }
         }
     }
 
     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);
         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();
     }
 
+    function updateQuota(newFileSize) {
+        // Change the quota displayed to the user, pass in newFileSize as a negative number
+        // when deleting files
+        let container = document.getElementById("quotaDiv");
+        uiState.userQuota += newFileSize;
+        container.textContent = `Using ${prettyFileSize(uiState.userQuota)} of ${prettyFileSize(uiState.maxQuota)}`;
+    }
 
     function addNewUploadedHubToTable(hub) {
         // hub is a list of objects representing the file just uploaded, the associated
         // hub.txt, and directory. Make a new row for each in the filesTable, except for
         // maybe the hub directory row and hub.txt which we may have already seen before
         let table = $("#filesTable").DataTable();
         let justUploaded = {}; // hash of contents of hub but keyed by fullPath
         let hubDirData = {}; // the data for the parentDir of the uploaded file
         for (let obj of hub) {
             if (!obj.parentDir) {
                 hubDirData = obj;
             }
             let rowObj;
             if (!(obj.fullPath in uiState.filesHash)) {
                 justUploaded[obj.fullPath] = obj;
@@ -1283,30 +1293,31 @@
     };
 
     function showExistingFiles(d) {
         // Make the DataTable for each file
         // make buttons have the same style as other buttons
         $.fn.dataTable.Buttons.defaults.dom.button.className = 'button';
         tableInitOptions.data = d;
         if (uiState.isLoggedIn) {
             tableInitOptions.language = {emptyTable: "Uploaded files will appear here. Click \"Upload\" to get started"};
         } else {
             tableInitOptions.language = {emptyTable: "You are not logged in, please navigate to \"My Data\" > \"My Sessions\" and log in or create an account to begin uploading files"};
         }
         DataTable.feature.register('quota', function(settings, opts) {
             let options = Object.assign({option1: false, option2: false}, opts);
             let container = document.createElement("div");
+            container.id = "quotaDiv";
             if (uiState.isLoggedIn) {
                 container.textContent = `Using ${prettyFileSize(uiState.userQuota)} of ${prettyFileSize(uiState.maxQuota)}`;
             }
             return container;
         });
         let table = new DataTable("#filesTable", tableInitOptions);
         if (uiState.isLoggedIn) {
             table.buttons(".uploadButton").enable();
             document.getElementById("rootBreadcrumb").addEventListener("click", function(e) {
                 dataTableShowTopLevel(table);
                 dataTableCustomOrder(table);
                 dataTableEmptyBreadcrumb(table);
                 table.draw();
             });
         } else {
@@ -1407,30 +1418,31 @@
                 "uploadTime": nowFormatted,
                 "lastModified": dFormatted,
                 "fileName": cgiEncode(metadata.parentDir),
                 "fileSize": 0,
                 "fileType": "dir",
                 "genome": metadata.genome,
                 "parentDir": "",
                 "fullPath": cgiEncode(metadata.parentDir),
             };
             // package the three objects together as one "hub" and display it
             let hub = [parentDirObj, newReqObj];
             if (hubTxtObj) {
                 hub.push(hubTxtObj);
             }
             addNewUploadedHubToTable(hub);
+            updateQuota(metadata.fileSize);
         });
         uppy.on('complete', (result) => {
             history.replaceState(uiState, "", document.location.href);
             console.log("replace history with uiState");
         });
     }
 
     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);