diff --git a/js/components/datasets/redux/actions.js b/js/components/datasets/redux/actions.js
index 3ec64c23c..0b7a79f33 100644
--- a/js/components/datasets/redux/actions.js
+++ b/js/components/datasets/redux/actions.js
@@ -623,3 +623,35 @@ export const setUpdatedDatasets = updatedDataset => ({
type: constants.SET_UPDATED_DATASETS,
payload: { updatedDataset }
});
+
+export const setToBeDisplayedListForDataset = (datasetID, toBeDisplayedList) => {
+ return {
+ type: constants.SET_TO_BE_DISPLAYED_LIST_DATASET,
+ toBeDisplayedList: toBeDisplayedList,
+ datasetID: datasetID
+ };
+};
+
+export const appendToBeDisplayedListForDataset = (datasetID, item) => {
+ return {
+ type: constants.APPEND_TO_BE_DISPLAYED_LIST_DATASET,
+ item: item,
+ datasetID: datasetID
+ };
+};
+
+export const removeFromToBeDisplayedListForDataset = (datasetID, item) => {
+ return {
+ type: constants.REMOVE_FROM_TO_BE_DISPLAYED_LIST_DATASET,
+ item: item,
+ datasetID: datasetID
+ };
+};
+
+export const updateInToBeDisplayedListForDataset = (datasetID, item) => {
+ return {
+ type: constants.UPDATE_IN_TO_BE_DISPLAYED_LIST_DATASET,
+ item: item,
+ datasetID: datasetID
+ };
+};
diff --git a/js/components/datasets/redux/constants.js b/js/components/datasets/redux/constants.js
index 3e96418fe..b355e07be 100644
--- a/js/components/datasets/redux/constants.js
+++ b/js/components/datasets/redux/constants.js
@@ -122,7 +122,12 @@ export const constants = {
SET_SELECTED_COMPOUNDS_ITERATOR: prefix + 'SET_SELECTED_COMPOUNDS_ITERATOR',
SET_INSPIRATION_DIALOG_ACTION: prefix + 'SET_INSPIRATION_DIALOG_ACTION',
- SET_INSPIRATION_DIALOG_OPENED_FOR_SELECTED_COMPOUND: prefix + 'SET_INSPIRATION_DIALOG_OPENED_FOR_SELECTED_COMPOUND'
+ SET_INSPIRATION_DIALOG_OPENED_FOR_SELECTED_COMPOUND: prefix + 'SET_INSPIRATION_DIALOG_OPENED_FOR_SELECTED_COMPOUND',
+
+ SET_TO_BE_DISPLAYED_LIST_DATASET: prefix + 'SET_TO_BE_DISPLAYED_LIST_DATASET',
+ APPEND_TO_BE_DISPLAYED_LIST_DATASET: prefix + 'APPEND_TO_BE_DISPLAYED_LIST_DATASET',
+ REMOVE_FROM_TO_BE_DISPLAYED_LIST_DATASET: prefix + 'REMOVE_FROM_TO_BE_DISPLAYED_LIST_DATASET',
+ UPDATE_IN_TO_BE_DISPLAYED_LIST_DATASET: prefix + 'UPDATE_IN_TO_BE_DISPLAYED_LIST_DATASET'
};
export const COUNT_OF_VISIBLE_SCORES = 7;
diff --git a/js/components/datasets/redux/dispatchActions.js b/js/components/datasets/redux/dispatchActions.js
index 18f8eab34..64ea970e9 100644
--- a/js/components/datasets/redux/dispatchActions.js
+++ b/js/components/datasets/redux/dispatchActions.js
@@ -37,7 +37,9 @@ import {
removeDataset,
appendCompoundToSelectedCompoundsByDataset,
setDatasetIterator,
- setSelectedCompoundsIterator
+ setSelectedCompoundsIterator,
+ appendToBeDisplayedListForDataset,
+ updateInToBeDisplayedListForDataset
} from './actions';
import { base_url } from '../../routes/constants';
import {
@@ -78,6 +80,7 @@ import { getRepresentationsByType } from '../../nglView/generatingObjects';
import { getRandomColor } from '../../preview/molecule/utils/color';
import { isCompoundFromVectorSelector } from '../../preview/compounds/redux/dispatchActions';
import { getCompoundById } from '../../../utils/genericDispatchActions';
+import { NGL_OBJECTS } from '../../../reducers/ngl/constants';
export const initializeDatasetFilter = datasetID => (dispatch, getState) => {
const state = getState();
@@ -104,34 +107,26 @@ export const addDatasetHitProtein = (
skipTracking = false,
representations = undefined
) => async dispatch => {
- dispatch(appendProteinList(datasetID, generateMoleculeCompoundId(data), skipTracking));
- return dispatch(
- loadObject({
- target: Object.assign(
- { display_div: VIEWS.MAJOR_VIEW },
- generateHitProteinObject(data, colourToggle, base_url, datasetID)
- ),
- stage,
- previousRepresentations: representations,
- orientationMatrix: null
+ dispatch(
+ appendToBeDisplayedListForDataset(datasetID, {
+ type: NGL_OBJECTS.PROTEIN,
+ id: data.id,
+ display: true,
+ representations: representations,
+ datasetID: datasetID
})
- ).finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- });
+ );
};
export const removeDatasetHitProtein = (stage, data, colourToggle, datasetID, skipTracking = false) => dispatch => {
dispatch(
- deleteObject(
- Object.assign(
- { display_div: VIEWS.MAJOR_VIEW },
- generateHitProteinObject(data, colourToggle, base_url, datasetID)
- ),
- stage
- )
+ updateInToBeDisplayedListForDataset(datasetID, {
+ id: data.id,
+ display: false,
+ type: NGL_OBJECTS.PROTEIN,
+ datasetID: datasetID
+ })
);
- dispatch(removeFromProteinList(datasetID, generateMoleculeCompoundId(data), skipTracking));
};
export const addDatasetComplex = (
@@ -142,31 +137,26 @@ export const addDatasetComplex = (
skipTracking = false,
representations = undefined
) => async dispatch => {
- dispatch(appendComplexList(datasetID, generateMoleculeCompoundId(data), skipTracking));
- return dispatch(
- loadObject({
- target: Object.assign(
- { display_div: VIEWS.MAJOR_VIEW },
- generateComplexObject(data, colourToggle, base_url, datasetID)
- ),
- stage,
- previousRepresentations: representations,
- orientationMatrix: null
+ dispatch(
+ appendToBeDisplayedListForDataset(datasetID, {
+ type: NGL_OBJECTS.COMPLEX,
+ id: data.id,
+ display: true,
+ representations: representations,
+ datasetID: datasetID
})
- ).finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- });
+ );
};
export const removeDatasetComplex = (stage, data, colourToggle, datasetID, skipTracking = false) => dispatch => {
dispatch(
- deleteObject(
- Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateComplexObject(data, colourToggle, base_url, datasetID)),
- stage
- )
+ updateInToBeDisplayedListForDataset(datasetID, {
+ id: data.id,
+ display: false,
+ type: NGL_OBJECTS.COMPLEX,
+ datasetID: datasetID
+ })
);
- dispatch(removeFromComplexList(datasetID, generateMoleculeCompoundId(data), skipTracking));
};
export const addDatasetSurface = (
@@ -176,31 +166,48 @@ export const addDatasetSurface = (
datasetID,
representations = undefined
) => async dispatch => {
- dispatch(appendSurfaceList(datasetID, generateMoleculeCompoundId(data)));
- return dispatch(
- loadObject({
- target: Object.assign(
- { display_div: VIEWS.MAJOR_VIEW },
- generateSurfaceObject(data, colourToggle, base_url, datasetID)
- ),
- stage,
- previousRepresentations: representations,
- orientationMatrix: null
+ dispatch(
+ appendToBeDisplayedListForDataset(datasetID, {
+ type: NGL_OBJECTS.SURFACE,
+ id: data.id,
+ display: true,
+ representations: representations,
+ datasetID: datasetID
})
- ).finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- });
+ );
+ // dispatch(appendSurfaceList(datasetID, generateMoleculeCompoundId(data)));
+ // return dispatch(
+ // loadObject({
+ // target: Object.assign(
+ // { display_div: VIEWS.MAJOR_VIEW },
+ // generateSurfaceObject(data, colourToggle, base_url, datasetID)
+ // ),
+ // stage,
+ // previousRepresentations: representations,
+ // orientationMatrix: null
+ // })
+ // ).finally(() => {
+ // const currentOrientation = stage.viewerControls.getOrientation();
+ // dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ // });
};
export const removeDatasetSurface = (stage, data, colourToggle, datasetID) => dispatch => {
dispatch(
- deleteObject(
- Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateSurfaceObject(data, colourToggle, base_url, datasetID)),
- stage
- )
+ updateInToBeDisplayedListForDataset(datasetID, {
+ id: data.id,
+ display: false,
+ type: NGL_OBJECTS.SURFACE,
+ datasetID: datasetID
+ })
);
- dispatch(removeFromSurfaceList(datasetID, generateMoleculeCompoundId(data)));
+ // dispatch(
+ // deleteObject(
+ // Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateSurfaceObject(data, colourToggle, base_url, datasetID)),
+ // stage
+ // )
+ // );
+ // dispatch(removeFromSurfaceList(datasetID, generateMoleculeCompoundId(data)));
};
export const addDatasetLigand = (
@@ -211,42 +218,26 @@ export const addDatasetLigand = (
skipTracking = false,
representations = undefined
) => async (dispatch, getState) => {
- dispatch(appendLigandList(datasetID, generateMoleculeCompoundId(data), skipTracking));
- console.count(`Grabbed orientation before loading dataset ligand`);
- const currentOrientation = stage.viewerControls.getOrientation();
- return dispatch(
- loadObject({
- target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data, colourToggle, datasetID)),
- stage,
- previousRepresentations: representations,
- markAsRightSideLigand: true
+ dispatch(
+ appendToBeDisplayedListForDataset(datasetID, {
+ type: NGL_OBJECTS.LIGAND,
+ id: data.id,
+ display: true,
+ representations: representations,
+ datasetID: datasetID
})
- ).finally(() => {
- const skipOrientation = false; //state.trackingReducers.skipOrientationChange;
- if (!skipOrientation) {
- const ligandOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, ligandOrientation));
-
- dispatch(appendMoleculeOrientation(getDatasetMoleculeID(datasetID, data?.id), ligandOrientation));
-
- // keep current orientation of NGL View
- if (!skipOrientation) {
- console.count(`Before applying orientation after loading dataset ligand.`);
- stage.viewerControls.orient(currentOrientation);
- console.count(`After applying orientation after loading dataset ligand.`);
- }
- }
- });
+ );
};
export const removeDatasetLigand = (stage, data, colourToggle, datasetID, skipTracking = false) => dispatch => {
dispatch(
- deleteObject(
- Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data, undefined, datasetID)),
- stage
- )
+ updateInToBeDisplayedListForDataset(datasetID, {
+ id: data.id,
+ display: false,
+ type: NGL_OBJECTS.LIGAND,
+ datasetID: datasetID
+ })
);
- dispatch(removeFromLigandList(datasetID, generateMoleculeCompoundId(data), skipTracking));
};
export const loadDataSets = targetId => async dispatch => {
diff --git a/js/components/datasets/redux/reducer.js b/js/components/datasets/redux/reducer.js
index 43595c0ee..b14225986 100644
--- a/js/components/datasets/redux/reducer.js
+++ b/js/components/datasets/redux/reducer.js
@@ -87,7 +87,20 @@ export const INITIAL_STATE = {
inspirationsDialogOpenedForSelectedCompound: false,
- isSelectedDatasetScrolled: false
+ isSelectedDatasetScrolled: false,
+ //Map of datasetID and its objects which shape is bellow
+ // Shape of the object in toBeDisplayedList:
+ // {
+ // type: 'L|P|C|S|V|RIBBON|etc...',
+ // id: 1,
+
+ // center: true,
+ // withQuality: true,
+ // representations: [] etc...
+
+ // display: true
+ // }
+ toBeDisplayedList: {}
};
/**
@@ -191,6 +204,45 @@ const removeDatasetFromState = (state, datasetId) => {
export const datasetsReducers = (state = INITIAL_STATE, action = {}) => {
switch (action.type) {
+ case constants.SET_TO_BE_DISPLAYED_LIST_DATASET: {
+ return setList(state, 'toBeDisplayedList', action.datasetID, action.list);
+ }
+ case constants.APPEND_TO_BE_DISPLAYED_LIST_DATASET: {
+ return {
+ ...state,
+ toBeDisplayedList: {
+ ...state.toBeDisplayedList,
+ [action.datasetID]: [...(state.toBeDisplayedList[action.datasetID] || []), action.item]
+ }
+ };
+ }
+ case constants.REMOVE_FROM_TO_BE_DISPLAYED_LIST_DATASET: {
+ return {
+ ...state,
+ toBeDisplayedList: {
+ ...state.toBeDisplayedList,
+ [action.datasetID]: state.toBeDisplayedList[action.datasetID].filter(
+ i => i.id !== action.item.id || i.type !== action.item.type
+ )
+ }
+ };
+ }
+ case constants.UPDATE_IN_TO_BE_DISPLAYED_LIST_DATASET: {
+ return {
+ ...state,
+ toBeDisplayedList: {
+ ...state.toBeDisplayedList,
+ [action.datasetID]: state.toBeDisplayedList[action.datasetID].map(item => {
+ if (item.id === action.item.id && item.type === action.item.type) {
+ return { ...item, ...action.item };
+ } else {
+ return item;
+ }
+ })
+ }
+ };
+ }
+
case constants.ADD_DATASET:
const increasedDatasets = state.datasets.slice();
increasedDatasets.push(action.payload);
diff --git a/js/components/preview/Preview.js b/js/components/preview/Preview.js
index 653d9063d..8160e1683 100644
--- a/js/components/preview/Preview.js
+++ b/js/components/preview/Preview.js
@@ -47,6 +47,16 @@ import { setTagEditorOpen, setMoleculeForTagEdit, setToastMessages } from '../..
import { LoadingContext } from '../loading';
import { ToastContext } from '../toast';
import { TOAST_LEVELS } from '../toast/constants';
+import { useDisplayLigandLHS } from '../../reducers/ngl/useDisplayLigandLHS';
+import { useDisplayProteinLHS } from '../../reducers/ngl/useDisplayProteinLHS';
+import { useDisplayComplexLHS } from '../../reducers/ngl/useDisplayComplexLHS';
+import { useDisplaySurfaceLHS } from '../../reducers/ngl/useDisplaySurfacesLHS';
+import { useDisplayVectorLHS } from '../../reducers/ngl/useDisplayVectorLHS';
+import { useDisplayDensityLHS } from '../../reducers/ngl/useDisplayDensityLHS';
+import { useDisplayLigandRHS } from '../../reducers/ngl/useDisplayLigandRHS';
+import { useDisplayProteinRHS } from '../../reducers/ngl/useDisplayProteinRHS';
+import { useDisplayComplexRHS } from '../../reducers/ngl/useDisplayComplexRHS';
+import { useDisplaySurfaceRHS } from '../../reducers/ngl/useDisplaySurfaceRHS';
const ReactGridLayout = WidthProvider(ResponsiveGridLayout);
@@ -128,6 +138,18 @@ const Preview = memo(({ isStateLoaded, hideProjects, isSnapshot = false }) => {
const { setMoleculesAndTagsAreLoading } = useContext(LoadingContext);
+ useDisplayLigandLHS();
+ useDisplayProteinLHS();
+ useDisplayComplexLHS();
+ useDisplaySurfaceLHS();
+ useDisplayVectorLHS();
+ useDisplayDensityLHS();
+
+ useDisplayLigandRHS();
+ useDisplayProteinRHS();
+ useDisplayComplexRHS();
+ useDisplaySurfaceRHS();
+
useEffect(() => {
if (target_on && !isSnapshot) {
dispatch(loadMoleculesAndTagsNew(target_on));
diff --git a/js/components/preview/molecule/modals/densityMapsModal.js b/js/components/preview/molecule/modals/densityMapsModal.js
index 84e52979f..00a505758 100644
--- a/js/components/preview/molecule/modals/densityMapsModal.js
+++ b/js/components/preview/molecule/modals/densityMapsModal.js
@@ -60,11 +60,11 @@ export const DensityMapsModal = memo(({ openDialog, setOpenDialog, data, setDens
};
const handleCloseModal = () => {
- dispatch(setOpenDialog(false));
+ setOpenDialog(false);
};
const handleSaveButton = () => {
- dispatch(setOpenDialog(false));
+ setOpenDialog(false);
setDensity();
};
diff --git a/js/components/preview/molecule/moleculeView/moleculeView.js b/js/components/preview/molecule/moleculeView/moleculeView.js
index cf0c74fa8..78d6252b1 100644
--- a/js/components/preview/molecule/moleculeView/moleculeView.js
+++ b/js/components/preview/molecule/moleculeView/moleculeView.js
@@ -49,7 +49,14 @@ import { SvgTooltip } from '../../../common';
import { MOL_TYPE } from '../redux/constants';
import { DensityMapsModal } from '../modals/densityMapsModal';
import { getRandomColor } from '../utils/color';
-import { DEFAULT_TAG_COLOR, getAllTagsForCategories, getAllTagsForLHSCmp, getAllTagsForMol, getAllTagsForObservation, getAllTagsForObservationPopover } from '../../tags/utils/tagUtils';
+import {
+ DEFAULT_TAG_COLOR,
+ getAllTagsForCategories,
+ getAllTagsForLHSCmp,
+ getAllTagsForMol,
+ getAllTagsForObservation,
+ getAllTagsForObservationPopover
+} from '../../tags/utils/tagUtils';
import MoleculeSelectCheckbox from './moleculeSelectCheckbox';
import useClipboard from 'react-use-clipboard';
import Typography from '@mui/material/Typography';
@@ -503,17 +510,24 @@ const MoleculeView = memo(
return getFontColorByBackgroundColor(bgColor);
};
- const getAllTags = useCallback(() => getAllTagsForCategories(data, tagList, tagCategories), [data, tagList, tagCategories]);
+ const getAllTags = useCallback(() => getAllTagsForCategories(data, tagList, tagCategories), [
+ data,
+ tagList,
+ tagCategories
+ ]);
/**
* Get tag for render
*/
- const getTagType = useCallback((type) => {
- const defaultTagObject = { tag_prefix: '-', color: 'orange' };
- const tagCategory = tagCategories.find(tag => tag.category === type);
- const tagObject = tagCategory ? getAllTags().find(tag => tag.category === tagCategory.id) : defaultTagObject;
- return tagObject ?? defaultTagObject;
- }, [getAllTags, tagCategories]);
+ const getTagType = useCallback(
+ type => {
+ const defaultTagObject = { tag_prefix: '-', color: 'orange' };
+ const tagCategory = tagCategories.find(tag => tag.category === type);
+ const tagObject = tagCategory ? getAllTags().find(tag => tag.category === tagCategory.id) : defaultTagObject;
+ return tagObject ?? defaultTagObject;
+ },
+ [getAllTags, tagCategories]
+ );
const generateTagPopover = () => {
// const allData = getAllTagsForObservation(data, tagList, tagCategories);
@@ -1050,10 +1064,10 @@ const MoleculeView = memo(
switch (string?.length) {
case 1:
case 2:
- fontSize = 18
+ fontSize = 18;
break;
case 4:
- fontSize = 10
+ fontSize = 10;
break;
default:
break;
@@ -1067,12 +1081,9 @@ const MoleculeView = memo(
container
justifyContent="space-between"
direction="row"
- className={classNames(
- classes.container,
- {
- [classes.containerHeight]: !hideImage
- }
- )}
+ className={classNames(classes.container, {
+ [classes.containerHeight]: !hideImage
+ })}
wrap="nowrap"
ref={ref}
>
@@ -1104,22 +1115,33 @@ const MoleculeView = memo(
{/* Title label */}
-
+
{
e.preventDefault();
setNameCopied(moleculeTitle);
}}
- className={classNames(classes.moleculeTitleLabel, { [classes.moleculeTitleLabelMainObs]: data.id === pose?.main_site_observation })}
+ className={classNames(classes.moleculeTitleLabel, {
+ [classes.moleculeTitleLabelMainObs]: data.id === pose?.main_site_observation
+ })}
>
- {moleculeTitleTruncated}
+
+ {moleculeTitleTruncated}
+
{data?.compound_code}
{/* Molecule properties */}
- {getCalculatedProps().length > 0 &&
+ {getCalculatedProps().length > 0 && (
{/* Molecule properties */}
- }
+ )}
{/* Control Buttons A, L, C, V */}
@@ -1357,33 +1379,45 @@ const MoleculeView = memo(
justifyContent="center"
alignItems="center"
// wrap="nowrap"
- style={{ height: "100%" }}
+ style={{ height: '100%' }}
>
- {['CanonSites', 'ConformerSites', 'CrystalformSites', 'Crystalforms', 'Quatassemblies'].map(tagCategory => {
- const tagTypeObject = getTagType(tagCategory);
- const tagLabel = tagCategory === 'ConformerSites' ? tagTypeObject.tag_prefix.replace(getTagType('CanonSites')?.tag_prefix, '') : tagTypeObject?.tag_prefix;
- return {PLURAL_TO_SINGULAR[tagCategory]} - {tagTypeObject.upload_name}}
- >
-
- {tagLabel}
-
-
- }
+ {['CanonSites', 'ConformerSites', 'CrystalformSites', 'Crystalforms', 'Quatassemblies'].map(
+ tagCategory => {
+ const tagTypeObject = getTagType(tagCategory);
+ const tagLabel =
+ tagCategory === 'ConformerSites'
+ ? tagTypeObject.tag_prefix.replace(getTagType('CanonSites')?.tag_prefix, '')
+ : tagTypeObject?.tag_prefix;
+ return (
+
+ {PLURAL_TO_SINGULAR[tagCategory]} - {tagTypeObject.upload_name}
+
+ }
+ >
+
+ {tagLabel}
+
+
+ );
+ }
)}
{/* Image */}
- {(hideImage !== true) &&
+ {hideImage !== true && (
)}
- }
+
+ )}
- {showExpandedView &&
- {['CanonSites', 'ConformerSites', 'CrystalformSites', 'Crystalforms', 'Quatassemblies'].map((tagCategory, index) => {
- const tagTypeObject = getTagType(tagCategory);
- let tagLabel = '';
- if (tagTypeObject) {
- if (tagCategory === 'CrystalformSites') {
- // "chop" more of CrystalformSites name
- tagLabel = tagTypeObject.upload_name.substring(tagTypeObject.upload_name.indexOf('-') + 1);
- tagLabel = tagLabel.substring(tagLabel.indexOf('-') + 1);
- } else {
- tagLabel = tagTypeObject.upload_name.substring(tagTypeObject.upload_name.indexOf('-') + 1);
+ {showExpandedView && (
+
+ {['CanonSites', 'ConformerSites', 'CrystalformSites', 'Crystalforms', 'Quatassemblies'].map(
+ (tagCategory, index) => {
+ const tagTypeObject = getTagType(tagCategory);
+ let tagLabel = '';
+ if (tagTypeObject) {
+ if (tagCategory === 'CrystalformSites') {
+ // "chop" more of CrystalformSites name
+ tagLabel = tagTypeObject.upload_name.substring(tagTypeObject.upload_name.indexOf('-') + 1);
+ tagLabel = tagLabel.substring(tagLabel.indexOf('-') + 1);
+ } else {
+ tagLabel = tagTypeObject.upload_name.substring(tagTypeObject.upload_name.indexOf('-') + 1);
+ }
+ }
+ return (
+
+
+ {tagLabel}
+
+
+ );
}
- }
- return
-
- {tagLabel}
-
-
- })}
- }
-
+ )}
+
+ )}
+
{
if (r) {
- dispatch(setDensityModalOpen(true));
+ setDensityModalOpen(true);
} else {
addNewDensity();
}
diff --git a/js/components/preview/molecule/redux/dispatchActions.js b/js/components/preview/molecule/redux/dispatchActions.js
index eab06336c..dacdba66c 100644
--- a/js/components/preview/molecule/redux/dispatchActions.js
+++ b/js/components/preview/molecule/redux/dispatchActions.js
@@ -34,7 +34,9 @@ import {
setTagEditorOpen,
setMoleculeForTagEdit,
setSelectVisiblePoses,
- setUnselectVisiblePoses
+ setUnselectVisiblePoses,
+ appendToBeDisplayedList,
+ updateInToBeDisplayedList
} from '../../../../reducers/selection/actions';
import { base_url } from '../../../routes/constants';
import {
@@ -79,6 +81,7 @@ import { CATEGORY_TYPE } from '../../../../constants/constants';
import { selectJoinedMoleculeList } from './selectors';
import { compareTagsAsc } from '../../tags/utils/tagUtils';
import { createPoseApi, updatePoseApi } from '../api/poseApi';
+import { NGL_OBJECTS } from '../../../../reducers/ngl/constants';
// import { molFile, pdbApo } from './testData';
/**
@@ -147,12 +150,12 @@ export const autoHideTagEditorDialogsOnScroll = ({ tagEditorRef, scrollBarRef })
}
};
-const getViewUrl = (get_view, data) => {
+export const getViewUrl = (get_view, data) => {
const url = new URL(base_url + '/api/' + get_view + '/' + data.id + '/');
return url;
};
-const handleVector = (json, stage, data) => (dispatch, getState) => {
+export const handleVector = (json, stage, data) => (dispatch, getState) => {
const state = getState();
const { vector_list, compoundsOfVectors } = state.selectionReducers;
@@ -179,41 +182,13 @@ const handleVector = (json, stage, data) => (dispatch, getState) => {
};
export const addVector = (stage, data, skipTracking = false) => async (dispatch, getState) => {
- const currentVector = getState().selectionReducers.currentVector;
-
- dispatch(appendVectorOnList(generateMoleculeId(data), skipTracking));
- dispatch(selectVectorAndResetCompounds(currentVector));
-
- return api({ url: getViewUrl('graph', data) })
- .then(response => {
- const result = response.data.graph;
- const new_dict = {};
- // Uniquify
- if (result) {
- Object.keys(result).forEach(key => {
- const smiSet = new Set();
- new_dict[key] = {};
- new_dict[key]['addition'] = [];
- new_dict[key]['vector'] = result[key]['vector'];
- Object.keys(result[key]['addition']).forEach(index => {
- const 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: new URL(base_url + '/api/vector/?id=' + data.id) }))
- .then(response => {
- dispatch(handleVector(response.data?.results[0]?.vectors, stage, data));
+ dispatch(
+ appendToBeDisplayedList({
+ type: NGL_OBJECTS.VECTOR,
+ id: data.id,
+ display: true
})
- .finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- });
+ );
};
export const removeCurrentVector = currentMoleculeSmile => (dispatch, getState) => {
@@ -226,19 +201,7 @@ export const removeCurrentVector = currentMoleculeSmile => (dispatch, getState)
};
export const removeVector = (stage, data, skipTracking = false) => (dispatch, getState) => {
- const state = getState();
- const vector_list = state.selectionReducers.vector_list;
- vector_list
- .filter(item => item.moleculeId === data.id)
- .forEach(item => dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, item), stage)));
-
- dispatch(removeCurrentVector(data.smiles));
-
- dispatch(updateVectorCompounds(data.smiles, undefined));
- dispatch(updateBondColorMapOfCompounds(data.smiles, undefined));
- dispatch(removeFromVectorOnList(generateMoleculeId(data), skipTracking));
-
- dispatch(setVectorList(vector_list.filter(item => item.moleculeId !== data.id)));
+ dispatch(updateInToBeDisplayedList({ id: data.id, display: false, type: NGL_OBJECTS.VECTOR }));
};
export const addComplex = (
@@ -249,29 +212,19 @@ export const addComplex = (
representations = undefined,
preserveColour = false
) => async dispatch => {
- dispatch(appendComplexList(generateMoleculeId(data), skipTracking));
- return dispatch(
- loadObject({
- target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateComplexObject(data, colourToggle, base_url)),
- stage,
- previousRepresentations: representations,
- orientationMatrix: null,
- preserveColour
+ dispatch(
+ appendToBeDisplayedList({
+ type: NGL_OBJECTS.COMPLEX,
+ id: data.id,
+ display: true,
+ representations: representations,
+ preserveColour: preserveColour
})
- ).finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- });
+ );
};
export const removeComplex = (stage, data, colourToggle, skipTracking = false) => dispatch => {
- dispatch(
- deleteObject(
- Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateComplexObject(data, colourToggle, base_url)),
- stage
- )
- );
- dispatch(removeFromComplexList(generateMoleculeId(data), skipTracking));
+ dispatch(updateInToBeDisplayedList({ id: data.id, display: false, type: NGL_OBJECTS.COMPLEX }));
};
export const addSurface = (
@@ -282,29 +235,19 @@ export const addSurface = (
representations = undefined,
preserveColour = false
) => async dispatch => {
- dispatch(appendSurfaceList(generateMoleculeId(data), skipTracking));
- return dispatch(
- loadObject({
- target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateSurfaceObject(data, colourToggle, base_url)),
- stage,
- previousRepresentations: representations,
- orientationMatrix: null,
- preserveColour
+ dispatch(
+ appendToBeDisplayedList({
+ type: NGL_OBJECTS.SURFACE,
+ id: data.id,
+ display: true,
+ representations: representations,
+ preserveColour: preserveColour
})
- ).finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- });
+ );
};
export const removeSurface = (stage, data, colourToggle, skipTracking = false) => dispatch => {
- dispatch(
- deleteObject(
- Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateSurfaceObject(data, colourToggle, base_url)),
- stage
- )
- );
- dispatch(removeFromSurfaceList(generateMoleculeId(data), skipTracking));
+ dispatch(updateInToBeDisplayedList({ id: data.id, display: false, type: NGL_OBJECTS.SURFACE }));
};
export const getDensityMapData = data => dispatch => {
@@ -347,52 +290,18 @@ const setDensity = (
skipTracking = false,
representations = undefined
) => async (dispatch, getState) => {
- const prepParams = dispatch(getDensityChangedParams(isWireframeStyle));
- const densityObject = generateDensityObject(data, colourToggle, base_url, isWireframeStyle);
- const combinedObject = { ...prepParams, ...densityObject };
dispatch(
- loadObject({
- target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, combinedObject),
- stage,
- previousRepresentations: representations,
- orientationMatrix: null
+ appendToBeDisplayedList({
+ type: NGL_OBJECTS.DENSITY,
+ id: data.id,
+ display: true,
+ representations: representations,
+ isWireframeStyle: isWireframeStyle
})
- ).finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- let molDataId = generateMoleculeId(data);
- if (!data.proteinData) {
- dispatch(getProteinData(data)).then(i => {
- const proteinData = i;
- data.proteinData = proteinData;
-
- molDataId['render_event'] = data.proteinData.render_event;
- molDataId['render_sigmaa'] = data.proteinData.render_sigmaa;
- molDataId['render_diff'] = data.proteinData.render_diff;
- molDataId['render_quality'] = data.proteinData.render_quality;
-
- dispatch(appendDensityList(generateMoleculeId(data), skipTracking));
- dispatch(appendToDensityListType(molDataId, skipTracking));
- if (data.proteinData.render_quality) {
- return dispatch(addQuality(stage, data, colourToggle, true));
- }
- });
- } else {
- molDataId['render_event'] = data.proteinData.render_event;
- molDataId['render_sigmaa'] = data.proteinData.render_sigmaa;
- molDataId['render_diff'] = data.proteinData.render_diff;
- molDataId['render_quality'] = data.proteinData.render_quality;
-
- dispatch(appendDensityList(generateMoleculeId(data), skipTracking));
- dispatch(appendToDensityListType(molDataId, skipTracking));
- if (data.proteinData.render_quality) {
- return dispatch(addQuality(stage, data, colourToggle, true));
- }
- }
- });
+ );
};
-const getDensityChangedParams = (isWireframeStyle = undefined) => (dispatch, getState) => {
+export const getDensityChangedParams = (isWireframeStyle = undefined) => (dispatch, getState) => {
const state = getState();
const viewParams = state.nglReducers.viewParams;
@@ -428,21 +337,12 @@ export const addDensityCustomView = (
) => async (dispatch, getState) => {
const state = getState();
const viewParams = state.nglReducers.viewParams;
- // const contour_DENSITY = viewParams[NGL_PARAMS.contour_DENSITY];
- // const contour_DENSITY_MAP_sigmaa = viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa];
- // const contour_DENSITY_MAP_diff = viewParams[NGL_PARAMS.contour_DENSITY_MAP_diff];
if (data.proteinData) {
return dispatch(setDensityCustom(stage, data, colourToggle, isWireframeStyle, skipTracking, representations));
- // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY, invertedWireframe));
- // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_sigmaa, invertedWireframe));
- // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_diff, invertedWireframe));
} else {
await dispatch(getDensityMapData(data));
return dispatch(setDensityCustom(stage, data, colourToggle, isWireframeStyle, skipTracking, representations));
}
- // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY, invertedWireframe));
- // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_sigmaa, invertedWireframe));
- // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_diff, invertedWireframe));
};
export const toggleDensityWireframe = (currentWireframeSetting, densityData) => dispatch => {
@@ -470,26 +370,15 @@ const setDensityCustom = (
skipTracking = false,
representations = undefined
) => async (dispatch, getState) => {
- let densityObject = dispatch(getDensityChangedParams());
- densityObject = dispatch(toggleDensityWireframe(isWireframeStyle, densityObject));
- const oldDensityData = dispatch(deleteDensityObject(data, colourToggle, stage, !isWireframeStyle));
- densityObject = { ...densityObject, ...oldDensityData };
- const molId = generateMoleculeId(data);
- dispatch(removeFromDensityList(molId, true));
- // dispatch(removeFromDensityListType(molId, true));
-
- dispatch(appendDensityListCustom(generateMoleculeId(data), skipTracking));
- return dispatch(
- loadObject({
- target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, densityObject),
- stage,
- previousRepresentations: representations,
- orientationMatrix: null
+ dispatch(
+ appendToBeDisplayedList({
+ type: NGL_OBJECTS.DENSITY_CUSTOM,
+ id: data.id,
+ display: true,
+ representations: representations,
+ isWireframeStyle: isWireframeStyle
})
- ).finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- });
+ );
};
export const removeDensity = (
@@ -500,19 +389,17 @@ export const removeDensity = (
skipTracking = false,
representations = undefined
) => dispatch => {
- dispatch(toggleDensityWireframe(isWireframeStyle));
- dispatch(deleteDensityObject(data, colourToggle, stage, isWireframeStyle));
-
- const molId = generateMoleculeId(data);
- dispatch(removeFromDensityList(molId, skipTracking));
- dispatch(removeFromDensityListCustom(molId, true));
- dispatch(removeFromDensityListType(molId, skipTracking));
- if (data.proteinData.render_quality) {
- dispatch(removeQuality(stage, data, colourToggle, true));
- }
+ dispatch(
+ updateInToBeDisplayedList({
+ id: data.id,
+ display: false,
+ isWireframeStyle: isWireframeStyle,
+ type: NGL_OBJECTS.DENSITY_CUSTOM
+ })
+ );
};
-const deleteDensityObject = (data, colourToggle, stage, isWireframeStyle) => dispatch => {
+export const deleteDensityObject = (data, colourToggle, stage, isWireframeStyle) => dispatch => {
const densityObject = generateDensityObject(data, colourToggle, base_url, isWireframeStyle);
dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, densityObject), stage));
@@ -534,44 +421,20 @@ export const addHitProtein = (
representations = undefined,
preserveColour = false
) => async dispatch => {
- // data.sdf_info = molFile;
- dispatch(appendProteinList(generateMoleculeId(data), skipTracking));
- let hitProteinObject = generateHitProteinObject(data, colourToggle, base_url);
- let qualityInformation = dispatch(readQualityInformation(hitProteinObject.name, hitProteinObject.sdf_info));
-
- let hasAdditionalInformation =
- withQuality === true &&
- qualityInformation &&
- qualityInformation.badproteinids &&
- qualityInformation.badproteinids.length !== 0;
- if (hasAdditionalInformation) {
- dispatch(appendQualityList(generateMoleculeId(data), true));
- }
-
- return dispatch(
- loadObject({
- target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, hitProteinObject),
- stage,
- previousRepresentations: representations,
- orientationMatrix: null,
- loadQuality: hasAdditionalInformation,
- quality: qualityInformation,
- preserveColour
+ dispatch(
+ appendToBeDisplayedList({
+ type: NGL_OBJECTS.PROTEIN,
+ id: data.id,
+ display: true,
+ withQuality: withQuality,
+ representations: representations,
+ preserveColour: preserveColour
})
- ).finally(() => {
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
- });
+ );
};
export const removeHitProtein = (stage, data, colourToggle, skipTracking = false) => dispatch => {
- dispatch(
- deleteObject(
- Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateHitProteinObject(data, colourToggle, base_url)),
- stage
- )
- );
- dispatch(removeFromProteinList(generateMoleculeId(data), skipTracking));
+ dispatch(updateInToBeDisplayedList({ id: data.id, display: false, type: NGL_OBJECTS.PROTEIN }));
};
export const addLigand = (
@@ -583,68 +446,41 @@ export const addLigand = (
skipTracking = false,
representations = undefined
) => async (dispatch, getState) => {
- // data.sdf_info = molFile;
- console.count(`Grabbing orientation before loading ligand.`);
- const currentOrientation = stage.viewerControls.getOrientation();
- dispatch(appendFragmentDisplayList(generateMoleculeId(data), skipTracking));
-
- let moleculeObject = generateMoleculeObject(data, colourToggle);
- let qualityInformation = dispatch(readQualityInformation(moleculeObject.name, moleculeObject.sdf_info));
-
- let hasAdditionalInformation =
- withQuality === true && qualityInformation && qualityInformation.badids && qualityInformation.badids.length !== 0;
- if (hasAdditionalInformation) {
- dispatch(appendQualityList(generateMoleculeId(data), true));
- }
-
- return dispatch(
- loadObject({
- target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, moleculeObject),
- stage,
- previousRepresentations: representations,
- loadQuality: hasAdditionalInformation,
- quality: qualityInformation
+ dispatch(
+ appendToBeDisplayedList({
+ type: NGL_OBJECTS.LIGAND,
+ id: data.id,
+ display: true,
+ center: centerOn,
+ withQuality: withQuality,
+ representations: representations
})
- ).then(() => {
- const state = getState();
- const skipOrientation = false; //state.trackingReducers.skipOrientationChange;
- if (!skipOrientation) {
- const ligandOrientation = stage.viewerControls.getOrientation();
- dispatch(setOrientation(VIEWS.MAJOR_VIEW, ligandOrientation));
-
- dispatch(appendMoleculeOrientation(data?.id, ligandOrientation));
- if (centerOn === false) {
- // keep current orientation of NGL View
- console.count(`Before applying orientation matrix after loading ligand.`);
- stage.viewerControls.orient(currentOrientation);
- console.count(`After applying orientation matrix after loading ligand.`);
- }
- }
- });
+ );
};
export const removeLigand = (stage, data, skipTracking = false, withVector = true) => dispatch => {
- dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage));
- dispatch(removeFromFragmentDisplayList(generateMoleculeId(data), skipTracking));
- dispatch(removeFromQualityList(generateMoleculeId(data), true));
-
- if (withVector === true) {
- // remove vector
- dispatch(removeVector(stage, data, skipTracking));
- }
+ dispatch(
+ updateInToBeDisplayedList({ id: data.id, display: false, withVector: withVector, type: NGL_OBJECTS.LIGAND })
+ );
};
export const addQuality = (stage, data, colourToggle, skipTracking = false, representations = undefined) => (
dispatch,
getState
) => {
- dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage));
+ dispatch(removeFromFragmentDisplayList(generateMoleculeId(data)));
+ dispatch(removeFromQualityList(generateMoleculeId(data)));
+ dispatch(updateInToBeDisplayedList({ id: data.id, display: false, type: NGL_OBJECTS.LIGAND }));
+ // dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage));
dispatch(appendQualityList(generateMoleculeId(data), skipTracking));
return dispatch(addLigand(stage, data, colourToggle, false, true, true, representations));
};
export const removeQuality = (stage, data, colourToggle, skipTracking = false) => dispatch => {
- dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage));
+ dispatch(removeFromFragmentDisplayList(generateMoleculeId(data)));
+ dispatch(removeFromQualityList(generateMoleculeId(data)));
+ dispatch(updateInToBeDisplayedList({ id: data.id, display: false, type: NGL_OBJECTS.LIGAND }));
+ // dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage));
dispatch(addLigand(stage, data, colourToggle, false, false, true));
dispatch(removeFromQualityList(generateMoleculeId(data), skipTracking));
};
diff --git a/js/reducers/ngl/actions.js b/js/reducers/ngl/actions.js
index 7c58ae185..5931ff6b3 100644
--- a/js/reducers/ngl/actions.js
+++ b/js/reducers/ngl/actions.js
@@ -265,3 +265,8 @@ export const addToQualityCache = (name, cacheItem) => ({
type: CONSTANTS.ADD_TO_QUALITY_CACHE,
payload: { name: name, cacheItem: cacheItem }
});
+
+export const setSkipOrientationChange = skip => ({
+ type: CONSTANTS.SET_SKIP_ORIENTATION_CHANGE,
+ skip: skip
+});
diff --git a/js/reducers/ngl/constants.js b/js/reducers/ngl/constants.js
index 5fdde957a..a54932761 100644
--- a/js/reducers/ngl/constants.js
+++ b/js/reducers/ngl/constants.js
@@ -58,10 +58,23 @@ export const CONSTANTS = {
SET_WARNING_ICON: prefix + 'SET_WARNING_ICON',
SET_ELECTRON_COLOR_DENSITY: prefix + 'SET_ELECTRON_COLOR' + MAP_TYPE.event,
SET_ELECTRON_COLOR_DENSITY_MAP_sigmaa: prefix + 'SET_ELECTRON_COLOR' + MAP_TYPE.sigmaa,
- SET_ELECTRON_COLOR_DENSITY_MAP_diff: prefix + 'SET_ELECTRONCOLOR' + MAP_TYPE.diff
+ SET_ELECTRON_COLOR_DENSITY_MAP_diff: prefix + 'SET_ELECTRONCOLOR' + MAP_TYPE.diff,
+
+ SET_SKIP_ORIENTATION_CHANGE: prefix + 'SET_SKIP_ORIENTATION_CHANGE'
};
export const SCENES = {
defaultScene: 'defaultScene',
sessionScene: 'sessionScene'
};
+
+export const NGL_OBJECTS = {
+ PROTEIN: 'PROTEIN',
+ LIGAND: 'LIGAND',
+ SURFACE: 'SURFACE',
+ DENSITY: 'DENSITY',
+ DENSITY_CUSTOM: 'DENSITY_CUSTOM',
+ VECTOR: 'VECTOR',
+ COMPLEX: 'COMPLEX',
+ QUALITY: 'QUALITY'
+};
diff --git a/js/reducers/ngl/nglReducers.js b/js/reducers/ngl/nglReducers.js
index 1cf6a2d46..96163294f 100644
--- a/js/reducers/ngl/nglReducers.js
+++ b/js/reducers/ngl/nglReducers.js
@@ -45,13 +45,17 @@ export const INITIAL_STATE = {
qualityCache: {},
electronDensityColor_event: 'blue',
electronDensityColor_sigmaa: 'blue',
- electronDensityColor_diff: 'blue'
+ electronDensityColor_diff: 'blue',
+ skipOrientationChange: false
};
export default function nglReducers(state = INITIAL_STATE, action = {}) {
switch (action.type) {
// Defined in initialState - but may be needed if we want to load a different structure
+ case CONSTANTS.SET_SKIP_ORIENTATION_CHANGE:
+ return { ...state, skipOrientationChange: action.skip };
+
case CONSTANTS.LOAD_OBJECT:
// at first check if object was already stashed
const objectsInViewStashTemp = JSON.parse(JSON.stringify(state.objectsInViewStash));
@@ -117,7 +121,10 @@ export default function nglReducers(state = INITIAL_STATE, action = {}) {
// stash state of the object
let newObjectsInViewStash = JSON.parse(JSON.stringify(state.objectsInViewStash));
if (objectsInViewTemp.hasOwnProperty(action.target.name)) {
- newObjectsInViewStash[action.target.name] = { ...objectsInViewTemp[action.target.name], representations: objectsInViewTemp[action.target.name].representations };
+ newObjectsInViewStash[action.target.name] = {
+ ...objectsInViewTemp[action.target.name],
+ representations: objectsInViewTemp[action.target.name].representations
+ };
}
delete objectsInViewTemp[action.target.name];
diff --git a/js/reducers/ngl/useDisplayComplexLHS.js b/js/reducers/ngl/useDisplayComplexLHS.js
new file mode 100644
index 000000000..ae3962bf3
--- /dev/null
+++ b/js/reducers/ngl/useDisplayComplexLHS.js
@@ -0,0 +1,85 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NGL_OBJECTS } from './constants';
+import { appendComplexList, removeFromComplexList, removeFromToBeDisplayedList } from '../selection/actions';
+import { generateComplexObject, generateMoleculeId } from '../../components/nglView/generatingObjects';
+import { VIEWS } from '../../constants/constants';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import { deleteObject, loadObject, setOrientation } from './dispatchActions';
+import { base_url } from '../../components/routes/constants';
+import { getToBeDisplayedStructures } from './utils';
+
+export const useDisplayComplexLHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.selectionReducers.toBeDisplayedList);
+ const displayedComplexes = useSelector(state => state.selectionReducers.complexList);
+ const allObservations = useSelector(state => state.apiReducers.all_mol_lists);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displayComplex = useCallback(
+ complexData => {
+ const data = allObservations.find(obs => obs.id === complexData.id);
+ const colourToggle = getRandomColor(data);
+
+ dispatch(appendComplexList(generateMoleculeId(data)));
+ return dispatch(
+ loadObject({
+ target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateComplexObject(data, colourToggle, base_url)),
+ stage,
+ previousRepresentations: complexData.representations,
+ orientationMatrix: null,
+ preserveColour: complexData.preserveColour
+ })
+ ).finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ });
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ const removeComplex = useCallback(
+ complexData => {
+ const data = allObservations.find(obs => obs.id === complexData.id);
+ const colourToggle = getRandomColor(data);
+
+ dispatch(
+ deleteObject(
+ Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateComplexObject(data, colourToggle, base_url)),
+ stage
+ )
+ );
+ dispatch(removeFromComplexList(generateMoleculeId(data)));
+
+ dispatch(removeFromToBeDisplayedList({ id: complexData.id, type: NGL_OBJECTS.COMPLEX }));
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeDisplayedComplexes = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedComplexes,
+ NGL_OBJECTS.COMPLEX
+ );
+ toBeDisplayedComplexes?.forEach(data => {
+ displayComplex(data);
+ });
+
+ const toBeRemovedComplexes = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedComplexes,
+ NGL_OBJECTS.COMPLEX,
+ true
+ );
+ toBeRemovedComplexes?.forEach(data => {
+ removeComplex(data);
+ });
+ }, [toBeDisplayedList, displayComplex, dispatch, stage, removeComplex, displayedComplexes]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplayComplexRHS.js b/js/reducers/ngl/useDisplayComplexRHS.js
new file mode 100644
index 000000000..36206351d
--- /dev/null
+++ b/js/reducers/ngl/useDisplayComplexRHS.js
@@ -0,0 +1,97 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { VIEWS } from '../../constants/constants';
+import { NGL_OBJECTS } from './constants';
+import { getToBeDisplayedStructuresDataset } from './utils';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import {
+ appendComplexList,
+ removeFromComplexList,
+ removeFromToBeDisplayedListForDataset
+} from '../../components/datasets/redux/actions';
+import { generateComplexObject, generateMoleculeCompoundId } from '../../components/nglView/generatingObjects';
+import { deleteObject, loadObject, setOrientation } from './dispatchActions';
+import { base_url } from '../../components/routes/constants';
+
+export const useDisplayComplexRHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.datasetsReducers.toBeDisplayedList);
+ const displayedComplexes = useSelector(state => state.datasetsReducers.complexLists);
+ const allCompounds = useSelector(state => state.datasetsReducers.moleculeLists);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displayComplex = useCallback(
+ complexData => {
+ const datasetCompounds = allCompounds[complexData.datasetID];
+ const data = datasetCompounds.find(obs => obs.id === complexData.id);
+ const colourToggle = getRandomColor(data);
+ const datasetID = complexData.datasetID;
+
+ dispatch(appendComplexList(datasetID, generateMoleculeCompoundId(data)));
+ return dispatch(
+ loadObject({
+ target: Object.assign(
+ { display_div: VIEWS.MAJOR_VIEW },
+ generateComplexObject(data, colourToggle, base_url, datasetID)
+ ),
+ stage,
+ previousRepresentations: complexData.representations,
+ orientationMatrix: null
+ })
+ ).finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ });
+ },
+ [allCompounds, dispatch, stage]
+ );
+
+ const removeComplex = useCallback(
+ complexData => {
+ const datasetCompounds = allCompounds[complexData.datasetID];
+ const data = datasetCompounds?.find(obs => obs.id === complexData.id);
+ const datasetID = complexData.datasetID;
+ const colourToggle = getRandomColor(data);
+
+ dispatch(
+ deleteObject(
+ Object.assign(
+ { display_div: VIEWS.MAJOR_VIEW },
+ generateComplexObject(data, colourToggle, base_url, datasetID)
+ ),
+ stage
+ )
+ );
+ dispatch(removeFromComplexList(datasetID, generateMoleculeCompoundId(data)));
+
+ dispatch(removeFromToBeDisplayedListForDataset(datasetID, { id: complexData.id, type: NGL_OBJECTS.COMPLEX }));
+ },
+ [allCompounds, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeRemovedComplexes = getToBeDisplayedStructuresDataset(
+ toBeDisplayedList,
+ displayedComplexes,
+ NGL_OBJECTS.COMPLEX,
+ true
+ );
+ toBeRemovedComplexes?.forEach(data => {
+ removeComplex(data);
+ });
+ const toBeDisplayedComplexes = getToBeDisplayedStructuresDataset(
+ toBeDisplayedList,
+ displayedComplexes,
+ NGL_OBJECTS.COMPLEX
+ );
+ toBeDisplayedComplexes?.forEach(data => {
+ displayComplex(data);
+ });
+ }, [toBeDisplayedList, displayedComplexes, displayComplex, dispatch, stage, removeComplex]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplayDensityLHS.js b/js/reducers/ngl/useDisplayDensityLHS.js
new file mode 100644
index 000000000..a9b15337f
--- /dev/null
+++ b/js/reducers/ngl/useDisplayDensityLHS.js
@@ -0,0 +1,212 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NGL_OBJECTS } from './constants';
+import {
+ appendDensityList,
+ appendDensityListCustom,
+ appendToBeDisplayedList,
+ appendToDensityListType,
+ removeFromDensityList,
+ removeFromDensityListCustom,
+ removeFromDensityListType,
+ removeFromToBeDisplayedList
+} from '../selection/actions';
+import { generateDensityObject, generateMoleculeId } from '../../components/nglView/generatingObjects';
+import { VIEWS } from '../../constants/constants';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import { loadObject, setOrientation } from './dispatchActions';
+import { base_url } from '../../components/routes/constants';
+import { getToBeDisplayedStructures } from './utils';
+import {
+ addQuality,
+ deleteDensityObject,
+ getDensityChangedParams,
+ getDensityMapData,
+ getProteinData,
+ removeQuality,
+ toggleDensityWireframe
+} from '../../components/preview/molecule/redux/dispatchActions';
+
+export const useDisplayDensityLHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.selectionReducers.toBeDisplayedList);
+ const displayedDensities = useSelector(state => state.selectionReducers.densityList);
+ const displayedCustomDensities = useSelector(state => state.selectionReducers.densityListCustom);
+ const allObservations = useSelector(state => state.apiReducers.all_mol_lists);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displayDensity = useCallback(
+ async densityData => {
+ const data = allObservations.find(obs => obs.id === densityData.id);
+ const colourToggle = getRandomColor(data);
+
+ if (!data.proteinData) {
+ await dispatch(getDensityMapData(data));
+ }
+
+ const prepParams = dispatch(getDensityChangedParams(densityData.isWireframeStyle));
+ const densityObject = generateDensityObject(data, colourToggle, base_url, densityData.isWireframeStyle);
+ const combinedObject = { ...prepParams, ...densityObject };
+ dispatch(
+ loadObject({
+ target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, combinedObject),
+ stage,
+ previousRepresentations: densityData.representations,
+ orientationMatrix: null
+ })
+ ).finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ let molDataId = generateMoleculeId(data);
+ if (!data.proteinData) {
+ dispatch(getProteinData(data)).then(i => {
+ const proteinData = i;
+ data.proteinData = proteinData;
+
+ molDataId['render_event'] = data.proteinData.render_event;
+ molDataId['render_sigmaa'] = data.proteinData.render_sigmaa;
+ molDataId['render_diff'] = data.proteinData.render_diff;
+ molDataId['render_quality'] = data.proteinData.render_quality;
+
+ dispatch(appendDensityList(generateMoleculeId(data)));
+ dispatch(appendToDensityListType(molDataId));
+ if (data.proteinData.render_quality) {
+ return dispatch(addQuality(stage, data, colourToggle, true));
+ }
+ });
+ } else {
+ molDataId['render_event'] = data.proteinData.render_event;
+ molDataId['render_sigmaa'] = data.proteinData.render_sigmaa;
+ molDataId['render_diff'] = data.proteinData.render_diff;
+ molDataId['render_quality'] = data.proteinData.render_quality;
+
+ dispatch(appendDensityList(generateMoleculeId(data)));
+ dispatch(appendToDensityListType(molDataId));
+ if (data.proteinData.render_quality) {
+ return dispatch(addQuality(stage, data, colourToggle, true));
+ }
+ }
+ });
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ const displayCustomDensity = useCallback(
+ async densityData => {
+ const data = allObservations.find(obs => obs.id === densityData.id);
+ const colourToggle = getRandomColor(data);
+
+ if (!data.proteinData) {
+ await dispatch(getDensityMapData(data));
+ }
+
+ let densityObject = dispatch(getDensityChangedParams());
+ densityObject = dispatch(toggleDensityWireframe(densityData.isWireframeStyle, densityObject));
+ const oldDensityData = dispatch(deleteDensityObject(data, colourToggle, stage, !densityData.isWireframeStyle));
+ densityObject = { ...densityObject, ...oldDensityData };
+ const molId = generateMoleculeId(data);
+ dispatch(removeFromDensityList(molId, true));
+ //here we need to remove density but we don't know if it is custom or not so we remove both
+ dispatch(removeFromToBeDisplayedList({ id: densityData.id, type: NGL_OBJECTS.DENSITY }));
+ dispatch(removeFromToBeDisplayedList({ id: densityData.id, type: NGL_OBJECTS.DENSITY_CUSTOM }));
+ //and then re-add it as custom
+ dispatch(appendDensityListCustom(generateMoleculeId(data)));
+ dispatch(
+ appendToBeDisplayedList({
+ ...densityData
+ })
+ );
+ // dispatch(removeFromDensityListType(molId, true));
+
+ return dispatch(
+ loadObject({
+ target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, densityObject),
+ stage,
+ previousRepresentations: densityData.representations,
+ orientationMatrix: null
+ })
+ ).finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ });
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ const removeDensity = useCallback(
+ densityData => {
+ const data = allObservations.find(obs => obs.id === densityData.id);
+ const colourToggle = getRandomColor(data);
+
+ dispatch(toggleDensityWireframe(densityData.isWireframeStyle));
+ dispatch(deleteDensityObject(data, colourToggle, stage, densityData.isWireframeStyle));
+
+ const molId = generateMoleculeId(data);
+ dispatch(removeFromDensityList(molId));
+ dispatch(removeFromDensityListCustom(molId, true));
+ dispatch(removeFromDensityListType(molId));
+ if (data.proteinData.render_quality) {
+ dispatch(removeQuality(stage, data, colourToggle, true));
+ }
+
+ dispatch(removeFromToBeDisplayedList({ id: densityData.id, type: NGL_OBJECTS.DENSITY }));
+ dispatch(removeFromToBeDisplayedList({ id: densityData.id, type: NGL_OBJECTS.DENSITY_CUSTOM }));
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeDisplayedDensities = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedDensities,
+ NGL_OBJECTS.DENSITY
+ );
+ toBeDisplayedDensities?.forEach(data => {
+ displayDensity(data);
+ });
+
+ const toBeDisplayedCustomDensities = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedCustomDensities,
+ NGL_OBJECTS.DENSITY_CUSTOM
+ );
+ toBeDisplayedCustomDensities?.forEach(data => {
+ displayCustomDensity(data);
+ });
+
+ const toBeRemovedDensities = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedDensities,
+ NGL_OBJECTS.DENSITY,
+ true
+ );
+ toBeRemovedDensities?.forEach(data => {
+ removeDensity(data);
+ });
+
+ const toBeRemovedCustomDensities = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedCustomDensities,
+ NGL_OBJECTS.DENSITY_CUSTOM,
+ true
+ );
+ toBeRemovedCustomDensities?.forEach(data => {
+ removeDensity(data);
+ });
+ }, [
+ toBeDisplayedList,
+ displayDensity,
+ dispatch,
+ stage,
+ removeDensity,
+ displayedDensities,
+ displayedCustomDensities,
+ displayCustomDensity
+ ]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplayLigandLHS.js b/js/reducers/ngl/useDisplayLigandLHS.js
new file mode 100644
index 000000000..b828bb0c7
--- /dev/null
+++ b/js/reducers/ngl/useDisplayLigandLHS.js
@@ -0,0 +1,112 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NGL_OBJECTS } from './constants';
+import {
+ appendFragmentDisplayList,
+ appendQualityList,
+ removeFromFragmentDisplayList,
+ removeFromQualityList,
+ removeFromToBeDisplayedList
+} from '../selection/actions';
+import { generateMoleculeId, generateMoleculeObject } from '../../components/nglView/generatingObjects';
+import { VIEWS } from '../../constants/constants';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import { readQualityInformation } from '../../components/nglView/renderingHelpers';
+import { deleteObject, loadObject, setOrientation } from './dispatchActions';
+import { appendMoleculeOrientation } from './actions';
+import { removeVector } from '../../components/preview/molecule/redux/dispatchActions';
+import { getToBeDisplayedStructures } from './utils';
+
+export const useDisplayLigandLHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.selectionReducers.toBeDisplayedList);
+ const displayedLigands = useSelector(state => state.selectionReducers.fragmentDisplayList);
+ const allObservations = useSelector(state => state.apiReducers.all_mol_lists);
+ const skipOrientationChange = useSelector(state => state.nglReducers.skipOrientationChange);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displayLigand = useCallback(
+ ligandData => {
+ const data = allObservations.find(obs => obs.id === ligandData.id);
+ const colourToggle = getRandomColor(data);
+ const currentOrientation = stage.viewerControls.getOrientation();
+
+ dispatch(appendFragmentDisplayList(generateMoleculeId(data)));
+
+ let moleculeObject = generateMoleculeObject(data, colourToggle);
+ let qualityInformation = dispatch(readQualityInformation(moleculeObject.name, moleculeObject.sdf_info));
+
+ let hasAdditionalInformation =
+ ligandData.withQuality === true &&
+ qualityInformation &&
+ qualityInformation.badids &&
+ qualityInformation.badids.length !== 0;
+ if (hasAdditionalInformation) {
+ dispatch(appendQualityList(generateMoleculeId(data)));
+ }
+
+ return dispatch(
+ loadObject({
+ target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, moleculeObject),
+ stage,
+ previousRepresentations: ligandData.representations,
+ loadQuality: hasAdditionalInformation,
+ quality: qualityInformation
+ })
+ ).then(() => {
+ const skipOrientation = skipOrientationChange;
+ if (!skipOrientation) {
+ const ligandOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, ligandOrientation));
+
+ dispatch(appendMoleculeOrientation(data?.id, ligandOrientation));
+ if (!ligandData.center) {
+ // keep current orientation of NGL View
+ console.count(`Before applying orientation matrix after loading ligand.`);
+ stage.viewerControls.orient(currentOrientation);
+ console.count(`After applying orientation matrix after loading ligand.`);
+ }
+ }
+ });
+ },
+ [allObservations, dispatch, skipOrientationChange, stage]
+ );
+
+ const removeLigand = useCallback(
+ ligandData => {
+ const data = allObservations.find(obs => obs.id === ligandData.id);
+ dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage));
+ dispatch(removeFromFragmentDisplayList(generateMoleculeId(data)));
+ dispatch(removeFromQualityList(generateMoleculeId(data)));
+ if (ligandData.withVector === true) {
+ // remove vector
+ dispatch(removeVector(stage, data));
+ }
+
+ dispatch(removeFromToBeDisplayedList({ id: ligandData.id, type: NGL_OBJECTS.LIGAND }));
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeRemovedLigands = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedLigands,
+ NGL_OBJECTS.LIGAND,
+ true
+ );
+ toBeRemovedLigands?.forEach(data => {
+ removeLigand(data);
+ });
+ const toBeDisplayedLigands = getToBeDisplayedStructures(toBeDisplayedList, displayedLigands, NGL_OBJECTS.LIGAND);
+ toBeDisplayedLigands?.forEach(data => {
+ displayLigand(data);
+ });
+ }, [toBeDisplayedList, displayedLigands, displayLigand, dispatch, stage, removeLigand]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplayLigandRHS.js b/js/reducers/ngl/useDisplayLigandRHS.js
new file mode 100644
index 000000000..de3fb1de5
--- /dev/null
+++ b/js/reducers/ngl/useDisplayLigandRHS.js
@@ -0,0 +1,109 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { VIEWS } from '../../constants/constants';
+import { NGL_OBJECTS } from './constants';
+import { getToBeDisplayedStructuresDataset } from './utils';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import {
+ appendLigandList,
+ removeFromLigandList,
+ removeFromToBeDisplayedListForDataset
+} from '../../components/datasets/redux/actions';
+import { generateMoleculeCompoundId, generateMoleculeObject } from '../../components/nglView/generatingObjects';
+import { deleteObject, loadObject, setOrientation } from './dispatchActions';
+import { appendMoleculeOrientation } from './actions';
+import { getDatasetMoleculeID } from '../../components/datasets/redux/dispatchActions';
+
+export const useDisplayLigandRHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.datasetsReducers.toBeDisplayedList);
+ const displayedLigands = useSelector(state => state.datasetsReducers.ligandLists);
+ const allCompounds = useSelector(state => state.datasetsReducers.moleculeLists);
+ const skipOrientationChange = useSelector(state => state.nglReducers.skipOrientationChange);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displayLigand = useCallback(
+ ligandData => {
+ const datasetCompounds = allCompounds[ligandData.datasetID];
+ const data = datasetCompounds.find(obs => obs.id === ligandData.id);
+ const colourToggle = getRandomColor(data);
+ const datasetID = ligandData.datasetID;
+
+ dispatch(appendLigandList(datasetID, generateMoleculeCompoundId(data)));
+ console.count(`Grabbed orientation before loading dataset ligand`);
+ const currentOrientation = stage.viewerControls.getOrientation();
+ return dispatch(
+ loadObject({
+ target: Object.assign(
+ { display_div: VIEWS.MAJOR_VIEW },
+ generateMoleculeObject(data, colourToggle, datasetID)
+ ),
+ stage,
+ previousRepresentations: ligandData.representations,
+ markAsRightSideLigand: true
+ })
+ ).finally(() => {
+ const skipOrientation = skipOrientationChange;
+ if (!skipOrientation) {
+ const ligandOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, ligandOrientation));
+
+ dispatch(appendMoleculeOrientation(getDatasetMoleculeID(datasetID, data?.id), ligandOrientation));
+
+ // keep current orientation of NGL View
+ if (!skipOrientation) {
+ console.count(`Before applying orientation after loading dataset ligand.`);
+ stage.viewerControls.orient(currentOrientation);
+ console.count(`After applying orientation after loading dataset ligand.`);
+ }
+ }
+ });
+ },
+ [allCompounds, dispatch, skipOrientationChange, stage]
+ );
+
+ const removeLigand = useCallback(
+ ligandData => {
+ const datasetCompounds = allCompounds[ligandData.datasetID];
+ const data = datasetCompounds?.find(obs => obs.id === ligandData.id);
+ const datasetID = ligandData.datasetID;
+
+ dispatch(
+ deleteObject(
+ Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data, undefined, datasetID)),
+ stage
+ )
+ );
+ dispatch(removeFromLigandList(datasetID, generateMoleculeCompoundId(data)));
+
+ dispatch(removeFromToBeDisplayedListForDataset(datasetID, { id: ligandData.id, type: NGL_OBJECTS.LIGAND }));
+ },
+ [allCompounds, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeRemovedLigands = getToBeDisplayedStructuresDataset(
+ toBeDisplayedList,
+ displayedLigands,
+ NGL_OBJECTS.LIGAND,
+ true
+ );
+ toBeRemovedLigands?.forEach(data => {
+ removeLigand(data);
+ });
+ const toBeDisplayedLigands = getToBeDisplayedStructuresDataset(
+ toBeDisplayedList,
+ displayedLigands,
+ NGL_OBJECTS.LIGAND
+ );
+ toBeDisplayedLigands?.forEach(data => {
+ displayLigand(data);
+ });
+ }, [toBeDisplayedList, displayedLigands, displayLigand, dispatch, stage, removeLigand]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplayProteinLHS.js b/js/reducers/ngl/useDisplayProteinLHS.js
new file mode 100644
index 000000000..a2f873a11
--- /dev/null
+++ b/js/reducers/ngl/useDisplayProteinLHS.js
@@ -0,0 +1,99 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NGL_OBJECTS } from './constants';
+import {
+ appendProteinList,
+ appendQualityList,
+ removeFromProteinList,
+ removeFromToBeDisplayedList
+} from '../selection/actions';
+import { generateHitProteinObject, generateMoleculeId } from '../../components/nglView/generatingObjects';
+import { VIEWS } from '../../constants/constants';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import { readQualityInformation } from '../../components/nglView/renderingHelpers';
+import { deleteObject, loadObject, setOrientation } from './dispatchActions';
+import { base_url } from '../../components/routes/constants';
+import { getToBeDisplayedStructures } from './utils';
+
+export const useDisplayProteinLHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.selectionReducers.toBeDisplayedList);
+ const displayedProteins = useSelector(state => state.selectionReducers.proteinList);
+ const allObservations = useSelector(state => state.apiReducers.all_mol_lists);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displayProtein = useCallback(
+ proteinData => {
+ const data = allObservations.find(obs => obs.id === proteinData.id);
+ const colourToggle = getRandomColor(data);
+
+ dispatch(appendProteinList(generateMoleculeId(data)));
+ const hitProteinObject = generateHitProteinObject(data, colourToggle, base_url);
+ const qualityInformation = dispatch(readQualityInformation(hitProteinObject.name, hitProteinObject.sdf_info));
+
+ let hasAdditionalInformation =
+ proteinData.withQuality === true &&
+ qualityInformation &&
+ qualityInformation.badproteinids &&
+ qualityInformation.badproteinids.length !== 0;
+ if (hasAdditionalInformation) {
+ dispatch(appendQualityList(generateMoleculeId(data), true));
+ }
+
+ return dispatch(
+ loadObject({
+ target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, hitProteinObject),
+ stage,
+ previousRepresentations: proteinData.representations,
+ orientationMatrix: null,
+ loadQuality: hasAdditionalInformation,
+ quality: qualityInformation,
+ preserveColour: proteinData.preserveColour
+ })
+ ).finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ });
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ const removeProtein = useCallback(
+ proteinData => {
+ const data = allObservations.find(obs => obs.id === proteinData.id);
+ const colourToggle = getRandomColor(data);
+ dispatch(
+ deleteObject(
+ Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateHitProteinObject(data, colourToggle, base_url)),
+ stage
+ )
+ );
+ dispatch(removeFromProteinList(generateMoleculeId(data)));
+ dispatch(removeFromToBeDisplayedList({ id: proteinData.id, type: NGL_OBJECTS.PROTEIN }));
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeDisplayedProteins = getToBeDisplayedStructures(toBeDisplayedList, displayedProteins, NGL_OBJECTS.PROTEIN);
+ toBeDisplayedProteins?.forEach(data => {
+ displayProtein(data);
+ });
+
+ const toBeRemovedProteins = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedProteins,
+ NGL_OBJECTS.PROTEIN,
+ true
+ );
+ toBeRemovedProteins?.forEach(data => {
+ removeProtein(data);
+ });
+ }, [toBeDisplayedList, displayProtein, dispatch, stage, removeProtein, displayedProteins]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplayProteinRHS.js b/js/reducers/ngl/useDisplayProteinRHS.js
new file mode 100644
index 000000000..f6e45beaf
--- /dev/null
+++ b/js/reducers/ngl/useDisplayProteinRHS.js
@@ -0,0 +1,97 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { VIEWS } from '../../constants/constants';
+import { NGL_OBJECTS } from './constants';
+import { getToBeDisplayedStructuresDataset } from './utils';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import {
+ appendProteinList,
+ removeFromProteinList,
+ removeFromToBeDisplayedListForDataset
+} from '../../components/datasets/redux/actions';
+import { generateHitProteinObject, generateMoleculeCompoundId } from '../../components/nglView/generatingObjects';
+import { deleteObject, loadObject, setOrientation } from './dispatchActions';
+import { base_url } from '../../components/routes/constants';
+
+export const useDisplayProteinRHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.datasetsReducers.toBeDisplayedList);
+ const displayedProteins = useSelector(state => state.datasetsReducers.proteinLists);
+ const allCompounds = useSelector(state => state.datasetsReducers.moleculeLists);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displayProtein = useCallback(
+ proteinData => {
+ const datasetCompounds = allCompounds[proteinData.datasetID];
+ const data = datasetCompounds.find(obs => obs.id === proteinData.id);
+ const colourToggle = getRandomColor(data);
+ const datasetID = proteinData.datasetID;
+
+ dispatch(appendProteinList(datasetID, generateMoleculeCompoundId(data)));
+ return dispatch(
+ loadObject({
+ target: Object.assign(
+ { display_div: VIEWS.MAJOR_VIEW },
+ generateHitProteinObject(data, colourToggle, base_url, datasetID)
+ ),
+ stage,
+ previousRepresentations: proteinData.representations,
+ orientationMatrix: null
+ })
+ ).finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ });
+ },
+ [allCompounds, dispatch, stage]
+ );
+
+ const removeProtein = useCallback(
+ proteinData => {
+ const datasetCompounds = allCompounds[proteinData.datasetID];
+ const data = datasetCompounds?.find(obs => obs.id === proteinData.id);
+ const datasetID = proteinData.datasetID;
+ const colourToggle = getRandomColor(data);
+
+ dispatch(
+ deleteObject(
+ Object.assign(
+ { display_div: VIEWS.MAJOR_VIEW },
+ generateHitProteinObject(data, colourToggle, base_url, datasetID)
+ ),
+ stage
+ )
+ );
+ dispatch(removeFromProteinList(datasetID, generateMoleculeCompoundId(data)));
+
+ dispatch(removeFromToBeDisplayedListForDataset(datasetID, { id: proteinData.id, type: NGL_OBJECTS.PROTEIN }));
+ },
+ [allCompounds, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeRemovedProteins = getToBeDisplayedStructuresDataset(
+ toBeDisplayedList,
+ displayedProteins,
+ NGL_OBJECTS.PROTEIN,
+ true
+ );
+ toBeRemovedProteins?.forEach(data => {
+ removeProtein(data);
+ });
+ const toBeDisplayedProteins = getToBeDisplayedStructuresDataset(
+ toBeDisplayedList,
+ displayedProteins,
+ NGL_OBJECTS.PROTEIN
+ );
+ toBeDisplayedProteins?.forEach(data => {
+ displayProtein(data);
+ });
+ }, [toBeDisplayedList, displayedProteins, displayProtein, dispatch, stage, removeProtein]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplaySurfaceRHS.js b/js/reducers/ngl/useDisplaySurfaceRHS.js
new file mode 100644
index 000000000..32776da1f
--- /dev/null
+++ b/js/reducers/ngl/useDisplaySurfaceRHS.js
@@ -0,0 +1,97 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { VIEWS } from '../../constants/constants';
+import { NGL_OBJECTS } from './constants';
+import { getToBeDisplayedStructuresDataset } from './utils';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import {
+ appendSurfaceList,
+ removeFromSurfaceList,
+ removeFromToBeDisplayedListForDataset
+} from '../../components/datasets/redux/actions';
+import { generateMoleculeCompoundId, generateSurfaceObject } from '../../components/nglView/generatingObjects';
+import { deleteObject, loadObject, setOrientation } from './dispatchActions';
+import { base_url } from '../../components/routes/constants';
+
+export const useDisplaySurfaceRHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.datasetsReducers.toBeDisplayedList);
+ const displayedSurfaces = useSelector(state => state.datasetsReducers.surfaceLists);
+ const allCompounds = useSelector(state => state.datasetsReducers.moleculeLists);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displaySurface = useCallback(
+ surfaceData => {
+ const datasetCompounds = allCompounds[surfaceData.datasetID];
+ const data = datasetCompounds.find(obs => obs.id === surfaceData.id);
+ const colourToggle = getRandomColor(data);
+ const datasetID = surfaceData.datasetID;
+
+ dispatch(appendSurfaceList(datasetID, generateMoleculeCompoundId(data)));
+ return dispatch(
+ loadObject({
+ target: Object.assign(
+ { display_div: VIEWS.MAJOR_VIEW },
+ generateSurfaceObject(data, colourToggle, base_url, datasetID)
+ ),
+ stage,
+ previousRepresentations: surfaceData.representations,
+ orientationMatrix: null
+ })
+ ).finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ });
+ },
+ [allCompounds, dispatch, stage]
+ );
+
+ const removeSurface = useCallback(
+ surfaceData => {
+ const datasetCompounds = allCompounds[surfaceData.datasetID];
+ const data = datasetCompounds?.find(obs => obs.id === surfaceData.id);
+ const datasetID = surfaceData.datasetID;
+ const colourToggle = getRandomColor(data);
+
+ dispatch(
+ deleteObject(
+ Object.assign(
+ { display_div: VIEWS.MAJOR_VIEW },
+ generateSurfaceObject(data, colourToggle, base_url, datasetID)
+ ),
+ stage
+ )
+ );
+ dispatch(removeFromSurfaceList(datasetID, generateMoleculeCompoundId(data)));
+
+ dispatch(removeFromToBeDisplayedListForDataset(datasetID, { id: surfaceData.id, type: NGL_OBJECTS.SURFACE }));
+ },
+ [allCompounds, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeRemovedSurfaces = getToBeDisplayedStructuresDataset(
+ toBeDisplayedList,
+ displayedSurfaces,
+ NGL_OBJECTS.SURFACE,
+ true
+ );
+ toBeRemovedSurfaces?.forEach(data => {
+ removeSurface(data);
+ });
+ const toBeDisplayedSurfaces = getToBeDisplayedStructuresDataset(
+ toBeDisplayedList,
+ displayedSurfaces,
+ NGL_OBJECTS.SURFACE
+ );
+ toBeDisplayedSurfaces?.forEach(data => {
+ displaySurface(data);
+ });
+ }, [toBeDisplayedList, displayedSurfaces, displaySurface, dispatch, stage, removeSurface]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplaySurfacesLHS.js b/js/reducers/ngl/useDisplaySurfacesLHS.js
new file mode 100644
index 000000000..427d6f3f2
--- /dev/null
+++ b/js/reducers/ngl/useDisplaySurfacesLHS.js
@@ -0,0 +1,81 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NGL_OBJECTS } from './constants';
+import { appendSurfaceList, removeFromSurfaceList, removeFromToBeDisplayedList } from '../selection/actions';
+import { generateMoleculeId, generateSurfaceObject } from '../../components/nglView/generatingObjects';
+import { VIEWS } from '../../constants/constants';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { getRandomColor } from '../../components/preview/molecule/utils/color';
+import { deleteObject, loadObject, setOrientation } from './dispatchActions';
+import { base_url } from '../../components/routes/constants';
+import { getToBeDisplayedStructures } from './utils';
+
+export const useDisplaySurfaceLHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.selectionReducers.toBeDisplayedList);
+ const displayedSurfaces = useSelector(state => state.selectionReducers.surfaceList);
+ const allObservations = useSelector(state => state.apiReducers.all_mol_lists);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displaySurface = useCallback(
+ surfaceData => {
+ const data = allObservations.find(obs => obs.id === surfaceData.id);
+ const colourToggle = getRandomColor(data);
+
+ dispatch(appendSurfaceList(generateMoleculeId(data)));
+ return dispatch(
+ loadObject({
+ target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateSurfaceObject(data, colourToggle, base_url)),
+ stage,
+ previousRepresentations: surfaceData.representations,
+ orientationMatrix: null,
+ preserveColour: surfaceData.preserveColour
+ })
+ ).finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ });
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ const removeSurface = useCallback(
+ surfaceData => {
+ const data = allObservations.find(obs => obs.id === surfaceData.id);
+ const colourToggle = getRandomColor(data);
+
+ dispatch(
+ deleteObject(
+ Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateSurfaceObject(data, colourToggle, base_url)),
+ stage
+ )
+ );
+ dispatch(removeFromSurfaceList(generateMoleculeId(data)));
+
+ dispatch(removeFromToBeDisplayedList({ id: surfaceData.id, type: NGL_OBJECTS.SURFACE }));
+ },
+ [allObservations, dispatch, stage]
+ );
+
+ useEffect(() => {
+ const toBeDisplayedSurfaces = getToBeDisplayedStructures(toBeDisplayedList, displayedSurfaces, NGL_OBJECTS.SURFACE);
+ toBeDisplayedSurfaces?.forEach(data => {
+ displaySurface(data);
+ });
+
+ const toBeRemovedSurfaces = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedSurfaces,
+ NGL_OBJECTS.SURFACE,
+ true
+ );
+ toBeRemovedSurfaces?.forEach(data => {
+ removeSurface(data);
+ });
+ }, [toBeDisplayedList, displaySurface, dispatch, stage, removeSurface, displayedSurfaces]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/useDisplayVectorLHS.js b/js/reducers/ngl/useDisplayVectorLHS.js
new file mode 100644
index 000000000..e2ca3afc5
--- /dev/null
+++ b/js/reducers/ngl/useDisplayVectorLHS.js
@@ -0,0 +1,114 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { NGL_OBJECTS } from './constants';
+import {
+ appendVectorOnList,
+ removeFromToBeDisplayedList,
+ removeFromVectorOnList,
+ setVectorList,
+ updateBondColorMapOfCompounds,
+ updateVectorCompounds
+} from '../selection/actions';
+import { generateMoleculeId } from '../../components/nglView/generatingObjects';
+import { VIEWS } from '../../constants/constants';
+import { NglContext } from '../../components/nglView/nglProvider';
+import { deleteObject, setOrientation } from './dispatchActions';
+import { base_url } from '../../components/routes/constants';
+import { getToBeDisplayedStructures } from './utils';
+import { selectVectorAndResetCompounds } from '../selection/dispatchActions';
+import { api } from '../../utils/api';
+import { getViewUrl, handleVector, removeCurrentVector } from '../../components/preview/molecule/redux/dispatchActions';
+
+export const useDisplayVectorLHS = () => {
+ const dispatch = useDispatch();
+
+ const toBeDisplayedList = useSelector(state => state.selectionReducers.toBeDisplayedList);
+ const displayedVectors = useSelector(state => state.selectionReducers.vectorOnList);
+ const allObservations = useSelector(state => state.apiReducers.all_mol_lists);
+ const currentVector = useSelector(state => state.selectionReducers.currentVector);
+ const vector_list = useSelector(state => state.selectionReducers.vector_list);
+
+ const { getNglView } = useContext(NglContext);
+ const stage = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage;
+
+ const displayVector = useCallback(
+ vectorData => {
+ const data = allObservations.find(obs => obs.id === vectorData.id);
+
+ dispatch(appendVectorOnList(generateMoleculeId(data)));
+ dispatch(selectVectorAndResetCompounds(currentVector));
+
+ return api({ url: getViewUrl('graph', data) })
+ .then(response => {
+ const result = response.data.graph;
+ const new_dict = {};
+ // Uniquify
+ if (result) {
+ Object.keys(result).forEach(key => {
+ const smiSet = new Set();
+ new_dict[key] = {};
+ new_dict[key]['addition'] = [];
+ new_dict[key]['vector'] = result[key]['vector'];
+ Object.keys(result[key]['addition']).forEach(index => {
+ const 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: new URL(base_url + '/api/vector/?id=' + data.id) }))
+ .then(response => {
+ dispatch(handleVector(response.data?.results[0]?.vectors, stage, data));
+ })
+ .finally(() => {
+ const currentOrientation = stage.viewerControls.getOrientation();
+ dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation));
+ });
+ },
+ [allObservations, currentVector, dispatch, stage]
+ );
+
+ const removeVector = useCallback(
+ vectorData => {
+ const data = allObservations.find(obs => obs.id === vectorData.id);
+
+ vector_list
+ .filter(item => item.moleculeId === data.id)
+ .forEach(item => dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, item), stage)));
+
+ dispatch(removeCurrentVector(data.smiles));
+
+ dispatch(updateVectorCompounds(data.smiles, undefined));
+ dispatch(updateBondColorMapOfCompounds(data.smiles, undefined));
+ dispatch(removeFromVectorOnList(generateMoleculeId(data)));
+
+ dispatch(setVectorList(vector_list.filter(item => item.moleculeId !== data.id)));
+
+ dispatch(removeFromToBeDisplayedList({ id: vectorData.id, type: NGL_OBJECTS.VECTOR }));
+ },
+ [allObservations, dispatch, stage, vector_list]
+ );
+
+ useEffect(() => {
+ const toBeDisplayedVectors = getToBeDisplayedStructures(toBeDisplayedList, displayedVectors, NGL_OBJECTS.VECTOR);
+ toBeDisplayedVectors?.forEach(data => {
+ displayVector(data);
+ });
+
+ const toBeRemovedVectors = getToBeDisplayedStructures(
+ toBeDisplayedList,
+ displayedVectors,
+ NGL_OBJECTS.VECTOR,
+ true
+ );
+ toBeRemovedVectors?.forEach(data => {
+ removeVector(data);
+ });
+ }, [toBeDisplayedList, displayVector, dispatch, stage, removeVector, displayedVectors]);
+
+ return {};
+};
diff --git a/js/reducers/ngl/utils.js b/js/reducers/ngl/utils.js
new file mode 100644
index 000000000..b00e209d3
--- /dev/null
+++ b/js/reducers/ngl/utils.js
@@ -0,0 +1,28 @@
+export const getToBeDisplayedStructures = (toBeDisplayed, displayedList, type, toBeRemoved = false) => {
+ let structures = [];
+
+ structures = toBeDisplayed.filter(
+ struct =>
+ struct.type === type &&
+ struct.display === !toBeRemoved &&
+ (toBeRemoved || !displayedList.find(id => id === struct.id))
+ );
+
+ return structures;
+};
+
+export const getToBeDisplayedStructuresDataset = (toBeDisplayed, displayedList, type, toBeRemoved = false) => {
+ let result = [];
+
+ Object.keys(toBeDisplayed).forEach(datasetID => {
+ const displayedDatasetLigands = displayedList[datasetID] || [];
+ const toBeDisplayedDataset = toBeDisplayed[datasetID] || [];
+ result = [
+ ...result,
+ ...getToBeDisplayedStructures(toBeDisplayedDataset, displayedDatasetLigands, type, toBeRemoved)
+ ];
+ // result.push(...getToBeDisplayedStructures(toBeDisplayedDataset, displayedDatasetLigands, type, toBeRemoved));
+ });
+
+ return result;
+};
diff --git a/js/reducers/selection/actions.js b/js/reducers/selection/actions.js
index e4d708386..88e60669b 100644
--- a/js/reducers/selection/actions.js
+++ b/js/reducers/selection/actions.js
@@ -617,3 +617,31 @@ export const setTargetToEdit = target => {
target: target
};
};
+
+export const setToBeDisplayedList = toBeDisplayedList => {
+ return {
+ type: constants.SET_TO_BE_DISPLAYED_LIST,
+ toBeDisplayedList: toBeDisplayedList
+ };
+};
+
+export const appendToBeDisplayedList = item => {
+ return {
+ type: constants.APPEND_TO_BE_DISPLAYED_LIST,
+ item: item
+ };
+};
+
+export const removeFromToBeDisplayedList = item => {
+ return {
+ type: constants.REMOVE_FROM_TO_BE_DISPLAYED_LIST,
+ item: item
+ };
+};
+
+export const updateInToBeDisplayedList = item => {
+ return {
+ type: constants.UPDATE_IN_TO_BE_DISPLAYED_LIST,
+ item: item
+ };
+};
diff --git a/js/reducers/selection/constants.js b/js/reducers/selection/constants.js
index 7255753a6..795001356 100644
--- a/js/reducers/selection/constants.js
+++ b/js/reducers/selection/constants.js
@@ -104,7 +104,12 @@ export const constants = {
SET_UNSELECT_VISIBLE_POSES: prefix + 'SET_UNSELECT_VISIBLE_POSES',
SET_OBSERVATION_DIALOG_ACTION: prefix + 'SET_OBSERVATION_DIALOG_ACTION',
- SET_TARGET_TO_EDIT: prefix + 'SET_TARGET_TO_EDIT'
+ SET_TARGET_TO_EDIT: prefix + 'SET_TARGET_TO_EDIT',
+
+ SET_TO_BE_DISPLAYED_LIST: prefix + 'SET_TO_BE_DISPLAYED_LIST',
+ APPEND_TO_BE_DISPLAYED_LIST: prefix + 'APPEND_TO_BE_DISPLAYED_LIST',
+ REMOVE_FROM_TO_BE_DISPLAYED_LIST: prefix + 'REMOVE_FROM_TO_BE_DISPLAYED_LIST',
+ UPDATE_IN_TO_BE_DISPLAYED_LIST: prefix + 'UPDATE_IN_TO_BE_DISPLAYED_LIST'
};
export const PREDEFINED_FILTERS = {
diff --git a/js/reducers/selection/selectionReducers.js b/js/reducers/selection/selectionReducers.js
index 2b17daaa1..49ff18944 100644
--- a/js/reducers/selection/selectionReducers.js
+++ b/js/reducers/selection/selectionReducers.js
@@ -56,11 +56,48 @@ export const INITIAL_STATE = {
areLSHCompoundsInitialized: false,
toastMessages: [],
isScrollFiredForLHS: false,
- targetToEdit: null
+ targetToEdit: null,
+ // Shape of the object in toBeDisplayedList:
+ // {
+ // type: 'L|P|C|S|V|RIBBON|etc...',
+ // id: 1,
+
+ // center: true,
+ // withQuality: true,
+ // representations: [] etc...
+
+ // display: true
+ // }
+ toBeDisplayedList: []
};
export function selectionReducers(state = INITIAL_STATE, action = {}) {
switch (action.type) {
+ case constants.SET_TO_BE_DISPLAYED_LIST:
+ return { ...state, toBeDisplayedList: action.toBeDisplayedList };
+
+ case constants.APPEND_TO_BE_DISPLAYED_LIST:
+ return { ...state, toBeDisplayedList: [...state.toBeDisplayedList, action.item] };
+
+ case constants.REMOVE_FROM_TO_BE_DISPLAYED_LIST:
+ return {
+ ...state,
+ toBeDisplayedList: state.toBeDisplayedList.filter(
+ item => item.id !== action.item.id || item.type !== action.item.type
+ )
+ };
+
+ case constants.UPDATE_IN_TO_BE_DISPLAYED_LIST:
+ return {
+ ...state,
+ toBeDisplayedList: state.toBeDisplayedList.map(item => {
+ if (item.id === action.item.id && item.type === action.item.type) {
+ return { ...item, ...action.item };
+ }
+ return item;
+ })
+ };
+
case constants.SET_SCROLL_FIRED_FOR_LHS: {
return { ...state, isScrollFiredForLHS: action.isFired };
}