From 4565aa850f538c700298d72054bd948152cd5893 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:32:37 +0200 Subject: [PATCH 1/8] fix: cancel pending AggregationPanel requests --- src/dashboard/Data/Browser/Browser.react.js | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 5488e8b0e..795d0af3d 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -263,6 +263,9 @@ class Browser extends DashboardView { this.fetchAggregationPanelData = this.fetchAggregationPanelData.bind(this); this.setAggregationPanelData = this.setAggregationPanelData.bind(this); + // Reference to cancel the ongoing info panel cloud function request + this.currentInfoPanelQuery = null; + this.dataBrowserRef = React.createRef(); window.addEventListener('popstate', () => { @@ -299,6 +302,9 @@ class Browser extends DashboardView { if (this.currentQuery) { this.currentQuery.cancel(); } + if (this.currentInfoPanelQuery) { + this.currentInfoPanelQuery.cancel(); + } this.removeLocation(); window.removeEventListener('mouseup', this.onMouseUpRowCheckBox); } @@ -346,9 +352,14 @@ class Browser extends DashboardView { } fetchAggregationPanelData(objectId, className, appId) { + if (this.currentInfoPanelQuery) { + this.currentInfoPanelQuery.cancel(); + } + this.setState({ isLoadingInfoPanel: true, }); + const params = { object: Parse.Object.extend(className).createWithoutData(objectId).toPointer(), }; @@ -358,8 +369,14 @@ class Browser extends DashboardView { const appName = this.props.params.appId; const cloudCodeFunction = this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; - Parse.Cloud.run(cloudCodeFunction, params, options).then( + + const query = Parse.Cloud.run(cloudCodeFunction, params, options); + this.currentInfoPanelQuery = query; + query.then( result => { + if (this.currentInfoPanelQuery !== query) { + return; + } if (result && result.panel && result.panel && result.panel.segments) { this.setState({ AggregationPanelData: result, isLoadingInfoPanel: false }); } else { @@ -371,13 +388,20 @@ class Browser extends DashboardView { } }, error => { + if (this.currentInfoPanelQuery !== query) { + return; + } this.setState({ isLoadingInfoPanel: false, errorAggregatedData: error.message, }); this.showNote(this.state.errorAggregatedData, true); } - ); + ).finally(() => { + if (this.currentInfoPanelQuery === query) { + this.currentInfoPanelQuery = null; + } + }); } setAggregationPanelData(data) { From bd8ac3040583aebe23489489e29c1a5a5a67adb8 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 16 Jul 2025 16:38:28 +0200 Subject: [PATCH 2/8] fix: allow cancelling info panel requests --- src/dashboard/Data/Browser/Browser.react.js | 34 +++++++++++++-------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 795d0af3d..9b11f32aa 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -263,8 +263,9 @@ class Browser extends DashboardView { this.fetchAggregationPanelData = this.fetchAggregationPanelData.bind(this); this.setAggregationPanelData = this.setAggregationPanelData.bind(this); - // Reference to cancel the ongoing info panel cloud function request - this.currentInfoPanelQuery = null; + // Reference to abort the ongoing info panel cloud function request + this.currentInfoPanelRequest = null; + this.currentInfoPanelToken = null; this.dataBrowserRef = React.createRef(); @@ -302,8 +303,8 @@ class Browser extends DashboardView { if (this.currentQuery) { this.currentQuery.cancel(); } - if (this.currentInfoPanelQuery) { - this.currentInfoPanelQuery.cancel(); + if (this.currentInfoPanelRequest) { + this.currentInfoPanelRequest.abort(); } this.removeLocation(); window.removeEventListener('mouseup', this.onMouseUpRowCheckBox); @@ -352,8 +353,10 @@ class Browser extends DashboardView { } fetchAggregationPanelData(objectId, className, appId) { - if (this.currentInfoPanelQuery) { - this.currentInfoPanelQuery.cancel(); + if (this.currentInfoPanelRequest) { + this.currentInfoPanelRequest.abort(); + this.currentInfoPanelRequest = null; + this.currentInfoPanelToken = null; } this.setState({ @@ -365,16 +368,20 @@ class Browser extends DashboardView { }; const options = { useMasterKey: true, + requestTask: xhr => { + this.currentInfoPanelRequest = xhr; + }, }; const appName = this.props.params.appId; const cloudCodeFunction = this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; - const query = Parse.Cloud.run(cloudCodeFunction, params, options); - this.currentInfoPanelQuery = query; - query.then( + const token = {}; + this.currentInfoPanelToken = token; + const promise = Parse.Cloud.run(cloudCodeFunction, params, options); + promise.then( result => { - if (this.currentInfoPanelQuery !== query) { + if (this.currentInfoPanelToken !== token) { return; } if (result && result.panel && result.panel && result.panel.segments) { @@ -388,7 +395,7 @@ class Browser extends DashboardView { } }, error => { - if (this.currentInfoPanelQuery !== query) { + if (this.currentInfoPanelToken !== token) { return; } this.setState({ @@ -398,8 +405,9 @@ class Browser extends DashboardView { this.showNote(this.state.errorAggregatedData, true); } ).finally(() => { - if (this.currentInfoPanelQuery === query) { - this.currentInfoPanelQuery = null; + if (this.currentInfoPanelToken === token) { + this.currentInfoPanelRequest = null; + this.currentInfoPanelToken = null; } }); } From 685e11cd9d1f20b2885ddef3843ec27fe82b42d7 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 16 Jul 2025 16:55:02 +0200 Subject: [PATCH 3/8] fix: cancel AggregationPanel requests --- src/dashboard/Data/Browser/Browser.react.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 9b11f32aa..c830b7c81 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -263,9 +263,9 @@ class Browser extends DashboardView { this.fetchAggregationPanelData = this.fetchAggregationPanelData.bind(this); this.setAggregationPanelData = this.setAggregationPanelData.bind(this); - // Reference to abort the ongoing info panel cloud function request + // Reference to cancel the ongoing info panel cloud function request this.currentInfoPanelRequest = null; - this.currentInfoPanelToken = null; + this.currentInfoPanelQuery = null; this.dataBrowserRef = React.createRef(); @@ -305,6 +305,7 @@ class Browser extends DashboardView { } if (this.currentInfoPanelRequest) { this.currentInfoPanelRequest.abort(); + this.currentInfoPanelQuery = null; } this.removeLocation(); window.removeEventListener('mouseup', this.onMouseUpRowCheckBox); @@ -356,7 +357,7 @@ class Browser extends DashboardView { if (this.currentInfoPanelRequest) { this.currentInfoPanelRequest.abort(); this.currentInfoPanelRequest = null; - this.currentInfoPanelToken = null; + this.currentInfoPanelQuery = null; } this.setState({ @@ -376,12 +377,11 @@ class Browser extends DashboardView { const cloudCodeFunction = this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; - const token = {}; - this.currentInfoPanelToken = token; const promise = Parse.Cloud.run(cloudCodeFunction, params, options); + this.currentInfoPanelQuery = promise; promise.then( result => { - if (this.currentInfoPanelToken !== token) { + if (this.currentInfoPanelQuery !== promise) { return; } if (result && result.panel && result.panel && result.panel.segments) { @@ -395,7 +395,7 @@ class Browser extends DashboardView { } }, error => { - if (this.currentInfoPanelToken !== token) { + if (this.currentInfoPanelQuery !== promise) { return; } this.setState({ @@ -405,9 +405,9 @@ class Browser extends DashboardView { this.showNote(this.state.errorAggregatedData, true); } ).finally(() => { - if (this.currentInfoPanelToken === token) { + if (this.currentInfoPanelQuery === promise) { this.currentInfoPanelRequest = null; - this.currentInfoPanelToken = null; + this.currentInfoPanelQuery = null; } }); } From 7765962f8999e0a1a44f4804d29cd8ced5ea3930 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:08:38 +0200 Subject: [PATCH 4/8] fix: cancel stale info panel requests --- src/dashboard/Data/Browser/Browser.react.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index c830b7c81..84615c18d 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -264,7 +264,6 @@ class Browser extends DashboardView { this.setAggregationPanelData = this.setAggregationPanelData.bind(this); // Reference to cancel the ongoing info panel cloud function request - this.currentInfoPanelRequest = null; this.currentInfoPanelQuery = null; this.dataBrowserRef = React.createRef(); @@ -303,8 +302,8 @@ class Browser extends DashboardView { if (this.currentQuery) { this.currentQuery.cancel(); } - if (this.currentInfoPanelRequest) { - this.currentInfoPanelRequest.abort(); + if (this.currentInfoPanelQuery && this.currentInfoPanelQuery.abort) { + this.currentInfoPanelQuery.abort(); this.currentInfoPanelQuery = null; } this.removeLocation(); @@ -354,9 +353,8 @@ class Browser extends DashboardView { } fetchAggregationPanelData(objectId, className, appId) { - if (this.currentInfoPanelRequest) { - this.currentInfoPanelRequest.abort(); - this.currentInfoPanelRequest = null; + if (this.currentInfoPanelQuery && this.currentInfoPanelQuery.abort) { + this.currentInfoPanelQuery.abort(); this.currentInfoPanelQuery = null; } @@ -367,10 +365,11 @@ class Browser extends DashboardView { const params = { object: Parse.Object.extend(className).createWithoutData(objectId).toPointer(), }; + let xhr; const options = { useMasterKey: true, - requestTask: xhr => { - this.currentInfoPanelRequest = xhr; + requestTask: req => { + xhr = req; }, }; const appName = this.props.params.appId; @@ -378,6 +377,7 @@ class Browser extends DashboardView { this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; const promise = Parse.Cloud.run(cloudCodeFunction, params, options); + promise.abort = () => xhr && xhr.abort(); this.currentInfoPanelQuery = promise; promise.then( result => { @@ -406,7 +406,6 @@ class Browser extends DashboardView { } ).finally(() => { if (this.currentInfoPanelQuery === promise) { - this.currentInfoPanelRequest = null; this.currentInfoPanelQuery = null; } }); From 296b9703817fd9f3a826c3be64e5a0f737d84154 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 16 Jul 2025 19:08:13 +0200 Subject: [PATCH 5/8] fix: cancel stale info panel queries --- src/dashboard/Data/Browser/Browser.react.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 84615c18d..565a8601a 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -302,8 +302,8 @@ class Browser extends DashboardView { if (this.currentQuery) { this.currentQuery.cancel(); } - if (this.currentInfoPanelQuery && this.currentInfoPanelQuery.abort) { - this.currentInfoPanelQuery.abort(); + if (this.currentInfoPanelQuery) { + Parse.Query.cancel(this.currentInfoPanelQuery); this.currentInfoPanelQuery = null; } this.removeLocation(); @@ -353,8 +353,8 @@ class Browser extends DashboardView { } fetchAggregationPanelData(objectId, className, appId) { - if (this.currentInfoPanelQuery && this.currentInfoPanelQuery.abort) { - this.currentInfoPanelQuery.abort(); + if (this.currentInfoPanelQuery) { + Parse.Query.cancel(this.currentInfoPanelQuery); this.currentInfoPanelQuery = null; } @@ -365,19 +365,14 @@ class Browser extends DashboardView { const params = { object: Parse.Object.extend(className).createWithoutData(objectId).toPointer(), }; - let xhr; const options = { useMasterKey: true, - requestTask: req => { - xhr = req; - }, }; const appName = this.props.params.appId; const cloudCodeFunction = this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; const promise = Parse.Cloud.run(cloudCodeFunction, params, options); - promise.abort = () => xhr && xhr.abort(); this.currentInfoPanelQuery = promise; promise.then( result => { From d882c6150373747656cc8554713c66643ba94f8a Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 16 Jul 2025 19:08:20 +0200 Subject: [PATCH 6/8] fix: cancel aggregation panel query --- src/dashboard/Data/Browser/Browser.react.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 565a8601a..8a398cb0f 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -303,7 +303,7 @@ class Browser extends DashboardView { this.currentQuery.cancel(); } if (this.currentInfoPanelQuery) { - Parse.Query.cancel(this.currentInfoPanelQuery); + this.currentInfoPanelQuery.cancel(); this.currentInfoPanelQuery = null; } this.removeLocation(); @@ -354,7 +354,7 @@ class Browser extends DashboardView { fetchAggregationPanelData(objectId, className, appId) { if (this.currentInfoPanelQuery) { - Parse.Query.cancel(this.currentInfoPanelQuery); + this.currentInfoPanelQuery.cancel(); this.currentInfoPanelQuery = null; } From ef1e63aa8dc5c254855c04e3ea60dc49a5d5cf7b Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 16 Jul 2025 23:28:21 +0200 Subject: [PATCH 7/8] fix: allow selecting new cell while info panel loads --- src/dashboard/Data/Browser/Browser.react.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 8a398cb0f..660aff262 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -263,7 +263,7 @@ class Browser extends DashboardView { this.fetchAggregationPanelData = this.fetchAggregationPanelData.bind(this); this.setAggregationPanelData = this.setAggregationPanelData.bind(this); - // Reference to cancel the ongoing info panel cloud function request + // Handle for the ongoing info panel cloud function request this.currentInfoPanelQuery = null; this.dataBrowserRef = React.createRef(); @@ -303,7 +303,7 @@ class Browser extends DashboardView { this.currentQuery.cancel(); } if (this.currentInfoPanelQuery) { - this.currentInfoPanelQuery.cancel(); + this.currentInfoPanelQuery.abort(); this.currentInfoPanelQuery = null; } this.removeLocation(); @@ -354,7 +354,7 @@ class Browser extends DashboardView { fetchAggregationPanelData(objectId, className, appId) { if (this.currentInfoPanelQuery) { - this.currentInfoPanelQuery.cancel(); + this.currentInfoPanelQuery.abort(); this.currentInfoPanelQuery = null; } @@ -365,18 +365,25 @@ class Browser extends DashboardView { const params = { object: Parse.Object.extend(className).createWithoutData(objectId).toPointer(), }; + let requestTask; const options = { useMasterKey: true, + requestTask: task => { + requestTask = task; + }, }; const appName = this.props.params.appId; const cloudCodeFunction = this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; const promise = Parse.Cloud.run(cloudCodeFunction, params, options); - this.currentInfoPanelQuery = promise; + this.currentInfoPanelQuery = { + abort: () => requestTask?.abort(), + promise, + }; promise.then( result => { - if (this.currentInfoPanelQuery !== promise) { + if (this.currentInfoPanelQuery?.promise !== promise) { return; } if (result && result.panel && result.panel && result.panel.segments) { @@ -390,7 +397,7 @@ class Browser extends DashboardView { } }, error => { - if (this.currentInfoPanelQuery !== promise) { + if (this.currentInfoPanelQuery?.promise !== promise) { return; } this.setState({ @@ -400,7 +407,7 @@ class Browser extends DashboardView { this.showNote(this.state.errorAggregatedData, true); } ).finally(() => { - if (this.currentInfoPanelQuery === promise) { + if (this.currentInfoPanelQuery?.promise === promise) { this.currentInfoPanelQuery = null; } }); From 35e1fe79ccff03ae43083c29c1a09bc08c4254af Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 16 Jul 2025 23:29:01 +0200 Subject: [PATCH 8/8] fix: cannot select new cell during info panel loading --- src/dashboard/Data/Browser/Browser.react.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 660aff262..e0d5b4693 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -303,7 +303,7 @@ class Browser extends DashboardView { this.currentQuery.cancel(); } if (this.currentInfoPanelQuery) { - this.currentInfoPanelQuery.abort(); + this.currentInfoPanelQuery.cancel?.(); this.currentInfoPanelQuery = null; } this.removeLocation(); @@ -354,7 +354,7 @@ class Browser extends DashboardView { fetchAggregationPanelData(objectId, className, appId) { if (this.currentInfoPanelQuery) { - this.currentInfoPanelQuery.abort(); + this.currentInfoPanelQuery.cancel?.(); this.currentInfoPanelQuery = null; } @@ -377,13 +377,11 @@ class Browser extends DashboardView { this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; const promise = Parse.Cloud.run(cloudCodeFunction, params, options); - this.currentInfoPanelQuery = { - abort: () => requestTask?.abort(), - promise, - }; + promise.cancel = () => requestTask?.abort(); + this.currentInfoPanelQuery = promise; promise.then( result => { - if (this.currentInfoPanelQuery?.promise !== promise) { + if (this.currentInfoPanelQuery !== promise) { return; } if (result && result.panel && result.panel && result.panel.segments) { @@ -397,7 +395,7 @@ class Browser extends DashboardView { } }, error => { - if (this.currentInfoPanelQuery?.promise !== promise) { + if (this.currentInfoPanelQuery !== promise) { return; } this.setState({ @@ -407,7 +405,7 @@ class Browser extends DashboardView { this.showNote(this.state.errorAggregatedData, true); } ).finally(() => { - if (this.currentInfoPanelQuery?.promise === promise) { + if (this.currentInfoPanelQuery === promise) { this.currentInfoPanelQuery = null; } });