diff --git a/js/components/preview/molecule/moleculeListSortFilterDialog.js b/js/components/preview/molecule/moleculeListSortFilterDialog.js index 0d659ddb8..2b727af1f 100644 --- a/js/components/preview/molecule/moleculeListSortFilterDialog.js +++ b/js/components/preview/molecule/moleculeListSortFilterDialog.js @@ -173,6 +173,9 @@ export const MoleculeListSortFilterDialog = memo( }, [joinedMoleculeLists]); const [initState, setInitState] = useState(initialize()); + + filter = filter || initState; + const [filteredCount, setFilteredCount] = useState(getFilteredMoleculesCount(joinedMoleculeLists, filter)); const [predefinedFilter, setPredefinedFilter] = useState(filter.predefined); diff --git a/js/components/preview/molecule/moleculeView.js b/js/components/preview/molecule/moleculeView.js index f95460220..c2667f31d 100644 --- a/js/components/preview/molecule/moleculeView.js +++ b/js/components/preview/molecule/moleculeView.js @@ -612,7 +612,7 @@ const MoleculeView = memo( )} onClick={() => { // always deselect all if are selected only some of options - selectedAll.current = hasSomeValuesOn ? false : !selectedAll.current; + selectedAll.current = hasSomeValuesOn || hasAllValuesOn ? false : !selectedAll.current; setCalledFromAll(); onLigand(true); diff --git a/js/components/preview/moleculeGroups/redux/dispatchActions.js b/js/components/preview/moleculeGroups/redux/dispatchActions.js index f472b7b8b..2c026fd1e 100644 --- a/js/components/preview/moleculeGroups/redux/dispatchActions.js +++ b/js/components/preview/moleculeGroups/redux/dispatchActions.js @@ -1,4 +1,7 @@ import { + complexObjectTypes, + generateComplex, + generateMolecule, generateSphere } from '../../molecule/molecules_helpers'; import { VIEWS } from '../../../../constants/constants'; @@ -8,28 +11,111 @@ import { loadObject } from '../../../../reducers/ngl/dispatchActions'; import { + removeFromComplexList, + removeFromProteinList, + removeFromSurfaceList, + removeFromFragmentDisplayList, + removeFromVectorOnList, resetSelectionState, setComplexList, setFilter, setFragmentDisplayList, setMolGroupSelection, + setObjectSelection, setVectorList, setVectorOnList } from '../../../../reducers/selection/actions'; import { setCountOfRemainingMoleculeGroups, setMoleculeOrientations } from '../../../../reducers/ngl/actions'; -import { setMolGroupList, setMolGroupOn } from '../../../../reducers/api/actions'; +import { setMolGroupList, setMolGroupOn, setMolGroupOff } from '../../../../reducers/api/actions'; import { getUrl, loadFromServer } from '../../../../utils/genericList'; import { OBJECT_TYPE } from '../../../nglView/constants'; import { setSortDialogOpen } from '../../molecule/redux/actions'; import { resetCurrentCompoundsSettings } from '../../compounds/redux/actions'; import { reloadSession } from '../../../snapshot/redux/dispatchActions'; import { resetRestoringState } from '../../../../reducers/tracking/dispatchActions'; +import { selectJoinedMoleculeList } from '../../molecule/redux/selectors'; -export const clearAfterDeselectingMoleculeGroup = () => ( - dispatch +export const clearAfterDeselectingMoleculeGroup = ({ molGroupId, currentMolGroup, majorViewStage }) => ( + dispatch, + getState ) => { + dispatch(setObjectSelection([molGroupId])); + + let site; + const state = getState(); + const { fragmentDisplayList, complexList, proteinList, surfaceList, vectorOnList, vector_list } = state.selectionReducers; + + const actionFragmentDisplayList = []; + const actionComplexList = []; + const actionProteinList = []; + const actionSurfaceList = []; + const actionVectorOnList = []; + + // loop through all molecules + selectJoinedMoleculeList(state).forEach(mol => { + site = mol.site; + + // remove Ligand + dispatch( + deleteObject( + Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMolecule(mol.protein_code, mol.sdf_info)), + majorViewStage + ) + ); + + // remove Complex, Protein, Surface + Object.keys(complexObjectTypes).forEach(type => { + dispatch( + deleteObject( + Object.assign( + { display_div: VIEWS.MAJOR_VIEW }, + generateComplex(mol.protein_code, mol.sdf_info, mol.molecule_protein, type) + ), + majorViewStage + ) + ); + }); + + if (fragmentDisplayList.find(ligand => ligand === mol.id)) actionFragmentDisplayList.push(mol); + if (complexList.find(ligand => ligand === mol.id)) actionComplexList.push(mol); + if (proteinList.find(ligand => ligand === mol.id)) actionProteinList.push(mol); + if (surfaceList.find(ligand => ligand === mol.id)) actionSurfaceList.push(mol); + if (vectorOnList.find(ligand => ligand === mol.id)) actionVectorOnList.push(mol); + }); + dispatch(setMolGroupOff(molGroupId, { + ligand: actionFragmentDisplayList, + protein: actionProteinList, + complex: actionComplexList, + surface: actionSurfaceList, + vector: actionVectorOnList + })); + + // remove all Vectors + vector_list + .filter(v => v.site === site) + .forEach(item => { + dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, item), majorViewStage)); + }); + + dispatch(setObjectSelection(undefined)); + // remove all molecule orientations dispatch(setMoleculeOrientations({})); + + // remove all selected ALCV of given site + currentMolGroup.mol_id.forEach(moleculeID => { + // remove Ligand, Complex, Vectors from selection + //Ligand + dispatch(removeFromFragmentDisplayList({ id: moleculeID }, true)); + // Complex + dispatch(removeFromComplexList({ id: moleculeID }, true)); + // Protein + dispatch(removeFromProteinList({ id: moleculeID }, true)); + // Surface + dispatch(removeFromSurfaceList({ id: moleculeID }, true)); + // Vectors + dispatch(removeFromVectorOnList({ id: moleculeID }, true)); + }); }; export const saveMoleculeGroupsToNglView = (molGroupList, stage, projectId) => dispatch => { @@ -200,7 +286,11 @@ export const onDeselectMoleculeGroup = ({ moleculeGroup, stageSummaryView, major const selectionCopy = mol_group_selection.slice(); const objIdx = mol_group_selection.indexOf(moleculeGroup.id); dispatch( - clearAfterDeselectingMoleculeGroup() + clearAfterDeselectingMoleculeGroup({ + molGroupId: moleculeGroup.id, + currentMolGroup, + majorViewStage + }) ); selectionCopy.splice(objIdx, 1); dispatch( diff --git a/js/reducers/api/actions.js b/js/reducers/api/actions.js index 925e9b56a..d384e30e4 100644 --- a/js/reducers/api/actions.js +++ b/js/reducers/api/actions.js @@ -59,6 +59,14 @@ export const setMolGroupOn = function(mol_group_id) { }; }; +export const setMolGroupOff = function(mol_group_id, selectionGroups) { + return { + type: constants.SET_MOL_GROUP_OFF, + mol_group_off: mol_group_id, + selectionGroups + }; +}; + export const setMolGroupList = function(mol_group_list) { return { type: constants.SET_MOL_GROUP_LIST, diff --git a/js/reducers/api/constants.js b/js/reducers/api/constants.js index b15a46d25..00208acbc 100644 --- a/js/reducers/api/constants.js +++ b/js/reducers/api/constants.js @@ -11,6 +11,7 @@ export const constants = { SET_PANNDA_EVENT_ON: prefix + 'SET_PANNDA_EVENT_ON', SET_MOL_GROUP_ON: prefix + 'SET_MOL_GROUP_ON', + SET_MOL_GROUP_OFF: prefix + 'SET_MOL_GROUP_OFF', SET_MOL_GROUP_LIST: prefix + 'SET_MOL_GROUP_LIST', SET_MOLECULE_LIST: prefix + 'SET_MOLECULE_LIST', SET_CACHED_MOL_LISTS: prefix + 'SET_CACHED_MOL_LISTS', diff --git a/js/reducers/selection/actions.js b/js/reducers/selection/actions.js index 9c154498c..d1b9a5479 100644 --- a/js/reducers/selection/actions.js +++ b/js/reducers/selection/actions.js @@ -39,10 +39,11 @@ export const setCurrentVector = vectorSmile => { }; }; -export const setFragmentDisplayList = function(fragmentDisplayList) { +export const setFragmentDisplayList = function(fragmentDisplayList, skipTracking = false) { return { type: constants.SET_FRAGMENT_DISPLAY_LIST, - fragmentDisplayList: fragmentDisplayList + fragmentDisplayList: fragmentDisplayList, + skipTracking }; }; @@ -62,10 +63,11 @@ export const removeFromFragmentDisplayList = function(item, skipTracking = false }; }; -export const setProteinList = function(proteinList) { +export const setProteinList = function(proteinList, skipTracking = false) { return { type: constants.SET_PROTEIN_LIST, - proteinList: proteinList + proteinList: proteinList, + skipTracking }; }; @@ -84,10 +86,11 @@ export const removeFromProteinList = function(item, skipTracking = false) { skipTracking: skipTracking }; }; -export const setComplexList = function(complexList) { +export const setComplexList = function(complexList, skipTracking = false) { return { type: constants.SET_COMPLEX_LIST, - complexList: complexList + complexList: complexList, + skipTracking }; }; @@ -107,10 +110,11 @@ export const removeFromComplexList = function(item, skipTracking = false) { }; }; -export const setSurfaceList = function(surfaceList) { +export const setSurfaceList = function(surfaceList, skipTracking = false) { return { type: constants.SET_SURFACE_LIST, - surfaceList: surfaceList + surfaceList: surfaceList, + skipTracking }; }; @@ -151,10 +155,11 @@ export const removeFromDensityList = function(item) { }; }; -export const setVectorOnList = function(vectorOnList) { +export const setVectorOnList = function(vectorOnList, skipTracking = false) { return { type: constants.SET_VECTOR_ON_LIST, - vectorOnList: vectorOnList + vectorOnList: vectorOnList, + skipTracking }; }; diff --git a/js/reducers/tracking/dispatchActions.js b/js/reducers/tracking/dispatchActions.js index 93b2b353e..fc8aee47c 100644 --- a/js/reducers/tracking/dispatchActions.js +++ b/js/reducers/tracking/dispatchActions.js @@ -1513,10 +1513,24 @@ const removeRepresentation = (parentKey, representation, nglView) => (dispatch, const handleMoleculeGroupAction = (action, isSelected, stageSummaryView, majorViewStage) => (dispatch, getState) => { const state = getState(); if (action) { - let moleculeGroup = getMolGroup(action.object_name, state); + const { selectionGroups, object_name } = action; + let moleculeGroup = getMolGroup(object_name, state); if (moleculeGroup) { if (isSelected === true) { dispatch(selectMoleculeGroup(moleculeGroup, stageSummaryView)); + + for (const type in selectionGroups) { + if (selectionGroups.hasOwnProperty(type)) { + const typeGroup = selectionGroups[type]; + for (const mol of typeGroup) { + if (type === 'ligand') { + dispatch(addType[type](majorViewStage, mol, colourList[mol.id % colourList.length], true, true)); + } else { + dispatch(addType[type](majorViewStage, mol, colourList[mol.id % colourList.length], true)); + } + } + } + } } else { dispatch(onDeselectMoleculeGroup({ moleculeGroup, stageSummaryView, majorViewStage })); } diff --git a/js/reducers/tracking/trackingActions.js b/js/reducers/tracking/trackingActions.js index 963671514..5d359a6b5 100644 --- a/js/reducers/tracking/trackingActions.js +++ b/js/reducers/tracking/trackingActions.js @@ -42,20 +42,19 @@ export const findTrackAction = (action, state) => { }; } } - } else if (action.type.includes(selectionConstants.SET_OBJECT_SELECTION)) { - let objectId = action.payload && action.payload[0]; - if (objectId) { - let molGroupName = getMolGroupName(objectId, state); - trackAction = { - type: actionType.SITE_TURNED_OFF, - timestamp: Date.now(), - username: username, - object_type: actionObjectType.SITE, - object_name: molGroupName, - object_id: objectId, - text: `${actionDescription.SITE} ${molGroupName} ${actionDescription.TURNED_OFF}` - }; - } + } else if (action.type.includes(apiConstants.SET_MOL_GROUP_OFF)) { + const { mol_group_off, selectionGroups } = action; + let molGroupName = getMolGroupName(mol_group_off, state); + trackAction = { + type: actionType.SITE_TURNED_OFF, + timestamp: Date.now(), + username: username, + object_type: actionObjectType.SITE, + object_name: molGroupName, + object_id: mol_group_off, + selectionGroups, + text: `${actionDescription.SITE} ${molGroupName} ${actionDescription.TURNED_OFF}` + }; } else if (action.type === selectionConstants.SET_HIDE_ALL) { if (action.data) { let objectType = actionObjectType.MOLECULE; diff --git a/package.json b/package.json index 1b275cbba..53677783f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.9.37", + "version": "0.9.40", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": {