From 81473217220f93f94431aee361c1a97ae6ed01ae Mon Sep 17 00:00:00 2001 From: cnathe Date: Fri, 16 Jan 2026 15:17:31 -0600 Subject: [PATCH 1/2] GitHub Issue 778: Track selection loading state on DataRegion so we can disable buttons and prevent another click --- api/webapp/clientapi/dom/DataRegion.js | 76 +++++++++++++++++--------- 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/api/webapp/clientapi/dom/DataRegion.js b/api/webapp/clientapi/dom/DataRegion.js index 29903cbbcd4..e5e6f4607b9 100644 --- a/api/webapp/clientapi/dom/DataRegion.js +++ b/api/webapp/clientapi/dom/DataRegion.js @@ -493,6 +493,7 @@ if (!LABKEY.DataRegions) { * Non-configurable Options */ this.selectionModified = false; + this.selectionLoading = false; if (this.panelConfigurations === undefined) { this.panelConfigurations = {}; @@ -1171,19 +1172,11 @@ if (!LABKEY.DataRegions) { config.selectionKey = this.selectionKey; config.scope = config.scope || me; - config = _chainSelectionCountCallback(this, config); + // set loading flag for DataRegion, will be cleared in callback + this.selectionLoading = true; + _updateSelectedCountMessage(this); - var failure = LABKEY.Utils.getOnFailure(config); - if ($.isFunction(failure)) { - config.failure = failure; - } - else { - config.failure = function(error) { - let msg = 'Error setting selection'; - if (error && error.exception) msg += ': ' + error.exception; - me.addMessage(msg, 'selection'); - }; - } + config = _chainSelectionCountCallback(this, config); if (config.selectionKey) { LABKEY.DataRegion.setSelected(config); @@ -3064,6 +3057,7 @@ if (!LABKEY.DataRegions) { config.success = function(data) { region.removeMessage('selection'); region.selectionModified = true; + region.selectionLoading = false; region.selectedCount = data.count; _onSelectionChange(region); @@ -3073,6 +3067,19 @@ if (!LABKEY.DataRegions) { } }; + var failure = LABKEY.Utils.getOnFailure(config); + config.failure = function(error) { + region.selectionLoading = false; + + let msg = 'Error setting selection'; + if (error && error.exception) msg += ': ' + error.exception; + config.scope.addMessage(msg, 'selection'); + + if ($.isFunction(failure)) { + failure.call(config.scope, error); + } + } + return config; }; @@ -3363,7 +3370,10 @@ if (!LABKEY.DataRegions) { var _buttonSelectionBind = function(region, cls, fn) { var partEl = region.msgbox.getParent().find('div[data-msgpart="selection"]'); partEl.find('.labkey-button' + cls).off('click').on('click', $.proxy(function() { - fn.call(this); + // if one of the buttons is clicked while another action is loading selections, skip the click (the button should also be disabled) + if (!region.selectionLoading) { + fn.call(this); + } }, region)); }; @@ -3592,18 +3602,20 @@ if (!LABKEY.DataRegions) { var _showSelectMessage = function(region, msg) { if (region.showRecordSelectors) { + const cls = 'labkey-button ' + (region.selectionLoading ? 'disabled ' : ''); + if (_isShowSelectAll(region)) { - msg += " " + _getSelectAllText(region) + ""; + msg += " " + _getSelectAllText(region) + ""; } - msg += " " + "Select None"; + msg += " " + "Select None"; var showOpts = []; if (region.showRows !== 'all' && !_isMaxRowsAllRows(region)) - showOpts.push("Show All"); + showOpts.push("Show All"); if (region.showRows !== 'selected') - showOpts.push("Show Selected"); + showOpts.push("Show Selected"); if (region.showRows !== 'unselected') - showOpts.push("Show Unselected"); + showOpts.push("Show Unselected"); msg += "  " + showOpts.join(" "); } @@ -4081,6 +4093,21 @@ if (!LABKEY.DataRegions) { _setParameters(region, params, [OFFSET_PREFIX].concat(skipPrefixes)); }; + var _updateSelectedCountMessage = function(region) { + // If not all rows are visible and some rows are selected, show selection message + if (region.totalRows && 0 !== region.selectedCount && !region.complete) { + var msg; + if (region.selectedCount === region.totalRows) { + msg = 'All ' + region.totalRows.toLocaleString() + ' rows selected.'; + } else if (region.selectionLoading) { + msg = 'Selected of ' + region.totalRows.toLocaleString() + ' rows.'; + } else { + msg = 'Selected ' + region.selectedCount.toLocaleString() + ' of ' + region.totalRows.toLocaleString() + ' rows.'; + } + _showSelectMessage(region, msg); + } + } + var _updateRequiresSelectionButtons = function(region, selectedCount) { // update the 'select all on page' checkbox state @@ -4100,13 +4127,7 @@ if (!LABKEY.DataRegions) { } }); - // If not all rows are visible and some rows are selected, show selection message - if (region.totalRows && 0 !== region.selectedCount && !region.complete) { - var msg = (region.selectedCount === region.totalRows) ? - 'All ' + region.totalRows.toLocaleString() + ' rows selected.' : - 'Selected ' + region.selectedCount.toLocaleString() + ' of ' + region.totalRows.toLocaleString() + ' rows.'; - _showSelectMessage(region, msg); - } + _updateSelectedCountMessage(region); // Issue 10566: for javascript perf on IE stash the requires selection buttons if (!region._requiresSelectionButtons) { @@ -4446,6 +4467,11 @@ if (!LABKEY.DataRegions) { }; LABKEY.DataRegion.selectAll = function(config) { + // GitHub Issue 778: Track selection loading state on DataRegion so we can disable buttons and prevent another click + var region = config.scope; + region.selectionLoading = true; + _updateSelectedCountMessage(region); + var params = {}; if (!config.url) { // DataRegion doesn't have selectAllURL so generate url and query parameters manually From 00cb9848a49556818bca745fb996ea93ca126a40 Mon Sep 17 00:00:00 2001 From: cnathe Date: Fri, 16 Jan 2026 15:18:05 -0600 Subject: [PATCH 2/2] GitHub Issue 778: DataRegion selectAll to use jsonData for Ajax request instead of params --- api/webapp/clientapi/dom/DataRegion.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/api/webapp/clientapi/dom/DataRegion.js b/api/webapp/clientapi/dom/DataRegion.js index e5e6f4607b9..e931d48bcfa 100644 --- a/api/webapp/clientapi/dom/DataRegion.js +++ b/api/webapp/clientapi/dom/DataRegion.js @@ -4505,14 +4505,17 @@ if (!LABKEY.DataRegions) { } // NOTE: ignore maxRows, showRows, and offset + } else { + params = LABKEY.ActionURL.getParameters(config.url); + config.url = LABKEY.ActionURL.buildURL('query', 'selectAll.api', config.containerPath); } LABKEY.Ajax.request({ url: config.url, method: 'POST', - params: params, - success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), - failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) + jsonData: params, + success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), region), + failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), region, true) }); };