From d5078f79729434fee5c5d3cc968b2b71280a4b23 Mon Sep 17 00:00:00 2001 From: Tibor Postek Date: Wed, 1 Apr 2020 12:13:02 +0200 Subject: [PATCH] #190 Fix inconsistencies - Selecting and reselecting sites --- docker-compose.dev.yml | 6 +- docker-compose.localhost.yml | 2 +- js/components/header/index.js | 19 +-- js/components/nglView/generatingObjects.js | 23 ++-- .../nglView/redux/dispatchActions.js | 4 +- js/components/preview/Preview.js | 1 - .../preview/compounds/compoundList.js | 129 +++++++++--------- .../compounds/redux/dispatchActions.js | 27 ++-- .../preview/molecule/moleculeView.js | 3 +- .../preview/molecule/redux/dispatchActions.js | 83 ++++++----- .../preview/summary/CmpdSummaryImage.js | 15 +- .../preview/summary/redux/dispatchAction.js | 14 +- .../session/redux/dispatchActions.js | 26 +--- js/reducers/api/selectors.js | 1 + js/reducers/selection/actions.js | 54 +++----- js/reducers/selection/constants.js | 11 +- js/reducers/selection/dispatchActions.js | 7 +- js/reducers/selection/selectionReducers.js | 128 +++++++---------- js/reducers/selection/selectors.js | 105 ++++++++++---- 19 files changed, 335 insertions(+), 323 deletions(-) create mode 100644 js/reducers/api/selectors.js diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index d73c902434..56f13daaaa 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -14,7 +14,7 @@ services: - "3306:3306" graph: container_name: neo4j - image: neo4j + image: neo4j:3.5 ports: # Comment these two out in produciton - "7474:7474" @@ -28,7 +28,7 @@ services: - ../data/neo4j/logs:/logs environment: - NEO4J_AUTH=none - - NEO4J_dbms_memory_pagecache_size=4G + - NEO4J_dbms_memory_pagecache_size=4G web: container_name: web_dock image: xchem/fragalysis-stack:latest @@ -55,4 +55,4 @@ services: MYSQL_USER: django DATA_ORIGIN: EXAMPLE depends_on: - - mysql \ No newline at end of file + - mysql diff --git a/docker-compose.localhost.yml b/docker-compose.localhost.yml index fee9458560..49389d12cc 100644 --- a/docker-compose.localhost.yml +++ b/docker-compose.localhost.yml @@ -14,7 +14,7 @@ services: - "3306:3306" graph: container_name: neo4j - image: neo4j + image: neo4j:3.5 ports: # Comment these two out in produciton - "7474:7474" diff --git a/js/components/header/index.js b/js/components/header/index.js index 78c331660f..6699437118 100644 --- a/js/components/header/index.js +++ b/js/components/header/index.js @@ -73,7 +73,8 @@ const useStyles = makeStyles(theme => ({ cursor: 'progress' }, loadingProgress: { - height: '7px' + height: 2, + bottom: -2 }, clickableImage: { cursor: 'pointer' @@ -256,6 +257,9 @@ export default memo( + {(isLoading === true || disableUserInteraction === true) && ( + + )} setOpenFunders(false)} /> - - {(isLoading === true || disableUserInteraction === true) && ( - <> - - - - )} - + ); }) diff --git a/js/components/nglView/generatingObjects.js b/js/components/nglView/generatingObjects.js index b4b13c327e..573673c914 100644 --- a/js/components/nglView/generatingObjects.js +++ b/js/components/nglView/generatingObjects.js @@ -56,7 +56,7 @@ export const generateMoleculeObject = (data, colourToggle) => ({ // Vector export const generateArrowObject = (data, start, end, name, colour) => ({ - name: listTypes.VECTOR + '_' + name, + name: `${listTypes.VECTOR}_${name}`, OBJECT_TYPE: OBJECT_TYPE.ARROW, start: start, end: end, @@ -68,7 +68,7 @@ export const generateArrowObject = (data, start, end, name, colour) => ({ // Vector export const generateCylinderObject = (data, start, end, name, colour) => ({ - name: listTypes.VECTOR + '_' + name, + name: `${listTypes.VECTOR}_${name}`, OBJECT_TYPE: OBJECT_TYPE.CYLINDER, start: start, end: end, @@ -126,15 +126,18 @@ export const generateMoleculeId = data => ({ id: data.id }); -export const getVectorWithColorByCountOfCompounds = (item, to_select) => { - var thisSmi = item.name.split('VECTOR_')[1]; +export const getVectorWithColorByCountOfCompounds = (item, currentVectorCompounds) => { + var thisSmi = item.name.split(`${listTypes.VECTOR}_`)[1]; + var counter = 0; - Object.keys(to_select).forEach(key => { - var smi = key.split('_')[0]; - if (smi === thisSmi) { - counter += to_select[key]['addition'].length; - } - }); + if (currentVectorCompounds) { + Object.keys(currentVectorCompounds).forEach(compoundKey => { + var smi = compoundKey.split('_')[0]; + if (smi === thisSmi) { + counter += currentVectorCompounds[compoundKey]['addition'].length; + } + }); + } var colour = [1, 0, 0]; diff --git a/js/components/nglView/redux/dispatchActions.js b/js/components/nglView/redux/dispatchActions.js index 0462c18fe9..822a300866 100644 --- a/js/components/nglView/redux/dispatchActions.js +++ b/js/components/nglView/redux/dispatchActions.js @@ -126,8 +126,8 @@ export const handleNglViewPick = (stage, pickingProxy, getNglView) => (dispatch, //else if (type === listTypes.MOLECULE) { //} else if (type === listTypes.VECTOR) { - const vectorSmi = name.split('_')[1]; - dispatch(selectVectorAndResetCompounds(vectorSmi)); + const vectorSmile = name.split('_')[1]; + dispatch(selectVectorAndResetCompounds(vectorSmile)); } } } diff --git a/js/components/preview/Preview.js b/js/components/preview/Preview.js index dc26162902..66314f1acb 100644 --- a/js/components/preview/Preview.js +++ b/js/components/preview/Preview.js @@ -86,7 +86,6 @@ const Preview = memo(({ isStateLoaded, headerHeight }) => { return () => { dispatch(removeAllNglComponents()); dispatch(resetCurrentCompoundsSettings(true)); - console.log(' Unmount Preview '); }; }, [dispatch]); diff --git a/js/components/preview/compounds/compoundList.js b/js/components/preview/compounds/compoundList.js index 91ce3b01c2..a280018949 100644 --- a/js/components/preview/compounds/compoundList.js +++ b/js/components/preview/compounds/compoundList.js @@ -71,7 +71,6 @@ export const CompoundList = memo(({ height }) => { const { getNglView } = useContext(NglContext); const majorViewStage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage; - const to_query = useSelector(state => state.selectionReducers.to_query); // const compoundClasses = useSelector(state => getCompoundClasses(state)); const blueInput = useSelector(state => state.previewReducers.compounds[compoundsColors.blue.key]); const redInput = useSelector(state => state.previewReducers.compounds[compoundsColors.red.key]); @@ -90,78 +89,72 @@ export const CompoundList = memo(({ height }) => { const currentCompoundClass = useSelector(state => state.previewReducers.compounds.currentCompoundClass); // const totalCountOfMolecules = useSelector(state => getTotalCountOfMolecules(state)); const canLoadMoreCompounds = useSelector(state => getCanLoadMoreCompounds(state)); - const querying = useSelector(state => state.selectionReducers.querying); const currentVector = useSelector(state => state.selectionReducers.currentVector); const currentCompounds = useSelector(state => state.previewReducers.compounds.currentCompounds); const compoundsListOffset = useSelector(state => getCompoundListOffset(state)); - let mol_string = currentCompounds.length + ' Compounds on vector to pick'; - - if (to_query === '' || to_query === undefined) { - mol_string = ''; + let headerMessage = currentCompounds.length + ' Compounds on vector to pick'; + if (currentVector === null) { + headerMessage = 'Not selected vector'; } - if (currentVector !== undefined && to_query !== undefined) { - return ( - - {currentCompounds && ( - - - {Object.keys(compoundsColors).map(item => ( - - dispatch(onChangeCompoundClassValue(e))} - onKeyDown={e => dispatch(onKeyDownCompoundClass(e))} - value={inputs[item] || ''} - /> - - ))} - - - - dispatch(loadNextPageOfCompounds())} - hasMore={canLoadMoreCompounds} - loader={ -
-
- -
+ return ( + + {currentCompounds && ( + + + {Object.keys(compoundsColors).map(item => ( + + dispatch(onChangeCompoundClassValue(e))} + onKeyDown={e => dispatch(onKeyDownCompoundClass(e))} + value={inputs[item] || ''} + /> + + ))} + + + + dispatch(loadNextPageOfCompounds())} + hasMore={canLoadMoreCompounds} + loader={ +
+
+
- } - useWindow={false} - > - {currentCompounds.slice(0, compoundsListOffset).map((data, index) => { - return ; - })} - - - - - - - )} - - ); - } else { - return null; - } +
+ } + useWindow={false} + > + {currentCompounds.slice(0, compoundsListOffset).map((data, index) => { + return ; + })} +
+
+
+ + +
+ )} +
+ ); }); diff --git a/js/components/preview/compounds/redux/dispatchActions.js b/js/components/preview/compounds/redux/dispatchActions.js index 9fa4da87ba..ccddaf0924 100644 --- a/js/components/preview/compounds/redux/dispatchActions.js +++ b/js/components/preview/compounds/redux/dispatchActions.js @@ -20,21 +20,27 @@ import { api, getCsrfToken, METHOD } from '../../../../utils/api'; import { base_url } from '../../../routes/constants'; import { loadFromServer } from '../../../../utils/genericView'; import { compoundsColors } from './constants'; +import { + getCurrentVectorCompoundsFiltered, + getMoleculeOfCurrentVector +} from '../../../../reducers/selection/selectors'; export const selectAllCompounds = () => (dispatch, getState) => { const state = getState(); - const thisVectorList = state.selectionReducers.this_vector_list; - const to_query = state.selectionReducers.to_query; + const currentVectorCompoundsFiltered = getCurrentVectorCompoundsFiltered(state); + + const moleculeOfVector = getMoleculeOfCurrentVector(state); + const smiles = moleculeOfVector && moleculeOfVector.smiles; const currentCompoundClass = state.previewReducers.compounds.currentCompoundClass; - for (let key in thisVectorList) { - for (let index in thisVectorList[key]) { + for (let key in currentVectorCompoundsFiltered) { + for (let index in currentVectorCompoundsFiltered[key]) { if (index !== 'vector') { - for (let indexOfCompound in thisVectorList[key][index]) { + for (let indexOfCompound in currentVectorCompoundsFiltered[key][index]) { var thisObj = { - smiles: thisVectorList[key][index][indexOfCompound].end, - vector: thisVectorList[key].vector.split('_')[0], - mol: to_query, + smiles: currentVectorCompoundsFiltered[key][index][indexOfCompound].end, + vector: currentVectorCompoundsFiltered[key].vector.split('_')[0], + mol: smiles, class: parseInt(currentCompoundClass) }; dispatch(appendToBuyList(thisObj)); @@ -73,7 +79,8 @@ export const loadNextPageOfCompounds = () => (dispatch, getState) => { const showCompoundNglView = ({ majorViewStage, data, index }) => (dispatch, getState) => { const state = getState(); - const to_query_sdf_info = state.selectionReducers.to_query_sdf_info; + const moleculeOfVector = getMoleculeOfCurrentVector(state); + const sdf_info = moleculeOfVector && moleculeOfVector.sdf_info; const configuration = state.previewReducers.compounds.configuration; const showedCompoundList = state.previewReducers.compounds.showedCompoundList; @@ -92,7 +99,7 @@ const showCompoundNglView = ({ majorViewStage, data, index }) => (dispatch, getS var post_data = { INPUT_VECTOR: data.vector, INPUT_SMILES: [data.smiles], - INPUT_MOL_BLOCK: to_query_sdf_info + INPUT_MOL_BLOCK: sdf_info }; api({ diff --git a/js/components/preview/molecule/moleculeView.js b/js/components/preview/molecule/moleculeView.js index 7bf6a5201e..5eb8642c71 100644 --- a/js/components/preview/molecule/moleculeView.js +++ b/js/components/preview/molecule/moleculeView.js @@ -155,7 +155,6 @@ const MoleculeView = memo(({ imageHeight, imageWidth, data }) => { const key = 'mol_image'; const dispatch = useDispatch(); - const to_query = useSelector(state => state.selectionReducers.to_query); const proteinList = useSelector(state => state.selectionReducers.proteinList); const complexList = useSelector(state => state.selectionReducers.complexList); const surfaceList = useSelector(state => state.selectionReducers.surfaceList); @@ -240,7 +239,7 @@ const MoleculeView = memo(({ imageHeight, imageWidth, data }) => { refOnCancel.current(); } }; - }, [complexList, data.id, data.smiles, fragmentDisplayList, imageHeight, to_query, url, vectorOnList, imageWidth]); + }, [complexList, data.id, data.smiles, fragmentDisplayList, imageHeight, url, vectorOnList, imageWidth]); const svg_image = ( { for (let r in rings) { outList.push(generateCylinderObject(data, rings[r][0], rings[r][2], r, colour)); } - return outList; }; @@ -87,14 +86,18 @@ const getViewUrl = (get_view, data) => { const handleVector = (json, stage, data) => (dispatch, getState) => { const state = getState(); - const to_select = state.selectionReducers.to_select; + const { vector_list, compoundsOfVectors } = state.selectionReducers; + var objList = generateObjectList(json['3d'], data); - dispatch(setVectorList(objList)); + dispatch(setVectorList([...vector_list, ...objList])); + + const currentVectorCompounds = compoundsOfVectors && compoundsOfVectors[data.smiles]; + // loading vector objects objList.map(item => dispatch( loadObject( - Object.assign({ display_div: VIEWS.MAJOR_VIEW }, getVectorWithColorByCountOfCompounds(item, to_select)), + { display_div: VIEWS.MAJOR_VIEW, ...getVectorWithColorByCountOfCompounds(item, currentVectorCompounds) }, stage, undefined, null @@ -102,26 +105,40 @@ const handleVector = (json, stage, data) => (dispatch, getState) => { ) ); var vectorBondColorMap = generateBondColorMap(json['indices']); - dispatch(setBondColorMap(vectorBondColorMap)); + dispatch(updateBondColorMapOfCompounds(data.smiles, vectorBondColorMap)); }; export const addVector = (stage, data) => async (dispatch, getState) => { - const state = getState(); - const vector_list = state.selectionReducers.vector_list; + const currentVector = getState().selectionReducers.currentVector; - vector_list.forEach(item => dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, item), stage))); - // Set this - dispatch(setInitialFullGraph(data)); - // Do the query dispatch(incrementCountOfPendingVectorLoadRequests()); - dispatch(appendVectorOnList(generateMoleculeId(data))); - dispatch(selectVectorAndResetCompounds(undefined)); + dispatch(selectVectorAndResetCompounds(currentVector)); return api({ url: getViewUrl('graph', data) }) - .then(response => dispatch(updateFullGraph(response.data['graph']))) + .then(response => { + const result = response.data.graph; + var new_dict = {}; + // Uniquify + if (result) { + Object.keys(result).forEach(key => { + var smiSet = new Set(); + new_dict[key] = {}; + new_dict[key]['addition'] = []; + new_dict[key]['vector'] = result[key]['vector']; + Object.keys(result[key]['addition']).forEach(index => { + var newSmi = result[key]['addition'][index]['end']; + if (smiSet.has(newSmi) !== true) { + new_dict[key]['addition'].push(result[key]['addition'][index]); + smiSet.add(newSmi); + } + }); + }); + } + return dispatch(updateVectorCompounds(data.smiles, new_dict)); + }) .then(() => api({ url: getViewUrl('vector', data) })) - .then(response => dispatch(handleVector(response.data['vectors'], stage, data))) + .then(response => dispatch(handleVector(response.data.vectors, stage, data))) .finally(() => { dispatch(decrementCountOfPendingVectorLoadRequests()); const currentOrientation = stage.viewerControls.getOrientation(); @@ -132,9 +149,14 @@ export const addVector = (stage, data) => async (dispatch, getState) => { export const removeVector = (stage, data) => (dispatch, getState) => { const state = getState(); const vector_list = state.selectionReducers.vector_list; - vector_list.forEach(item => dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, item), stage))); - dispatch(setToQuery('')); + vector_list + .filter(item => item.moleculeId === data.id) + .forEach(item => dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, item), stage))); + dispatch(updateVectorCompounds(data.smiles, undefined)); + dispatch(updateBondColorMapOfCompounds(data.smiles, undefined)); dispatch(removeFromVectorOnList(generateMoleculeId(data))); + + dispatch(setVectorList(vector_list.filter(item => item.moleculeId !== data.id))); }; export const addProtein = (stage, data, colourToggle) => dispatch => { @@ -263,6 +285,9 @@ export const addLigand = (stage, data, colourToggle) => (dispatch, getState) => export const removeLigand = (stage, data) => dispatch => { dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage)); dispatch(removeFromFragmentDisplayList(generateMoleculeId(data))); + + // remove vector + dispatch(removeVector(stage, data)); }; /** @@ -317,19 +342,7 @@ export const hideAllSelectedMolecules = (stage, currentMolecules) => (dispatch, // vector_list dispatch(setVectorList([])); - // to_query_pk - // to_query_prot - // to_query_sdf_info - dispatch( - setInitialFullGraph({ - to_query: undefined, - to_query_pk: undefined, - to_query_sdf_info: undefined, - to_query_prot: undefined, - to_select: undefined, - querying: undefined - }) - ); - + dispatch(resetCompoundsOfVectors()); + dispatch(resetBondColorMapOfVectors()); dispatch(setCompoundImage(noCompoundImage)); }; diff --git a/js/components/preview/summary/CmpdSummaryImage.js b/js/components/preview/summary/CmpdSummaryImage.js index 0674c551e5..7a23a3f557 100644 --- a/js/components/preview/summary/CmpdSummaryImage.js +++ b/js/components/preview/summary/CmpdSummaryImage.js @@ -7,6 +7,7 @@ import { useDispatch, useSelector } from 'react-redux'; import SVGInline from 'react-svg-inline'; import { Box } from '@material-ui/core'; import { reloadSummaryCompoundImage } from './redux/dispatchAction'; +import { getAllCurrentBondColorMapOfVectors } from '../../../reducers/selection/selectors'; export const CmpdSummaryImage = memo(() => { const dispatch = useDispatch(); @@ -14,13 +15,17 @@ export const CmpdSummaryImage = memo(() => { const width = useSelector(state => state.previewReducers.summary.width); const height = useSelector(state => state.previewReducers.summary.height); const currentVector = useSelector(state => state.selectionReducers.currentVector); - const bondColorMap = useSelector(state => state.selectionReducers.bondColorMap); + const currentBondColorMapOfVectors = useSelector(getAllCurrentBondColorMapOfVectors); useEffect(() => { - dispatch(reloadSummaryCompoundImage({ currentVector, bondColorMap })).catch(error => { - throw new Error(error); - }); - }, [bondColorMap, currentVector, dispatch]); + if (currentVector && currentBondColorMapOfVectors) { + dispatch(reloadSummaryCompoundImage({ currentVector, bondColorMap: currentBondColorMapOfVectors })).catch( + error => { + throw new Error(error); + } + ); + } + }, [currentBondColorMapOfVectors, currentVector, dispatch]); return ( diff --git a/js/components/preview/summary/redux/dispatchAction.js b/js/components/preview/summary/redux/dispatchAction.js index 57130f5970..96540f6c23 100644 --- a/js/components/preview/summary/redux/dispatchAction.js +++ b/js/components/preview/summary/redux/dispatchAction.js @@ -12,6 +12,7 @@ import { } from './actions'; import { base_url } from '../../../routes/constants'; import { isEmpty } from 'lodash'; +import { getMoleculeOfCurrentVector } from '../../../../reducers/selection/selectors'; const fetchCompoundImage = url => (dispatch, getState) => { const state = getState(); @@ -31,7 +32,7 @@ const fetchCompoundImage = url => (dispatch, getState) => { }; const getAtomIndices = ({ currentVector, bondColorMap }) => { - if (currentVector === undefined) { + if (currentVector === null) { return undefined; } if (bondColorMap === undefined) { @@ -56,15 +57,16 @@ const getAtomIndices = ({ currentVector, bondColorMap }) => { export const reloadSummaryCompoundImage = ({ currentVector, bondColorMap }) => (dispatch, getState) => { const state = getState(); - const { to_query } = state.selectionReducers; + const moleculeOfVector = getMoleculeOfCurrentVector(state); + const smiles = moleculeOfVector && moleculeOfVector.smiles; let atomIndices = getAtomIndices({ currentVector, bondColorMap }); const url = new URL(base_url + '/viewer/img_from_smiles/'); let get_params = {}; - if (atomIndices !== undefined && to_query !== undefined) { - get_params = { smiles: to_query, atom_indices: atomIndices }; - } else if (to_query !== undefined) { - get_params = { smiles: to_query }; + if (atomIndices !== undefined && smiles !== undefined) { + get_params = { smiles, atom_indices: atomIndices }; + } else if (smiles !== undefined) { + get_params = { smiles }; } if (!isEmpty(get_params)) { diff --git a/js/components/session/redux/dispatchActions.js b/js/components/session/redux/dispatchActions.js index 12e426d7db..985f273e2a 100644 --- a/js/components/session/redux/dispatchActions.js +++ b/js/components/session/redux/dispatchActions.js @@ -9,10 +9,10 @@ import { setSessionTitle, setTargetUnrecognised } from '../../../reducers/api/actions'; -import { reloadSelectionReducer, setBondColorMap, setVectorList } from '../../../reducers/selection/actions'; +import { reloadSelectionReducer } from '../../../reducers/selection/actions'; import { reloadNglViewFromScene } from '../../../reducers/ngl/dispatchActions'; import { api, getCsrfToken, METHOD } from '../../../utils/api'; -import { canCheckTarget, generateBondColorMap, generateObjectList } from '../helpers'; +import { canCheckTarget } from '../helpers'; import { saveCurrentStateAsSessionScene } from '../../../reducers/ngl/actions'; import { savingStateConst, savingTypeConst } from '../constants'; import { setLoadedSession, setNewSessionFlag, setNextUUID, setSaveType } from './actions'; @@ -20,17 +20,6 @@ import { getStore } from '../../helpers/globalStore'; import { DJANGO_CONTEXT } from '../../../utils/djangoContext'; import { reloadPreviewReducer } from '../../preview/redux/dispatchActions'; -export const handleVector = json => dispatch => { - let objList = generateObjectList(json['3d']); - dispatch(setVectorList(objList)); - let vectorBondColorMap = generateBondColorMap(json['indices']); - dispatch(setBondColorMap(vectorBondColorMap)); -}; - -export const redeployVectorsLocal = url => dispatch => { - return api({ url }).then(response => dispatch(handleVector(response.data['vectors']))); -}; - export const reloadSession = (myJson, nglViewList) => dispatch => { let jsonOfView = JSON.parse(JSON.parse(JSON.parse(myJson.scene)).state); dispatch(reloadApiState(jsonOfView.apiReducers)); @@ -44,17 +33,6 @@ export const reloadSession = (myJson, nglViewList) => dispatch => { }); if (jsonOfView.selectionReducers.vectorOnList.length !== 0) { - let url = - window.location.protocol + - '//' + - window.location.host + - '/api/vector/' + - jsonOfView.selectionReducers.vectorOnList[JSON.stringify(0)] + - '/'; - dispatch(redeployVectorsLocal(url)).catch(error => { - throw new Error(error); - }); - dispatch(reloadPreviewReducer(jsonOfView.previewReducers)); } } diff --git a/js/reducers/api/selectors.js b/js/reducers/api/selectors.js new file mode 100644 index 0000000000..4092891467 --- /dev/null +++ b/js/reducers/api/selectors.js @@ -0,0 +1 @@ +export const getMoleculeList = state => state.apiReducers.molecule_list; diff --git a/js/reducers/selection/actions.js b/js/reducers/selection/actions.js index a6a0deb91b..d0c67526e5 100644 --- a/js/reducers/selection/actions.js +++ b/js/reducers/selection/actions.js @@ -25,34 +25,6 @@ export const removeFromToBuyList = function(item) { }; }; -export const setInitialFullGraph = function(item) { - return { - type: constants.SET_INITIAL_FULL_GRAPH, - item: item - }; -}; - -export const updateFullGraph = function(result) { - return { - type: constants.UPDATE_FULL_GRAPH, - input_mol_dict: result - }; -}; - -export const setBondColorMap = function(result) { - return { - type: constants.SET_BOND_COLOR_MAP, - bondColorMap: result - }; -}; - -export const setToQuery = function(to_query) { - return { - type: constants.SET_TO_QUERY, - to_query - }; -}; - export const setVectorList = function(vectList) { return { type: constants.SET_VECTOR_LIST, @@ -60,10 +32,10 @@ export const setVectorList = function(vectList) { }; }; -export const selectVector = function(vector) { +export const selectVector = vectorSmile => { return { type: constants.SELECT_VECTOR, - vector: vector + payload: vectorSmile }; }; @@ -192,10 +164,10 @@ export const removeFromVectorOnList = function(item) { }; }; -export const reloadSelectionReducer = function(savedSelectionReducers) { +export const reloadSelectionReducer = savedSelectionReducers => { return { type: constants.RELOAD_SELECTION_REDUCER, - savedSelectionReducers + payload: savedSelectionReducers }; }; @@ -236,7 +208,25 @@ export const setFilterSettings = filterSettings => ({ payload: filterSettings }); +export const resetCompoundsOfVectors = () => ({ + type: constants.RESET_COMPOUNDS_OF_VECTORS +}); + +export const updateVectorCompounds = (key, value) => ({ + type: constants.UPDATE_VECTOR_COMPOUNDS, + payload: { key, value } +}); + export const setFirstLoad = firstLoad => ({ type: constants.SET_FIRST_LOAD, payload: firstLoad }); + +export const resetBondColorMapOfVectors = () => ({ + type: constants.RESET_BOND_COLOR_MAP_OF_VECTORS +}); + +export const updateBondColorMapOfCompounds = (key, value) => ({ + type: constants.UPDATE_BOND_COLOR_MAP_OF_COMPOUNDS, + payload: { key, value } +}); diff --git a/js/reducers/selection/constants.js b/js/reducers/selection/constants.js index 2c31c3285b..2b683cf156 100644 --- a/js/reducers/selection/constants.js +++ b/js/reducers/selection/constants.js @@ -8,10 +8,6 @@ export const constants = { SET_TO_BUY_LIST: prefix + 'SET_TO_BUY_LIST', APPEND_TO_BUY_LIST: prefix + 'APPEND_TO_BUY_LIST', REMOVE_FROM_TO_BUY_LIST: prefix + 'REMOVE_FROM_TO_BUY_LIST', - SET_INITIAL_FULL_GRAPH: prefix + 'SET_INITIAL_FULL_GRAPH', - UPDATE_FULL_GRAPH: prefix + 'UPDATE_FULL_GRAPH', - SET_BOND_COLOR_MAP: prefix + 'SET_BOND_COLOR_MAP', - SET_TO_QUERY: prefix + 'SET_TO_QUERY', SET_VECTOR_LIST: prefix + 'SET_VECTOR_LIST', SELECT_VECTOR: prefix + 'SELECT_VECTOR', SET_FRAGMENT_DISPLAY_LIST: prefix + 'SET_FRAGMENT_DISPLAY_LIST', @@ -36,8 +32,13 @@ export const constants = { RESET_SELECTION_STATE: prefix + 'RESET_SELECTION_STATE', SET_MOL_GROUP_SELECTION: prefix + 'SET_MOL_GROUP_SELECTION', SET_FILTER: prefix + 'SET_FILTER', + SET_FIRST_LOAD: prefix + 'SET_FIRST_LOAD', SET_FILTER_SETTINGS: prefix + 'SET_FILTER_SETTINGS', - SET_FIRST_LOAD: prefix + 'SET_FIRST_LOAD' + + RESET_COMPOUNDS_OF_VECTORS: prefix + 'RESET_COMPOUNDS_OF_VECTORS', + UPDATE_VECTOR_COMPOUNDS: prefix + 'UPDATE_VECTOR_COMPOUNDS', + RESET_BOND_COLOR_MAP_OF_VECTORS: prefix + 'RESET_BOND_COLOR_MAP_OF_VECTORS', + UPDATE_BOND_COLOR_MAP_OF_COMPOUNDS: prefix + 'UPDATE_BOND_COLOR_MAP_OF_COMPOUNDS' }; export const PREDEFINED_FILTERS = { diff --git a/js/reducers/selection/dispatchActions.js b/js/reducers/selection/dispatchActions.js index 7efc090608..18d87bef1f 100644 --- a/js/reducers/selection/dispatchActions.js +++ b/js/reducers/selection/dispatchActions.js @@ -3,10 +3,11 @@ import { setFilter, selectVector } from './actions'; import { getAllCompoundsList } from './selectors'; import { MOL_ATTRIBUTES } from '../../components/preview/molecule/redux/constants'; -export const selectVectorAndResetCompounds = currentVector => async (dispatch, getState) => { +export const selectVectorAndResetCompounds = vectorSmile => async (dispatch, getState) => { await dispatch(resetCurrentCompoundsSettings(false)); - dispatch(selectVector(currentVector)); - dispatch(setCurrentCompounds(getAllCompoundsList(getState()))); + await dispatch(selectVector(vectorSmile)); + const currentCompoundsList = getAllCompoundsList(getState()); + dispatch(setCurrentCompounds(currentCompoundsList)); }; export const getListedMolecules = (object_selection, cached_mol_lists) => { diff --git a/js/reducers/selection/selectionReducers.js b/js/reducers/selection/selectionReducers.js index 0cc9121720..3221d736c4 100644 --- a/js/reducers/selection/selectionReducers.js +++ b/js/reducers/selection/selectionReducers.js @@ -5,27 +5,28 @@ import { constants } from './constants'; export const INITIAL_STATE = { to_buy_list: [], - to_select: {}, vector_list: [], - to_query_pk: undefined, - to_query_prot: undefined, - to_query_sdf_info: undefined, - this_vector_list: {}, - querying: false, - to_query: undefined, fragmentDisplayList: [], - bondColorMap: undefined, proteinList: [], complexList: [], surfaceList: [], densityList: [], vectorOnList: [], - currentVector: undefined, countOfPendingVectorLoadRequests: 0, mol_group_selection: [], object_selection: undefined, filter: undefined, filterSettings: undefined, + + compoundsOfVectors: null, // list of all vector's compounds to pick + // compoundsOfVectors: { + // [vectorID] :{} // this object replaces to_select, based on vector smile + // } + bondColorMapOfVectors: null, // list of all vector's compounds to pick + // bondColorMapOfVectors: { + // [vectorID] :{} // based on currentVector (smile) + // } + currentVector: null, // selected vector smile (ID) of compoundsOfVectors firstLoad: false }; @@ -75,55 +76,9 @@ export default function selectionReducers(state = INITIAL_STATE, action = {}) { return Object.assign({}, state); } - case constants.SET_INITIAL_FULL_GRAPH: - var input_mol = action.item; - return Object.assign({}, state, { - to_query: input_mol.smiles, - to_query_pk: input_mol.id, - to_query_sdf_info: input_mol.sdf_info, - to_query_prot: input_mol.prot_id, - to_select: {}, - querying: true - }); - - case constants.SET_TO_QUERY: - return Object.assign({}, state, { - to_query: action.to_query - }); - - case constants.UPDATE_FULL_GRAPH: - const input_mol_dict = action.input_mol_dict; - var new_dict = {}; - // Uniquify - for (var input_mol_dict_key in input_mol_dict) { - var smiSet = new Set(); - new_dict[input_mol_dict_key] = {}; - new_dict[input_mol_dict_key]['addition'] = []; - new_dict[input_mol_dict_key]['vector'] = input_mol_dict[input_mol_dict_key]['vector']; - for (var index in input_mol_dict[input_mol_dict_key]['addition']) { - var newSmi = input_mol_dict[input_mol_dict_key]['addition'][index]['end']; - if (smiSet.has(newSmi) !== true) { - new_dict[input_mol_dict_key]['addition'].push(input_mol_dict[input_mol_dict_key]['addition'][index]); - smiSet.add(newSmi); - } - } - } - return Object.assign({}, state, { - to_select: new_dict, - querying: false - }); - case constants.SELECT_VECTOR: - var input_mol_key = action.vector; - var new_this_vector_list = {}; - for (var key_to_select in state.to_select) { - if (key_to_select.split('_')[0] === input_mol_key) { - new_this_vector_list[key_to_select] = state.to_select[key_to_select]; - } - } return Object.assign({}, state, { - this_vector_list: new_this_vector_list, - currentVector: action.vector + currentVector: action.payload }); case constants.SET_FRAGMENT_DISPLAY_LIST: @@ -217,52 +172,44 @@ export default function selectionReducers(state = INITIAL_STATE, action = {}) { return Object.assign({}, state, { vectorOnList: [...newVectorOnList] }); case constants.APPEND_VECTOR_ON_LIST: - return Object.assign({}, state, { vectorOnList: [action.item.id] }); + return Object.assign({}, state, { vectorOnList: [...new Set([...state.vectorOnList, action.item.id])] }); case constants.REMOVE_FROM_VECTOR_ON_LIST: let diminishedVectorOnList = new Set(state.vectorOnList); diminishedVectorOnList.delete(action.item.id); - return Object.assign({}, state, { vectorOnList: [...diminishedVectorOnList], currentVector: undefined }); - - case constants.SET_BOND_COLOR_MAP: return Object.assign({}, state, { - bondColorMap: action.bondColorMap + vectorOnList: [...diminishedVectorOnList], + currentVector: action.item.id === state.currentVector ? null : state.currentVector }); case constants.RELOAD_SELECTION_REDUCER: - var this_vector_list = {}; - for (var to_select_item in action.savedSelectionReducers.to_select) { - if (to_select_item === action.savedSelectionReducers.currentVector) { - this_vector_list[to_select_item] = action.savedSelectionReducers.to_select[to_select_item]; - } - } let newFraments = new Set(); - action.savedSelectionReducers.fragmentDisplayList.forEach(f => { + action.payload.fragmentDisplayList.forEach(f => { newFraments.add(f); }); let newProteins = new Set(); - action.savedSelectionReducers.proteinList.forEach(p => { + action.payload.proteinList.forEach(p => { newProteins.add(p); }); let newComplexes = new Set(); - action.savedSelectionReducers.complexList.forEach(c => { + action.payload.complexList.forEach(c => { newComplexes.add(c); }); let newSurfaces = new Set(); - action.savedSelectionReducers.surfaceList.forEach(s => { + action.payload.surfaceList.forEach(s => { newSurfaces.add(s); }); let newDensities = new Set(); - action.savedSelectionReducers.densityList.forEach(d => { + action.payload.densityList.forEach(d => { newDensities.add(d); }); let newVectors = new Set(); - action.savedSelectionReducers.vectorOnList.forEach(v => { + action.payload.vectorOnList.forEach(v => { newVectors.add(v); }); + return Object.assign({}, state, { - this_vector_list: this_vector_list, - ...action.savedSelectionReducers, + ...action.payload, fragmentDisplayList: [...newFraments], proteinList: [...newProteins], complexList: [...newComplexes], @@ -309,6 +256,37 @@ export default function selectionReducers(state = INITIAL_STATE, action = {}) { firstLoad: action.payload }); + case constants.RESET_COMPOUNDS_OF_VECTORS: + return Object.assign({}, state, { + compoundsOfVectors: null + }); + + case constants.UPDATE_VECTOR_COMPOUNDS: + let compoundsOfVectors = JSON.parse(JSON.stringify(state.compoundsOfVectors)); + if (!compoundsOfVectors) { + compoundsOfVectors = {}; + } + compoundsOfVectors[action.payload.key] = action.payload.value; + + return Object.assign({}, state, { + compoundsOfVectors: compoundsOfVectors + }); + + case constants.RESET_BOND_COLOR_MAP_OF_VECTORS: + return Object.assign({}, state, { + bondColorMapOfVectors: null + }); + + case constants.UPDATE_BOND_COLOR_MAP_OF_COMPOUNDS: + let bondColorMapOfVectors = JSON.parse(JSON.stringify(state.bondColorMapOfVectors)); + if (!bondColorMapOfVectors) { + bondColorMapOfVectors = {}; + } + bondColorMapOfVectors[action.payload.key] = action.payload.value; + + return Object.assign({}, state, { + bondColorMapOfVectors + }); // Cases like: @@redux/INIT default: return state; diff --git a/js/reducers/selection/selectors.js b/js/reducers/selection/selectors.js index aff0cbb663..51ea83689d 100644 --- a/js/reducers/selection/selectors.js +++ b/js/reducers/selection/selectors.js @@ -1,40 +1,89 @@ import { createSelector } from 'reselect'; +import { getMoleculeList } from '../api/selectors'; -const getToSelect = state => state.selectionReducers.to_select; -const getToQuery = state => state.selectionReducers.to_query; -const getThisVectorList = state => state.selectionReducers.this_vector_list; const getCurrentCompoundClass = state => state.previewReducers.compounds.currentCompoundClass; +const getVectorList = state => state.selectionReducers.vector_list; +const getCurrentVector = state => state.selectionReducers.currentVector; +const getBondColorMapOfVectors = state => state.selectionReducers.bondColorMapOfVectors; +const getCompoundsOfVectors = state => state.selectionReducers.compoundsOfVectors; -export const getTotalCountOfMolecules = createSelector(getToSelect, to_select => { - let tot_num = 0; - Object.keys(to_select).forEach(key => { - tot_num += to_select[key].addition ? to_select[key].addition.length : 0; - }); - return tot_num; -}); +export const getMoleculeOfCurrentVector = createSelector( + getCurrentVector, + getVectorList, + getMoleculeList, + (selectedVectorSmile, vectorList, moleculeList) => { + if (selectedVectorSmile !== null) { + const foundedVector = vectorList.find(vector => vector.name.includes(selectedVectorSmile)); + if (foundedVector) { + return moleculeList.find(molecule => molecule.id === foundedVector.moleculeId); + } + } + return null; + } +); + +export const getAllCurrentVectorCompounds = createSelector( + getCompoundsOfVectors, + getMoleculeOfCurrentVector, + (compoundsOfVectors, currentMolecule) => { + if (currentMolecule !== null && currentMolecule.smiles && compoundsOfVectors !== null) { + return compoundsOfVectors[currentMolecule.smiles]; + } + return null; + } +); + +export const getAllCurrentBondColorMapOfVectors = createSelector( + getBondColorMapOfVectors, + getMoleculeOfCurrentVector, + (bondColorMapOfVectors, currentMolecule) => { + if (currentMolecule !== null && currentMolecule.smiles && bondColorMapOfVectors !== null) { + return bondColorMapOfVectors[currentMolecule.smiles]; + } + return null; + } +); + +export const getCurrentVectorCompoundsFiltered = createSelector( + getAllCurrentVectorCompounds, + getCurrentVector, + (currentVectorCompounds, selectedVectorSmile) => { + if (currentVectorCompounds !== null && selectedVectorSmile !== null) { + var new_this_vector_list = {}; + Object.keys(currentVectorCompounds).forEach(key => { + if (key.split('_')[0] === selectedVectorSmile) { + new_this_vector_list[key] = currentVectorCompounds[key]; + } + }); + return new_this_vector_list; + } + return null; + } +); export const getAllCompoundsList = createSelector( - getThisVectorList, + getCurrentVectorCompoundsFiltered, getCurrentCompoundClass, - getToQuery, - (thisVectorList, currentCompoundClass, to_query) => { + getMoleculeOfCurrentVector, + (currentVectorCompoundsFiltered, currentCompoundClass, moleculeOfVector) => { let compoundsList = []; - Object.keys(thisVectorList).forEach(key => { - const vector_smi = thisVectorList[key].vector; - const change_list = thisVectorList[key].addition; - change_list.forEach(data_transfer => { - const inputData = {}; - inputData.smiles = data_transfer && data_transfer.end; - // Set this back for now - because it's confusing - alter to change if want later - inputData.show_frag = data_transfer && data_transfer.end; - inputData.vector = vector_smi; - inputData.mol = to_query; - inputData.class = currentCompoundClass; - inputData.isShowed = false; - compoundsList.push(inputData); + if (currentVectorCompoundsFiltered) { + Object.keys(currentVectorCompoundsFiltered).forEach(key => { + const vector_smi = currentVectorCompoundsFiltered[key].vector; + const change_list = currentVectorCompoundsFiltered[key].addition; + change_list.forEach(data_transfer => { + const inputData = {}; + inputData.smiles = data_transfer && data_transfer.end; + // Set this back for now - because it's confusing - alter to change if want later + inputData.show_frag = data_transfer && data_transfer.end; + inputData.vector = vector_smi; + inputData.mol = moleculeOfVector && moleculeOfVector.smiles; + inputData.class = currentCompoundClass; + inputData.isShowed = false; + compoundsList.push(inputData); + }); }); - }); - + } return compoundsList; } );