From 9dfd6b73a87515f179135c0ccd1a58f84d2e5f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1na=20Kohanov=C3=A1?= Date: Thu, 22 Oct 2020 08:27:09 +0200 Subject: [PATCH] #407 Properly turn on/off inspiration fragments when using the next/previous arrows (bug of #384) --- js/components/datasets/datasetMoleculeList.js | 132 +++------------- .../datasets/redux/dispatchActions.js | 143 ++++++++++++++++++ .../datasets/selectedCompoundsList.js | 105 +++++-------- .../preview/molecule/moleculeList.js | 3 + 4 files changed, 206 insertions(+), 177 deletions(-) diff --git a/js/components/datasets/datasetMoleculeList.js b/js/components/datasets/datasetMoleculeList.js index ee73503a6..304d60772 100644 --- a/js/components/datasets/datasetMoleculeList.js +++ b/js/components/datasets/datasetMoleculeList.js @@ -35,29 +35,19 @@ import { addDatasetSurface, removeDatasetSurface, autoHideDatasetDialogsOnScroll, - loadInspirationMoleculesDataList, - clearAllInspirationsOfDataset + moveMoleculeInspirationsSettings, + removeAllSelectedDatasetMolecules } from './redux/dispatchActions'; import { setFilterDialogOpen, setSearchStringOfCompoundSet } from './redux/actions'; import { DatasetFilter } from './datasetFilter'; import { FilterList, Search, Link } from '@material-ui/icons'; -import { getFilteredDatasetMoleculeList, isAnyInspirationTurnedOnByType } from './redux/selectors'; +import { getFilteredDatasetMoleculeList } from './redux/selectors'; import { debounce } from 'lodash'; import { InspirationDialog } from './inspirationDialog'; import { CrossReferenceDialog } from './crossReferenceDialog'; import { AlertModal } from '../common/Modal/AlertModal'; import { hideAllSelectedMolecules } from '../preview/molecule/redux/dispatchActions'; import { getMoleculeList } from '../preview/molecule/redux/selectors'; -import { - addVector, - addHitProtein, - addComplex, - addSurface, - addLigand, - addDensity -} from '../preview/molecule/redux/dispatchActions'; -import { OBJECT_TYPE } from '../nglView/constants'; -import { getRepresentationsByType } from '../nglView/generatingObjects'; const useStyles = makeStyles(theme => ({ container: { @@ -286,7 +276,6 @@ export const DatasetMoleculeList = memo( const ligandList = useSelector(state => state.datasetsReducers.ligandLists[datasetID]); const proteinList = useSelector(state => state.datasetsReducers.proteinLists[datasetID]); const complexList = useSelector(state => state.datasetsReducers.complexLists[datasetID]); - const surfaceList = useSelector(state => state.datasetsReducers.surfaceLists[datasetID]); const isLigandOn = (ligandList && ligandList.length > 0) || false; const isProteinOn = (proteinList && proteinList.length > 0) || false; @@ -311,109 +300,24 @@ export const DatasetMoleculeList = memo( }; const removeOfAllSelectedTypes = () => { - ligandList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); - dispatch( - removeDatasetLigand(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], datasetID) - ); - }); - proteinList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); - dispatch( - removeDatasetHitProtein(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], datasetID) - ); - }); - complexList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); - dispatch( - removeDatasetComplex(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], datasetID) - ); - }); - surfaceList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); - dispatch( - removeDatasetSurface(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], datasetID) - ); - }); - }; - - const moveInspirations = ( - isAnyInspirationLigandOn, - isAnyInspirationProteinOn, - isAnyInspirationComplexOn, - isAnyInspirationSurfaceOn, - isAnyInspirationDensityOn, - isAnyInspirationVectorOn - ) => (dispatch, getState) => { - const state = getState(); - const molecules = state.datasetsReducers.inspirationMoleculeDataList; - if (molecules) { - molecules.forEach(molecule => { - if (molecule) { - if (isAnyInspirationLigandOn) { - let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.LIGAND); - dispatch(addLigand(stage, molecule, colourList[molecule.id % colourList.length], false, representations)); - } - if (isAnyInspirationProteinOn) { - let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.HIT_PROTEIN); - dispatch(addHitProtein(stage, molecule, colourList[molecule.id % colourList.length], representations)); - } - if (isAnyInspirationComplexOn) { - let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.COMPLEX); - dispatch(addComplex(stage, molecule, colourList[molecule.id % colourList.length], representations)); - } - if (isAnyInspirationSurfaceOn) { - let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.SURFACE); - dispatch(addSurface(stage, molecule, colourList[molecule.id % colourList.length], representations)); - } - if (isAnyInspirationDensityOn) { - let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.DENSITY); - dispatch(addDensity(stage, molecule, colourList[molecule.id % colourList.length], representations)); - } - if (isAnyInspirationVectorOn) { - dispatch(addVector(stage, molecule, colourList[molecule.id % colourList.length])); - } - } - }); - } + dispatch(removeAllSelectedDatasetMolecules(stage)); }; const moveSelectedMoleculeInspirationsSettings = (data, newItemData) => (dispatch, getState) => { - dispatch(clearAllInspirationsOfDataset()); - if (newItemData) { - let computed_inspirations = (data && data.computed_inspirations) || []; - let isAnyInspirationLigandOn = isAnyInspirationTurnedOnByType( - computed_inspirations, - fragmentDisplayListMolecule - ); - let isAnyInspirationProteinOn = isAnyInspirationTurnedOnByType(computed_inspirations, proteinListMolecule); - let isAnyInspirationComplexOn = isAnyInspirationTurnedOnByType(computed_inspirations, complexListMolecule); - let isAnyInspirationSurfaceOn = isAnyInspirationTurnedOnByType(computed_inspirations, surfaceListMolecule); - let isAnyInspirationDensityOn = isAnyInspirationTurnedOnByType(computed_inspirations, densityListMolecule); - let isAnyInspirationVectorOn = isAnyInspirationTurnedOnByType(computed_inspirations, vectorOnListMolecule); - - if ( - isAnyInspirationLigandOn || - isAnyInspirationProteinOn || - isAnyInspirationComplexOn || - isAnyInspirationSurfaceOn || - isAnyInspirationDensityOn || - isAnyInspirationVectorOn - ) { - dispatch(loadInspirationMoleculesDataList(newItemData.computed_inspirations)).then(() => { - dispatch( - moveInspirations( - isAnyInspirationLigandOn, - isAnyInspirationProteinOn, - isAnyInspirationComplexOn, - isAnyInspirationSurfaceOn, - isAnyInspirationDensityOn, - isAnyInspirationVectorOn - ) - ); - }); - } - } + dispatch( + moveMoleculeInspirationsSettings( + data, + newItemData, + stage, + objectsInView, + fragmentDisplayListMolecule, + proteinListMolecule, + complexListMolecule, + surfaceListMolecule, + densityListMolecule, + vectorOnListMolecule + ) + ); }; // TODO "currentMolecules" do not need to correspondent to selections in {type}List diff --git a/js/components/datasets/redux/dispatchActions.js b/js/components/datasets/redux/dispatchActions.js index 5bcf48e62..d65ab5e61 100644 --- a/js/components/datasets/redux/dispatchActions.js +++ b/js/components/datasets/redux/dispatchActions.js @@ -43,6 +43,17 @@ import { getInitialDatasetFilterProperties, getInitialDatasetFilterSettings } fr import { COUNT_OF_VISIBLE_SCORES } from './constants'; import { colourList } from '../../preview/molecule/moleculeView'; import { appendMoleculeOrientation } from '../../../reducers/ngl/actions'; +import { isAnyInspirationTurnedOnByType } from './selectors'; +import { + addVector, + addHitProtein, + addComplex, + addSurface, + addLigand, + addDensity +} from '../../preview/molecule/redux/dispatchActions'; +import { OBJECT_TYPE } from '../../nglView/constants'; +import { getRepresentationsByType } from '../../nglView/generatingObjects'; export const initializeDatasetFilter = datasetID => (dispatch, getState) => { const initFilterSettings = getInitialDatasetFilterSettings(getState(), datasetID); @@ -539,4 +550,136 @@ export const autoHideDatasetDialogsOnScroll = ({ inspirationDialogRef, crossRefe } }; +export const removeAllSelectedDatasetMolecules = stage => (dispatch, getState) => { + const state = getState(); + const datasets = state.datasetsReducers.datasets; + const currentMolecules = state.datasetsReducers.moleculeLists; + if (datasets) { + datasets.forEach(dataset => { + let datasetID = dataset.id; + const ligandList = state.datasetsReducers.ligandLists[datasetID]; + const proteinList = state.datasetsReducers.proteinLists[datasetID]; + const complexList = state.datasetsReducers.complexLists[datasetID]; + const surfaceList = state.datasetsReducers.surfaceLists[datasetID]; + + let molecules = currentMolecules[datasetID]; + ligandList?.forEach(moleculeID => { + const foundedMolecule = molecules?.find(mol => mol.id === moleculeID); + dispatch( + removeDatasetLigand(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], datasetID) + ); + }); + proteinList?.forEach(moleculeID => { + const foundedMolecule = molecules?.find(mol => mol.id === moleculeID); + dispatch( + removeDatasetHitProtein(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], datasetID) + ); + }); + complexList?.forEach(moleculeID => { + const foundedMolecule = molecules?.find(mol => mol.id === moleculeID); + dispatch( + removeDatasetComplex(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], datasetID) + ); + }); + surfaceList?.forEach(moleculeID => { + const foundedMolecule = molecules?.find(mol => mol.id === moleculeID); + dispatch( + removeDatasetSurface(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], datasetID) + ); + }); + }); + } +}; + +export const moveMoleculeInspirationsSettings = ( + data, + newItemData, + stage, + objectsInView, + fragmentDisplayListMolecule, + proteinListMolecule, + complexListMolecule, + surfaceListMolecule, + densityListMolecule, + vectorOnListMolecule +) => (dispatch, getState) => { + dispatch(clearAllInspirationsOfDataset()); + if (newItemData) { + let computed_inspirations = (data && data.computed_inspirations) || []; + let isAnyInspirationLigandOn = isAnyInspirationTurnedOnByType(computed_inspirations, fragmentDisplayListMolecule); + let isAnyInspirationProteinOn = isAnyInspirationTurnedOnByType(computed_inspirations, proteinListMolecule); + let isAnyInspirationComplexOn = isAnyInspirationTurnedOnByType(computed_inspirations, complexListMolecule); + let isAnyInspirationSurfaceOn = isAnyInspirationTurnedOnByType(computed_inspirations, surfaceListMolecule); + let isAnyInspirationDensityOn = isAnyInspirationTurnedOnByType(computed_inspirations, densityListMolecule); + let isAnyInspirationVectorOn = isAnyInspirationTurnedOnByType(computed_inspirations, vectorOnListMolecule); + + if ( + isAnyInspirationLigandOn || + isAnyInspirationProteinOn || + isAnyInspirationComplexOn || + isAnyInspirationSurfaceOn || + isAnyInspirationDensityOn || + isAnyInspirationVectorOn + ) { + dispatch(loadInspirationMoleculesDataList(newItemData.computed_inspirations)).then(() => { + dispatch( + moveInspirations( + stage, + objectsInView, + isAnyInspirationLigandOn, + isAnyInspirationProteinOn, + isAnyInspirationComplexOn, + isAnyInspirationSurfaceOn, + isAnyInspirationDensityOn, + isAnyInspirationVectorOn + ) + ); + }); + } + } +}; + +const moveInspirations = ( + stage, + objectsInView, + isAnyInspirationLigandOn, + isAnyInspirationProteinOn, + isAnyInspirationComplexOn, + isAnyInspirationSurfaceOn, + isAnyInspirationDensityOn, + isAnyInspirationVectorOn +) => (dispatch, getState) => { + const state = getState(); + const molecules = state.datasetsReducers.inspirationMoleculeDataList; + if (molecules) { + molecules.forEach(molecule => { + if (molecule) { + if (isAnyInspirationLigandOn) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.LIGAND); + dispatch(addLigand(stage, molecule, colourList[molecule.id % colourList.length], false, representations)); + } + if (isAnyInspirationProteinOn) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.HIT_PROTEIN); + dispatch(addHitProtein(stage, molecule, colourList[molecule.id % colourList.length], representations)); + } + if (isAnyInspirationComplexOn) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.COMPLEX); + dispatch(addComplex(stage, molecule, colourList[molecule.id % colourList.length], representations)); + } + if (isAnyInspirationSurfaceOn) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.SURFACE); + dispatch(addSurface(stage, molecule, colourList[molecule.id % colourList.length], representations)); + } + if (isAnyInspirationDensityOn) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.DENSITY); + dispatch(addDensity(stage, molecule, colourList[molecule.id % colourList.length], representations)); + } + if (isAnyInspirationVectorOn) { + dispatch(addVector(stage, molecule, colourList[molecule.id % colourList.length])); + } + } + }); + } +}; + export const getDatasetMoleculeID = (datasetID, moleculeID) => `datasetID-${datasetID}_moleculeID-${moleculeID}`; diff --git a/js/components/datasets/selectedCompoundsList.js b/js/components/datasets/selectedCompoundsList.js index ee6979dad..760b61701 100644 --- a/js/components/datasets/selectedCompoundsList.js +++ b/js/components/datasets/selectedCompoundsList.js @@ -4,21 +4,20 @@ import { CircularProgress, Grid, makeStyles, Typography } from '@material-ui/cor import { useDispatch, useSelector } from 'react-redux'; import { getMoleculesObjectIDListOfCompoundsToBuy } from './redux/selectors'; import InfiniteScroll from 'react-infinite-scroller'; -import { colourList, DatasetMoleculeView } from './datasetMoleculeView'; +import { DatasetMoleculeView } from './datasetMoleculeView'; import { InspirationDialog } from './inspirationDialog'; import { setIsOpenInspirationDialog } from './redux/actions'; import { CrossReferenceDialog } from './crossReferenceDialog'; import { autoHideDatasetDialogsOnScroll, - removeDatasetComplex, - removeDatasetHitProtein, - removeDatasetLigand, - removeDatasetSurface, - resetCrossReferenceDialog + resetCrossReferenceDialog, + moveMoleculeInspirationsSettings, + removeAllSelectedDatasetMolecules } from './redux/dispatchActions'; -import MoleculeView from '../preview/molecule/moleculeView'; import { NglContext } from '../nglView/nglProvider'; import { VIEWS } from '../../constants/constants'; +import { hideAllSelectedMolecules } from '../preview/molecule/redux/dispatchActions'; +import { getMoleculeList } from '../preview/molecule/redux/selectors'; const useStyles = makeStyles(theme => ({ container: { @@ -65,64 +64,42 @@ export const SelectedCompoundList = memo(({ height }) => { const currentMolecules = moleculesObjectIDListOfCompoundsToBuy.slice(0, listItemOffset); const canLoadMore = listItemOffset < moleculesObjectIDListOfCompoundsToBuy.length; - const ligandListAllDatasets = useSelector(state => state.datasetsReducers.ligandLists); - const proteinListAllDatasets = useSelector(state => state.datasetsReducers.proteinLists); - const complexListAllDatasets = useSelector(state => state.datasetsReducers.complexLists); - const surfaceListAllDatasets = useSelector(state => state.datasetsReducers.surfaceLists); + const objectsInView = useSelector(state => state.nglReducers.objectsInView) || {}; + + const getJoinedMoleculeList = useSelector(state => getMoleculeList(state)); + const allInspirationMoleculeDataList = useSelector(state => state.datasetsReducers.allInspirationMoleculeDataList); + + const proteinListMolecule = useSelector(state => state.selectionReducers.proteinList); + const complexListMolecule = useSelector(state => state.selectionReducers.complexList); + const fragmentDisplayListMolecule = useSelector(state => state.selectionReducers.fragmentDisplayList); + const surfaceListMolecule = useSelector(state => state.selectionReducers.surfaceList); + const densityListMolecule = useSelector(state => state.selectionReducers.densityList); + const vectorOnListMolecule = useSelector(state => state.selectionReducers.vectorOnList); const removeOfAllSelectedTypes = () => { - Object.keys(ligandListAllDatasets).forEach(datasetKey => { - ligandListAllDatasets[datasetKey]?.forEach(moleculeID => { - const foundedMolecule = currentMolecules?.find(mol => mol?.molecule?.id === moleculeID); - dispatch( - removeDatasetLigand( - stage, - foundedMolecule?.molecule, - colourList[foundedMolecule?.molecule?.id % colourList.length], - datasetKey - ) - ); - }); - }); - Object.keys(proteinListAllDatasets).forEach(datasetKey => { - proteinListAllDatasets[datasetKey]?.forEach(moleculeID => { - const foundedMolecule = currentMolecules?.find(mol => mol?.molecule?.id === moleculeID); - dispatch( - removeDatasetHitProtein( - stage, - foundedMolecule?.molecule, - colourList[foundedMolecule?.molecule?.id % colourList.length], - datasetKey - ) - ); - }); - }); - Object.keys(complexListAllDatasets).forEach(datasetKey => { - complexListAllDatasets[datasetKey]?.forEach(moleculeID => { - const foundedMolecule = currentMolecules?.find(mol => mol?.molecule?.id === moleculeID); - dispatch( - removeDatasetComplex( - stage, - foundedMolecule?.molecule, - colourList[foundedMolecule?.molecule?.id % colourList.length], - datasetKey - ) - ); - }); - }); - Object.keys(surfaceListAllDatasets).forEach(datasetKey => { - surfaceListAllDatasets[datasetKey]?.forEach(moleculeID => { - const foundedMolecule = currentMolecules?.find(mol => mol?.molecule?.id === moleculeID); - dispatch( - removeDatasetSurface( - stage, - foundedMolecule?.molecule, - colourList[foundedMolecule?.molecule?.id % colourList.length], - datasetKey - ) - ); - }); - }); + dispatch(removeAllSelectedDatasetMolecules(stage)); + }; + + const removeOfAllSelectedTypesOfInspirations = () => { + let molecules = [...getJoinedMoleculeList, ...allInspirationMoleculeDataList]; + dispatch(hideAllSelectedMolecules(stage, [...molecules])); + }; + + const moveSelectedMoleculeInspirationsSettings = (data, newItemData) => (dispatch, getState) => { + dispatch( + moveMoleculeInspirationsSettings( + data, + newItemData, + stage, + objectsInView, + fragmentDisplayListMolecule, + proteinListMolecule, + complexListMolecule, + surfaceListMolecule, + densityListMolecule, + vectorOnListMolecule + ) + ); }; useEffect(() => { @@ -185,6 +162,8 @@ export const SelectedCompoundList = memo(({ height }) => { previousItemData={index > 0 && array[index - 1]} nextItemData={index < array?.length && array[index + 1]} removeOfAllSelectedTypes={removeOfAllSelectedTypes} + removeOfAllSelectedTypesOfInspirations={removeOfAllSelectedTypesOfInspirations} + moveSelectedMoleculeInspirationsSettings={moveSelectedMoleculeInspirationsSettings} /> ))} diff --git a/js/components/preview/molecule/moleculeList.js b/js/components/preview/molecule/moleculeList.js index c71dba646..451caabbf 100644 --- a/js/components/preview/molecule/moleculeList.js +++ b/js/components/preview/molecule/moleculeList.js @@ -59,6 +59,7 @@ import { useRouteMatch } from 'react-router-dom'; import { setSortDialogOpen } from './redux/actions'; import { setCachedMolLists, setMoleculeList } from '../../../reducers/api/actions'; import { AlertModal } from '../../common/Modal/AlertModal'; +import { removeAllSelectedDatasetMolecules } from '../../datasets/redux/dispatchActions'; const useStyles = makeStyles(theme => ({ container: { @@ -461,6 +462,8 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei const foundedMolecule = molecules?.find(mol => mol.id === moleculeID); dispatch(removeVector(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length])); }); + + dispatch(removeAllSelectedDatasetMolecules(stage)); }; const addNewType = type => {