Skip to content

Commit e68fab1

Browse files
- optimized snapshot creation
- optimized snapshot restoration - fixed bugs when switching between snapshots in one project
1 parent 634fd8d commit e68fab1

7 files changed

+162
-107
lines changed

docker-compose.dev.vector.yml

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ services:
106106
PROXY_FORWARDED_PROTO_HEADER: 'http'
107107
LEGACY_URL: 'https://fragalysis.diamond.ac.uk'
108108
DEPLOYMENT_MODE: 'development'
109+
DISABLE_RESTRICT_PROPOSALS_TO_MEMBERSHIP: 'True'
110+
PUBLIC_TAS: 'lb18145-1'
109111
# INFECTIONS: 'structure-download'
110112
depends_on:
111113
database:

js/components/snapshot/redux/dispatchActions.js

+86-84
Original file line numberDiff line numberDiff line change
@@ -310,94 +310,96 @@ export const createNewSnapshot = ({
310310
let project = { projectID: session_project, authorID: author };
311311
console.log('created snapshot id: ' + res.data.id);
312312

313-
return Promise.resolve(dispatch(saveCurrentActionsList(snapshot, project, nglViewList))).then(async () => {
314-
if (disableRedirect === false) {
315-
if (selectedSnapshotToSwitch != null) {
316-
if (createDiscourse) {
317-
dispatch(createSnapshotDiscoursePost(res.data.id));
313+
return Promise.resolve(dispatch(saveCurrentActionsList(snapshot, project, nglViewList, false))).then(
314+
async () => {
315+
if (disableRedirect === false) {
316+
if (selectedSnapshotToSwitch != null) {
317+
if (createDiscourse) {
318+
dispatch(createSnapshotDiscoursePost(res.data.id));
319+
}
320+
//window.location.replace(`${URLS.projects}${session_project}/${selectedSnapshotToSwitch}`);
321+
await dispatch(changeSnapshot(session_project, selectedSnapshotToSwitch, nglViewList, stage));
322+
dispatch(setOpenSnapshotSavingDialog(false));
323+
dispatch(setIsLoadingSnapshotDialog(false));
324+
} else {
325+
// A hacky way of changing the URL without triggering react-router
326+
window.history.replaceState(
327+
null,
328+
null,
329+
`${URLS.projects}${session_project}/${
330+
selectedSnapshotToSwitch === null ? res.data.id : selectedSnapshotToSwitch
331+
}`
332+
);
333+
api({ url: `${base_url}/api/session-projects/${session_project}/` })
334+
.then(async projectResponse => {
335+
const response = await api({
336+
url: `${base_url}/api/snapshots/?session_project=${session_project}`
337+
});
338+
339+
const length = response.data.results.length;
340+
if (length === 0) {
341+
dispatch(resetCurrentSnapshot());
342+
} else {
343+
const createdSnapshot =
344+
response.data.results && response.data.results.find(r => r.id === res.data.id);
345+
console.log('new snapshot id: ' + JSON.stringify(createdSnapshot?.id));
346+
347+
if (createdSnapshot !== undefined && createdSnapshot !== null) {
348+
// If the tree fails to load, bail out first without modifying the store
349+
await dispatch(loadSnapshotTree(projectResponse.data.id));
350+
await dispatch(
351+
setCurrentSnapshot({
352+
id: createdSnapshot.id,
353+
type: createdSnapshot.type,
354+
title: createdSnapshot.title,
355+
author: createdSnapshot.author,
356+
description: createdSnapshot.description,
357+
created: createdSnapshot.created,
358+
children: createdSnapshot.children,
359+
parent: createdSnapshot.parent,
360+
data: '[]'
361+
})
362+
);
363+
await dispatch(
364+
setCurrentProject({
365+
projectID: projectResponse.data.id,
366+
authorID: projectResponse.data.author || null,
367+
title: projectResponse.data.title,
368+
description: projectResponse.data.description,
369+
targetID: projectResponse.data.target.id,
370+
tags: JSON.parse(projectResponse.data.tags)
371+
})
372+
);
373+
if (createDiscourse) {
374+
dispatch(createSnapshotDiscoursePost());
375+
}
376+
dispatch(setOpenSnapshotSavingDialog(false));
377+
dispatch(setIsLoadingSnapshotDialog(false));
378+
dispatch(setSnapshotJustSaved(projectResponse.data.id));
379+
dispatch(setDialogCurrentStep());
380+
}
381+
}
382+
})
383+
.catch(error => {
384+
dispatch(resetCurrentSnapshot());
385+
dispatch(setIsLoadingSnapshotDialog(false));
386+
console.log(`Error while saving snapshot: ${error}`);
387+
});
318388
}
319-
//window.location.replace(`${URLS.projects}${session_project}/${selectedSnapshotToSwitch}`);
320-
await dispatch(changeSnapshot(session_project, selectedSnapshotToSwitch, nglViewList, stage));
389+
} else {
321390
dispatch(setOpenSnapshotSavingDialog(false));
322391
dispatch(setIsLoadingSnapshotDialog(false));
323-
} else {
324-
// A hacky way of changing the URL without triggering react-router
325-
window.history.replaceState(
326-
null,
327-
null,
328-
`${URLS.projects}${session_project}/${
329-
selectedSnapshotToSwitch === null ? res.data.id : selectedSnapshotToSwitch
330-
}`
331-
);
332-
api({ url: `${base_url}/api/session-projects/${session_project}/` })
333-
.then(async projectResponse => {
334-
const response = await api({
335-
url: `${base_url}/api/snapshots/?session_project=${session_project}`
336-
});
337-
338-
const length = response.data.results.length;
339-
if (length === 0) {
340-
dispatch(resetCurrentSnapshot());
341-
} else {
342-
const createdSnapshot =
343-
response.data.results && response.data.results.find(r => r.id === res.data.id);
344-
console.log('new snapshot id: ' + JSON.stringify(createdSnapshot?.id));
345-
346-
if (createdSnapshot !== undefined && createdSnapshot !== null) {
347-
// If the tree fails to load, bail out first without modifying the store
348-
await dispatch(loadSnapshotTree(projectResponse.data.id));
349-
await dispatch(
350-
setCurrentSnapshot({
351-
id: createdSnapshot.id,
352-
type: createdSnapshot.type,
353-
title: createdSnapshot.title,
354-
author: createdSnapshot.author,
355-
description: createdSnapshot.description,
356-
created: createdSnapshot.created,
357-
children: createdSnapshot.children,
358-
parent: createdSnapshot.parent,
359-
data: '[]'
360-
})
361-
);
362-
await dispatch(
363-
setCurrentProject({
364-
projectID: projectResponse.data.id,
365-
authorID: projectResponse.data.author || null,
366-
title: projectResponse.data.title,
367-
description: projectResponse.data.description,
368-
targetID: projectResponse.data.target.id,
369-
tags: JSON.parse(projectResponse.data.tags)
370-
})
371-
);
372-
if (createDiscourse) {
373-
dispatch(createSnapshotDiscoursePost());
374-
}
375-
dispatch(setOpenSnapshotSavingDialog(false));
376-
dispatch(setIsLoadingSnapshotDialog(false));
377-
dispatch(setSnapshotJustSaved(projectResponse.data.id));
378-
dispatch(setDialogCurrentStep());
379-
}
380-
}
392+
dispatch(
393+
setSharedSnapshot({
394+
title,
395+
description,
396+
url: `${base_url}${URLS.projects}${session_project}/${res.data.id}`
381397
})
382-
.catch(error => {
383-
dispatch(resetCurrentSnapshot());
384-
dispatch(setIsLoadingSnapshotDialog(false));
385-
console.log(`Error while saving snapshot: ${error}`);
386-
});
398+
);
399+
return res.data.id;
387400
}
388-
} else {
389-
dispatch(setOpenSnapshotSavingDialog(false));
390-
dispatch(setIsLoadingSnapshotDialog(false));
391-
dispatch(
392-
setSharedSnapshot({
393-
title,
394-
description,
395-
url: `${base_url}${URLS.projects}${session_project}/${res.data.id}`
396-
})
397-
);
398-
return res.data.id;
399401
}
400-
});
402+
);
401403
}
402404
});
403405
})
@@ -508,7 +510,7 @@ export const createNewSnapshotWithoutStateModification = ({
508510

509511
let snapshot = { id: res.data.id, title: title };
510512
let project = { projectID: session_project, authorID: author };
511-
dispatch(saveCurrentActionsList(snapshot, project, nglViewList, true));
513+
dispatch(saveCurrentActionsList(snapshot, project, nglViewList, true, true));
512514
}
513515
});
514516
});
@@ -566,7 +568,7 @@ export const saveAndShareSnapshot = (nglViewList, showDialog = true, axuData = {
566568
const parent = null;
567569
const session_project = projectID;
568570

569-
await dispatch(sendTrackingActionsByProjectId(projectID, author));
571+
await dispatch(sendTrackingActionsByProjectId(projectID, author, true));
570572

571573
await dispatch(
572574
createNewSnapshotWithoutStateModification({

js/reducers/tracking/actions.js

+7
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ export const setProjectActionListLoaded = isLoaded => {
9898
};
9999
};
100100

101+
export const setSnapshotActionsDownloaded = isDownloaded => {
102+
return {
103+
type: constants.SET_SNAPSHOT_ACTIONS_DOWNLOADED,
104+
isDownloaded: isDownloaded
105+
};
106+
};
107+
101108
export const setSnapshotImageActionList = function(snapshotActionImageList) {
102109
return {
103110
type: constants.SET_SNAPSOT_IMAGE_ACTIONS_LIST,

js/reducers/tracking/constants.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export const constants = {
2222
SET_UNDO_REDO_ACTIONS_LIST: prefix + 'SET_UNDO_REDO_ACTIONS_LIST',
2323
SET_PROJECT_ACTIONS_LIST_LOADED: prefix + 'SET_PROJECT_ACTIONS_LIST_LOADED',
2424
SET_SKIP_ORIENTATION_CHANGE: prefix + 'SET_SKIP_ORIENTATION_CHANGE', //when snapshot is switched we want to skip orientation change so it doesn't blink through multiple states
25-
SET_IS_SNAPSHOT_DIRTY: prefix + 'SET_IS_SNAPSHOT_DIRTY'
25+
SET_IS_SNAPSHOT_DIRTY: prefix + 'SET_IS_SNAPSHOT_DIRTY',
26+
SET_SNAPSHOT_ACTIONS_DOWNLOADED: prefix + 'SET_SNAPSHOT_ACTIONS_DOWNLOADED'
2627
};
2728

2829
export const actionType = {

js/reducers/tracking/dispatchActions.js

+43-17
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
setIsTrackingCompoundsRestoring,
55
setIsUndoRedoAction,
66
setProjectActionListLoaded,
7-
setIsSnapshotDirty
7+
setIsSnapshotDirty,
8+
setSnapshotActionsDownloaded
89
} from './actions';
910
import { createInitAction } from './trackingActions';
1011
import { actionType, actionObjectType, NUM_OF_SECONDS_TO_IGNORE_MERGE, mapTypesStrings } from './constants';
@@ -169,6 +170,7 @@ import {
169170
import { turnSide } from '../../components/preview/viewerControls/redux/actions';
170171
import { getQualityOffActions } from './utils';
171172
import { compoundsColors } from '../../components/preview/compounds/redux/constants';
173+
import { isEqual, uniqWith } from 'lodash';
172174

173175
export const addCurrentActionsListToSnapshot = (snapshot, project, nglViewList) => async (dispatch, getState) => {
174176
let projectID = project && project.projectID;
@@ -177,19 +179,27 @@ export const addCurrentActionsListToSnapshot = (snapshot, project, nglViewList)
177179
await dispatch(setSnapshotToActions(actionList, snapshot, projectID, project, nglViewList, true));
178180
};
179181

180-
export const saveCurrentActionsList = (snapshot, project, nglViewList, all = false) => async (dispatch, getState) => {
182+
export const saveCurrentActionsList = (snapshot, project, nglViewList, all, isAnonymousSnapshot = false) => async (
183+
dispatch,
184+
getState
185+
) => {
181186
let projectID = project && project.projectID;
182-
let actionList = await dispatch(getTrackingActions(projectID));
187+
let actionList = await dispatch(getTrackingActions(isAnonymousSnapshot ? null : projectID));
183188

184-
if (all === false) {
185-
dispatch(setSnapshotToActions(actionList, snapshot, projectID, project, nglViewList, false));
186-
} else {
187-
dispatch(setSnapshotToAllActions(actionList, snapshot, projectID));
189+
if (!isAnonymousSnapshot) {
190+
if (all === false) {
191+
dispatch(setSnapshotToActions(actionList, snapshot, projectID, project, nglViewList, false));
192+
} else {
193+
dispatch(setSnapshotToAllActions(actionList, snapshot, projectID));
194+
}
188195
}
189-
await dispatch(saveActionsList(project, snapshot, actionList, nglViewList));
196+
await dispatch(saveActionsList(project, snapshot, actionList, nglViewList /*, isAnonymousSnapshot*/));
190197
};
191198

192-
const saveActionsList = (project, snapshot, actionList, nglViewList) => async (dispatch, getState) => {
199+
const saveActionsList = (project, snapshot, actionList, nglViewList, isAnonymousSnapshot = false) => async (
200+
dispatch,
201+
getState
202+
) => {
193203
const state = getState();
194204
const snapshotID = snapshot && snapshot.id;
195205
if (snapshotID) {
@@ -526,7 +536,9 @@ const saveActionsList = (project, snapshot, actionList, nglViewList) => async (d
526536
currentActions.push(Object.assign({ ...trackAction }));
527537
}
528538

529-
await dispatch(saveSnapshotAction(snapshot, project, currentActions));
539+
if (!isAnonymousSnapshot) {
540+
await dispatch(saveSnapshotAction(snapshot, project, currentActions));
541+
}
530542
await dispatch(saveTrackingActions(currentActions, snapshotID));
531543
dispatch(setCurrentActionsList(currentActions));
532544
}
@@ -905,8 +917,10 @@ export const restoreCurrentActionsList = snapshotID => async (dispatch, getState
905917
};
906918

907919
const restoreTrackingActions = snapshotID => async (dispatch, getState) => {
920+
const state = getState();
921+
const areSnapshotActionsDownloaded = state.trackingReducers.areSnapshotActionsDownloaded;
908922
// console.log(`snapshotDebug - restoreTrackingActions - start`);
909-
if (snapshotID) {
923+
if (snapshotID && !areSnapshotActionsDownloaded) {
910924
try {
911925
// console.log(`snapshotDebug - restoreTrackingActions - before getting actions`);
912926
return api({
@@ -923,6 +937,7 @@ const restoreTrackingActions = snapshotID => async (dispatch, getState) => {
923937

924938
let snapshotActions = [...listToSet];
925939
dispatch(setCurrentActionsList(snapshotActions));
940+
dispatch(setSnapshotActionsDownloaded(true));
926941
// console.log(`snapshotDebug - restoreTrackingActions - end - success`);
927942
return Promise.resolve(snapshotActions);
928943
// return Promise.resolve();
@@ -969,10 +984,16 @@ const restoreTargetActions = orderedActionList => (dispatch, getState) => {
969984
};
970985

971986
export const restoreAfterTargetActions = (stages, projectId, snapshotId) => async (dispatch, getState) => {
972-
const currentActionList = await dispatch(restoreTrackingActions(snapshotId));
973-
974987
const state = getState();
975988

989+
const areSnapshotActionsDownloaded = state.trackingReducers.areSnapshotActionsDownloaded;
990+
let currentActionList = [];
991+
if (!areSnapshotActionsDownloaded) {
992+
currentActionList = await dispatch(restoreTrackingActions(snapshotId));
993+
} else {
994+
currentActionList = state.trackingReducers.current_actions_list;
995+
}
996+
976997
// const currentActionList = state.trackingReducers.current_actions_list;
977998
const orderedActionList = currentActionList.sort((a, b) => a.timestamp - b.timestamp);
978999
// console.log(`snapshotDebug - restoreAfterTargetActions - no. of actions: ${orderedActionList.length}`);
@@ -3739,7 +3760,7 @@ export const checkSendTrackingActions = (save = false) => async (dispatch, getSt
37393760
const sendActions = state.trackingReducers.send_actions_list;
37403761
const length = sendActions.length;
37413762

3742-
if (length >= CONSTANTS.COUNT_SEND_TRACK_ACTIONS || save) {
3763+
if (/*length >= CONSTANTS.COUNT_SEND_TRACK_ACTIONS || */ save) {
37433764
await dispatch(sendTrackingActions(sendActions, currentProject, true));
37443765
}
37453766
};
@@ -3797,6 +3818,8 @@ const getTrackingActions = (projectID, withTreeSeparation) => (dispatch, getStat
37973818
const currentProject = state.projectReducers.currentProject;
37983819
const currentProjectID = currentProject && currentProject.projectID;
37993820
const sendActions = state.trackingReducers.send_actions_list;
3821+
const currentActionList = state.trackingReducers.current_actions_list;
3822+
const trackActionsList = state.trackingReducers.track_actions_list;
38003823

38013824
if (projectID) {
38023825
dispatch(setIsActionsLoading(true));
@@ -3837,7 +3860,10 @@ const getTrackingActions = (projectID, withTreeSeparation) => (dispatch, getStat
38373860
dispatch(setIsActionsLoading(false));
38383861
});
38393862
} else {
3840-
let projectActions = [...sendActions];
3863+
// let projectActions = [...sendActions];
3864+
// const projectActions = [];
3865+
let projectActions = [...currentActionList, ...sendActions, ...trackActionsList];
3866+
projectActions = uniqWith(projectActions, isEqual);
38413867
dispatch(setProjectActionList(projectActions));
38423868
return Promise.resolve(projectActions);
38433869
}
@@ -3906,14 +3932,14 @@ const copyActionsToProject = (toProject, setActionList = true, clear = false) =>
39063932
}
39073933
};
39083934

3909-
export const sendTrackingActionsByProjectId = (projectID, authorID) => async (dispatch, getState) => {
3935+
export const sendTrackingActionsByProjectId = (projectID, authorID, offline = false) => async (dispatch, getState) => {
39103936
const state = getState();
39113937
const currentProject = state.projectReducers.currentProject;
39123938
const currentProjectID = currentProject && currentProject.projectID;
39133939

39143940
const project = { projectID, authorID };
39153941

3916-
await dispatch(getTrackingActions(currentProjectID));
3942+
await dispatch(getTrackingActions(offline ? null : currentProjectID));
39173943
await dispatch(copyActionsToProject(project, false, currentProjectID && currentProjectID != null ? true : false));
39183944
};
39193945

0 commit comments

Comments
 (0)