diff --git a/src/card/CardActions.ts b/src/card/CardActions.ts
index 8b4fa765e..9a1489443 100644
--- a/src/card/CardActions.ts
+++ b/src/card/CardActions.ts
@@ -91,3 +91,9 @@ export const updateReportDatabase = (pagenumber: number, id: number, database: a
type: UPDATE_REPORT_DATABASE,
payload: { pagenumber, id, database },
});
+
+export const UPDATE_LAST_POPULATE_QUERY_TIMESTAMP = 'PAGE/CARD/UPDATE_LAST_POPULATE_QUERY_TIMESTAMP';
+export const updateLastPopulateQueryTimestamp = (pagenumber: number, id: number, timestamp: number) => ({
+ type: UPDATE_LAST_POPULATE_QUERY_TIMESTAMP,
+ payload: { pagenumber, id, lastPopulateQueryTimestamp: timestamp },
+});
diff --git a/src/card/CardReducer.ts b/src/card/CardReducer.ts
index 9679b088e..c574eb9d0 100644
--- a/src/card/CardReducer.ts
+++ b/src/card/CardReducer.ts
@@ -13,6 +13,7 @@ import {
UPDATE_REPORT_TYPE,
UPDATE_SELECTION,
UPDATE_REPORT_DATABASE,
+ UPDATE_LAST_POPULATE_QUERY_TIMESTAMP,
} from './CardActions';
import { TOGGLE_CARD_SETTINGS } from './CardActions';
import { createUUID } from '../utils/uuid';
@@ -38,6 +39,7 @@ export const CARD_INITIAL_STATE = {
selection: {},
settings: {},
collapseTimeout: 'auto',
+ lastPopulateQueryTimestamp: -1,
};
export const cardReducer = (state = CARD_INITIAL_STATE, action: { type: any; payload: any }) => {
@@ -48,6 +50,11 @@ export const cardReducer = (state = CARD_INITIAL_STATE, action: { type: any; pay
}
switch (type) {
+ case UPDATE_LAST_POPULATE_QUERY_TIMESTAMP: {
+ const { lastPopulateQueryTimestamp } = payload;
+ state = update(state, { lastPopulateQueryTimestamp });
+ return state;
+ }
case UPDATE_REPORT_TITLE: {
const { title } = payload;
state = update(state, { title: title });
diff --git a/src/card/CardThunks.ts b/src/card/CardThunks.ts
index 18c68ae74..7d72f31fe 100644
--- a/src/card/CardThunks.ts
+++ b/src/card/CardThunks.ts
@@ -182,3 +182,15 @@ export const updateReportSettingThunk = (id, setting, value) => (dispatch: any,
dispatch(createNotificationThunk('Error when updating report settings', e));
}
};
+
+/** GET thunk semaphore to be able to retrieve last timestamp to prevent displaying stale result */
+export const getLastPopulateQueryTimestampThunk = (id) => (dispatch: any, getState: any) => {
+ try {
+ const state = getState();
+ const { pagenumber } = state.dashboard.settings;
+ const report = state.dashboard.pages[pagenumber].reports.find((o) => o.id === id);
+ return report ? report.lastPopulateQueryTimestamp : -1;
+ } catch (e) {
+ dispatch(createNotificationThunk('error', e));
+ }
+};
diff --git a/src/report/Report.tsx b/src/report/Report.tsx
index 1255a3cb3..a61dc84cb 100644
--- a/src/report/Report.tsx
+++ b/src/report/Report.tsx
@@ -18,8 +18,10 @@ import { EXTENSIONS } from '../extensions/ExtensionConfig';
import { getPageNumber } from '../settings/SettingsSelectors';
import { getPrepopulateReportExtension } from '../extensions/state/ExtensionSelectors';
import { deleteSessionStoragePrepopulationReportFunction } from '../extensions/state/ExtensionActions';
-import { updateFieldsThunk } from '../card/CardThunks';
+import { getLastPopulateQueryTimestampThunk, updateFieldsThunk } from '../card/CardThunks';
import { getDashboardTheme } from '../dashboard/DashboardSelectors';
+import { getReportState } from '../card/CardSelectors';
+import { updateLastPopulateQueryTimestamp } from '../card/CardActions';
export const REPORT_LOADING_ICON = ;
@@ -56,6 +58,9 @@ export const NeoReport = ({
prepopulateExtensionName,
deletePrepopulationReportFunction,
theme,
+ report,
+ setLastPopulateQueryTimestamp,
+ getLastTimestampDispatch,
}) => {
const [records, setRecords] = useState(null);
const [timer, setTimer] = useState(null);
@@ -67,6 +72,7 @@ export const NeoReport = ({
'`driver` not defined. Have you added it into your app as ?'
);
}
+ const getLastTimestampDispatchWrap = () => getLastTimestampDispatch(id);
const debouncedRunCypherQuery = useCallback(debounce(runCypherQuery, RUN_QUERY_DELAY_MS), []);
const setSchema = (id, schema) => {
@@ -111,6 +117,11 @@ export const NeoReport = ({
// Logic to run a query
const executeQuery = (newQuery) => {
setLoadingIcon(REPORT_LOADING_ICON);
+
+ const ts = Date.now();
+ if (!report.lastPopulateQueryTimestamp || ts > report.lastPopulateQueryTimestamp) {
+ setLastPopulateQueryTimestamp(pagenumber, id, ts);
+ }
if (debounced) {
debouncedRunCypherQuery(
driver,
@@ -128,7 +139,9 @@ export const NeoReport = ({
queryTimeLimit,
(schema) => {
setSchema(id, schema);
- }
+ },
+ ts,
+ getLastTimestampDispatchWrap
);
} else {
runCypherQuery(
@@ -147,7 +160,9 @@ export const NeoReport = ({
queryTimeLimit,
(schema) => {
setSchema(id, schema);
- }
+ },
+ ts,
+ getLastTimestampDispatchWrap
);
}
};
@@ -342,6 +357,7 @@ export const NeoReport = ({
};
const mapStateToProps = (state, ownProps) => ({
+ report: getReportState(state, ownProps.id),
pagenumber: getPageNumber(state),
prepopulateExtensionName: getPrepopulateReportExtension(state, ownProps.id),
theme: getDashboardTheme(state),
@@ -360,6 +376,12 @@ const mapDispatchToProps = (dispatch) => ({
setSchemaDispatch: (id: any, schema: any) => {
dispatch(updateFieldsThunk(id, schema, true));
},
+ setLastPopulateQueryTimestamp: (pageNumber: any, id: any, ts: number) => {
+ dispatch(updateLastPopulateQueryTimestamp(pageNumber, id, ts));
+ },
+ getLastTimestampDispatch: (id: any) => {
+ return dispatch(getLastPopulateQueryTimestampThunk(id));
+ },
});
export default connect(mapStateToProps, mapDispatchToProps)(NeoReport);
diff --git a/src/report/ReportQueryRunner.ts b/src/report/ReportQueryRunner.ts
index 599e4afde..6265fda4d 100644
--- a/src/report/ReportQueryRunner.ts
+++ b/src/report/ReportQueryRunner.ts
@@ -53,7 +53,9 @@ export async function runCypherQuery(
setSchema = () => {
// eslint-disable-next-line no-console
// console.log(`Query runner attempted to set schema: ${JSON.stringify(schema)}`);
- }
+ },
+ thisPopulateQueryTimestamp = -1,
+ getLastTimestampDispatch
) {
// If no query specified, we don't do anything.
if (query.trim() == '') {
@@ -121,7 +123,16 @@ export async function runCypherQuery(
return;
}
setStatus(QueryStatus.COMPLETE);
- setRecords(records);
+ if (getLastTimestampDispatch && typeof getLastTimestampDispatch === 'function') {
+ const lastTimestamp = getLastTimestampDispatch();
+ // console.log(thisPopulateQueryTimestamp, `Query complete, report.lastQueryTs =`, lastTimestamp);
+ if (!lastTimestamp || thisPopulateQueryTimestamp >= lastTimestamp) {
+ setRecords(records);
+ }
+ } else {
+ setRecords(records);
+ }
+
// console.log("TODO remove this - QUERY WAS EXECUTED SUCCESFULLY!")
transaction.commit();