You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by hb...@apache.org on 2022/11/01 14:08:24 UTC
[age-viewer] branch main updated: Request progress indicator for currently processing requests (#49)
This is an automated email from the ASF dual-hosted git repository.
hbshin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/age-viewer.git
The following commit(s) were added to refs/heads/main by this push:
new a232cec Request progress indicator for currently processing requests (#49)
a232cec is described below
commit a232cec4fc1dffd182586e168287fd202cbb54ed
Author: marodins <67...@users.noreply.github.com>
AuthorDate: Tue Nov 1 07:08:19 2022 -0700
Request progress indicator for currently processing requests (#49)
* add frame earlier and update state of cypher slice to include pending state
* update pending and fulfilled state of cypher slice
* include progress indicator while results are transmitting
* update container component's branch condition
* update cypher slice
* refactor frame creating code and frame component dependency; adjust progress indicator
* clean up comments
---
.../src/components/contents/containers/Editor.js | 3 +-
.../components/contents/presentations/Editor.jsx | 9 ++--
.../components/contents/presentations/Frames.jsx | 7 ++-
.../containers/CypherGraphResultContainers.js | 3 +-
.../frame/containers/CypherResultContainers.js | 5 ++-
.../frame/presentations/CypherGraphResultFrame.jsx | 51 +++++++++++++++-------
frontend/src/features/cypher/CypherSlice.js | 17 +++++++-
frontend/src/features/frame/FrameSlice.js | 3 +-
8 files changed, 65 insertions(+), 33 deletions(-)
diff --git a/frontend/src/components/contents/containers/Editor.js b/frontend/src/components/contents/containers/Editor.js
index cf6adf9..95b5176 100644
--- a/frontend/src/components/contents/containers/Editor.js
+++ b/frontend/src/components/contents/containers/Editor.js
@@ -18,7 +18,7 @@
*/
import { connect } from 'react-redux';
-import { addFrame, trimFrame } from '../../../features/frame/FrameSlice';
+import { addFrame, trimFrame, removeFrame } from '../../../features/frame/FrameSlice';
import { addAlert } from '../../../features/alert/AlertSlice';
import { getConnectionStatus } from '../../../features/database/DatabaseSlice';
import { executeCypherQuery } from '../../../features/cypher/CypherSlice';
@@ -38,6 +38,7 @@ const mapDispatchToProps = {
setCommand,
addFrame,
trimFrame,
+ removeFrame,
addAlert,
getConnectionStatus,
executeCypherQuery,
diff --git a/frontend/src/components/contents/presentations/Editor.jsx b/frontend/src/components/contents/presentations/Editor.jsx
index 3c14533..4c66ac1 100644
--- a/frontend/src/components/contents/presentations/Editor.jsx
+++ b/frontend/src/components/contents/presentations/Editor.jsx
@@ -88,12 +88,9 @@ const Editor = ({
dispatch(() => addFrame(command, 'ServerStatus', refKey));
}
} else if (database.status === 'connected') {
- const reqStringValue = command;
- dispatch(() => executeCypherQuery([refKey, reqStringValue]).then((response) => {
- if (response.type === 'cypher/executeCypherQuery/fulfilled') {
- addFrame(reqStringValue, 'CypherResultFrame', refKey);
- } else if (response.type === 'cypher/executeCypherQuery/rejected') {
- addFrame(reqStringValue, 'CypherResultFrame', refKey);
+ addFrame(command, 'CypherResultFrame', refKey);
+ dispatch(() => executeCypherQuery([refKey, command]).then((response) => {
+ if (response.type === 'cypher/executeCypherQuery/rejected') {
dispatch(() => addAlert('ErrorCypherQuery'));
}
}));
diff --git a/frontend/src/components/contents/presentations/Frames.jsx b/frontend/src/components/contents/presentations/Frames.jsx
index 2f5485a..90139db 100644
--- a/frontend/src/components/contents/presentations/Frames.jsx
+++ b/frontend/src/components/contents/presentations/Frames.jsx
@@ -114,9 +114,8 @@ const Frames = ({
);
}
if (frame.frameName === 'CypherResultFrame') {
- if (Object.prototype.hasOwnProperty.call(queryResult, frame.frameProps.key)
- && (queryResult[frame.frameProps.key].command !== null ? queryResult[frame.frameProps.key].command.toUpperCase() : 'NULL')
- .match('(ERROR|GRAPH|CREATE|UPDATE|COPY|NULL).*')) {
+ if (queryResult[frame.frameProps.key].complete && (queryResult[frame.frameProps.key].command !== null ? queryResult[frame.frameProps.key].command.toUpperCase() : 'NULL')
+ .match('(ERROR|GRAPH|CREATE|UPDATE|COPY|NULL).*')) {
return (
<CypherResult
key={frame.frameProps.key}
@@ -137,7 +136,7 @@ const Frames = ({
}
return '';
}));
- }, [frameList]);
+ }, [frameList, queryResult]);
return (
<div className="container-fluid frame-area pt-3">
diff --git a/frontend/src/components/frame/containers/CypherGraphResultContainers.js b/frontend/src/components/frame/containers/CypherGraphResultContainers.js
index 5b4e17e..d309c89 100644
--- a/frontend/src/components/frame/containers/CypherGraphResultContainers.js
+++ b/frontend/src/components/frame/containers/CypherGraphResultContainers.js
@@ -21,7 +21,8 @@ import { connect } from 'react-redux';
import { pinFrame, removeFrame } from '../../../features/frame/FrameSlice';
import CypherGraphResultFrame from '../presentations/CypherGraphResultFrame';
-const mapStateToProps = () => ({
+const mapStateToProps = (state, props) => ({
+ queryComplete: state.cypher.queryResult[props.refKey],
});
const mapDispatchToProps = { removeFrame, pinFrame };
diff --git a/frontend/src/components/frame/containers/CypherResultContainers.js b/frontend/src/components/frame/containers/CypherResultContainers.js
index 6319d4c..a8f57aa 100644
--- a/frontend/src/components/frame/containers/CypherResultContainers.js
+++ b/frontend/src/components/frame/containers/CypherResultContainers.js
@@ -21,8 +21,9 @@ import { connect } from 'react-redux';
import { pinFrame, removeFrame } from '../../../features/frame/FrameSlice';
import CypherResultFrame from '../presentations/CypherResultFrame';
-const mapStateToProps = () => ({
-});
+const mapStateToProps = () => (
+ {}
+);
const mapDispatchToProps = { removeFrame, pinFrame };
diff --git a/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx b/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
index 8117a8c..9298dfa 100644
--- a/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
+++ b/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
@@ -22,6 +22,7 @@ import uuid from 'react-uuid';
import { saveAs } from 'file-saver';
import { Parser } from 'json2csv';
import PropTypes from 'prop-types';
+import { Spinner } from 'react-bootstrap';
import CypherResultCytoscapeContainer from '../../cypherresult/containers/CypherResultCytoscapeContainer';
import CypherResultTableContainer from '../../cypherresult/containers/CypherResultTableContainer';
import GraphFilterModal from '../../cypherresult/components/GraphFilterModal';
@@ -29,6 +30,7 @@ import EdgeThicknessMenu from '../../cypherresult/components/EdgeThicknessMenu';
import Frame from '../Frame';
const CypherResultFrame = ({
+ queryComplete,
refKey,
isPinned,
reqString,
@@ -74,6 +76,7 @@ const CypherResultFrame = ({
}, [filterModalVisible, thicknessModalVisible, chartLegend]);
useEffect(() => {
+ if (!chartAreaRef.current) return;
if (globalFilter) {
chartAreaRef.current.applyFilterOnCytoscapeElements(globalFilter);
} else {
@@ -82,6 +85,7 @@ const CypherResultFrame = ({
}, [globalFilter]);
useEffect(() => {
+ if (!chartAreaRef.current) return;
chartAreaRef.current.applyEdgeThicknessCytoscapeElements(globalThickness);
}, [globalThickness]);
@@ -174,21 +178,33 @@ const CypherResultFrame = ({
isPinned={isPinned}
refKey={refKey}
>
- <div className="d-flex h-100">
- <div style={{ height: '100%', width: '100%' }} id={`${refKey}-graph`} className="selected-frame-tab">
- <CypherResultCytoscapeContainer
- key={cytoscapeContainerKey}
- ref={chartAreaRef}
- refKey={refKey}
- setChartLegend={setChartLegend}
- />
- </div>
- <div style={{ height: '100%', width: '100%' }} id={`${refKey}-table`} className="deselected-frame-tab">
- <CypherResultTableContainer
- refKey={refKey}
- />
- </div>
- </div>
+ {
+ queryComplete.complete
+ ? (
+ <div className="d-flex h-100">
+ <div style={{ height: '100%', width: '100%' }} id={`${refKey}-graph`} className="selected-frame-tab">
+ <CypherResultCytoscapeContainer
+ key={cytoscapeContainerKey}
+ ref={chartAreaRef}
+ refKey={refKey}
+ setChartLegend={setChartLegend}
+ />
+ </div>
+ <div style={{ height: '100%', width: '100%' }} id={`${refKey}-table`} className="deselected-frame-tab">
+ <CypherResultTableContainer
+ refKey={refKey}
+ />
+ </div>
+ </div>
+ )
+ : (
+ <div style={{ alignContent: 'center' }}>
+ <div style={{ marginLeft: '50%', padding: '20px' }} id={`${refKey}-loading`}>
+ <Spinner animation="border" />
+ </div>
+ </div>
+ )
+ }
</Frame>
<GraphFilterModal
onSubmit={(filters) => {
@@ -205,6 +221,11 @@ const CypherResultFrame = ({
};
CypherResultFrame.propTypes = {
+ queryComplete: PropTypes.shape(
+ {
+ complete: PropTypes.bool.isRequired,
+ },
+ ).isRequired,
refKey: PropTypes.string.isRequired,
isPinned: PropTypes.bool.isRequired,
reqString: PropTypes.string.isRequired,
diff --git a/frontend/src/features/cypher/CypherSlice.js b/frontend/src/features/cypher/CypherSlice.js
index 8edc9ad..78c2950 100644
--- a/frontend/src/features/cypher/CypherSlice.js
+++ b/frontend/src/features/cypher/CypherSlice.js
@@ -108,15 +108,28 @@ const CypherSlice = createSlice({
},
extraReducers: {
[executeCypherQuery.fulfilled]: (state, action) => {
- state.queryResult[action.payload.key] = {};
// state.queryResult[action.payload.key].response = action.payload
- Object.assign(state.queryResult[action.payload.key], action.payload);
+ Object.assign(state.queryResult[action.payload.key], {
+ ...action.payload,
+ complete: true,
+ });
+ },
+ [executeCypherQuery.pending]: (state, action) => {
+ const key = action.meta.arg[0];
+ const command = action.meta.arg[1];
+ state.queryResult[key] = {};
+ Object.assign(state.queryResult[key], {
+ command,
+ complete: false,
+ requestId: action.meta.requestId,
+ });
},
[executeCypherQuery.rejected]: (state, action) => {
state.queryResult[action.meta.arg[0]] = {
command: 'ERROR',
query: action.meta.arg[1],
key: action.meta.arg[0],
+ complete: true,
message: action.error.message,
};
},
diff --git a/frontend/src/features/frame/FrameSlice.js b/frontend/src/features/frame/FrameSlice.js
index 9b46299..7495237 100644
--- a/frontend/src/features/frame/FrameSlice.js
+++ b/frontend/src/features/frame/FrameSlice.js
@@ -48,8 +48,7 @@ const FrameSlice = createSlice({
removeFrame: {
reducer: (state, action) => {
const frameKey = action.payload.refKey;
- state.splice(state.findIndex((frame) => (frame.frameProps.key === frameKey)), 1);
- state.map((frame) => { if (frame.orgIndex) { frame.orgIndex -= 1; } return frame; });
+ return state.filter((frame) => frame.frameProps.key !== frameKey);
},
prepare: (refKey) => ({ payload: { refKey } }),