Skip to content

Commit

Permalink
#696 - Drag and drop compounds
Browse files Browse the repository at this point in the history
  • Loading branch information
ag-m2ms committed Dec 8, 2021
1 parent e223d79 commit 3c915ee
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 29 deletions.
70 changes: 45 additions & 25 deletions js/components/datasets/datasetMoleculeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
IconButton,
ButtonGroup
} from '@material-ui/core';
import React, { useState, useEffect, memo, useRef, useContext } from 'react';
import React, { useState, useEffect, memo, useRef, useContext, useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { DatasetMoleculeView } from './datasetMoleculeView';
import { colourList } from '../preview/molecule/utils/color';
Expand All @@ -39,7 +39,7 @@ import {
moveMoleculeInspirationsSettings,
removeAllSelectedDatasetMolecules
} from './redux/dispatchActions';
import { setFilterDialogOpen, setSearchStringOfCompoundSet } from './redux/actions';
import { setFilterDialogOpen, setSearchStringOfCompoundSet, replaceAllMoleculeLists } from './redux/actions';
import { DatasetFilter } from './datasetFilter';
import { FilterList, Search, Link } from '@material-ui/icons';
import { getFilteredDatasetMoleculeList } from './redux/selectors';
Expand All @@ -51,6 +51,9 @@ import { hideAllSelectedMolecules } from '../preview/molecule/redux/dispatchActi
import { getMoleculeList } from '../preview/molecule/redux/selectors';
import { setSelectedAllByType, setDeselectedAllByType } from './redux/actions';

import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';

const useStyles = makeStyles(theme => ({
container: {
height: '100%',
Expand Down Expand Up @@ -458,6 +461,19 @@ export const DatasetMoleculeList = memo(

const [isOpenAlert, setIsOpenAlert] = useState(false);

const moveMolecule = useCallback(
(dragIndex, hoverIndex) => {
const moleculeList = [...moleculeLists[datasetID]];
const draggedElement = moleculeList[dragIndex];

moleculeList.splice(dragIndex, 1);
moleculeList.splice(hoverIndex, 0, draggedElement);

dispatch(replaceAllMoleculeLists({ ...moleculeLists, [datasetID]: moleculeList }));
},
[dispatch, datasetID, moleculeLists]
);

return (
<ComputeSize
componentRef={filterRef.current}
Expand Down Expand Up @@ -653,29 +669,33 @@ export const DatasetMoleculeList = memo(
}
useWindow={false}
>
{datasetID &&
currentMolecules.map((data, index, array) => (
<DatasetMoleculeView
key={index}
index={index}
imageHeight={imgHeight}
imageWidth={imgWidth}
data={data}
datasetID={datasetID}
setRef={setSelectedMoleculeRef}
showCrossReferenceModal
previousItemData={index > 0 && array[index - 1]}
nextItemData={index < array?.length && array[index + 1]}
removeOfAllSelectedTypes={removeOfAllSelectedTypes}
removeOfAllSelectedTypesOfInspirations={removeOfAllSelectedTypesOfInspirations}
moveSelectedMoleculeInspirationsSettings={moveSelectedMoleculeInspirationsSettings}
L={ligandList.includes(data.id)}
P={proteinList.includes(data.id)}
C={complexList.includes(data.id)}
S={surfaceList.includes(data.id)}
V={false}
/>
))}
{datasetID && (
<DndProvider backend={HTML5Backend}>
{currentMolecules.map((data, index, array) => (
<DatasetMoleculeView
key={data.id}
index={index}
imageHeight={imgHeight}
imageWidth={imgWidth}
data={data}
datasetID={datasetID}
setRef={setSelectedMoleculeRef}
showCrossReferenceModal
previousItemData={index > 0 && array[index - 1]}
nextItemData={index < array?.length && array[index + 1]}
removeOfAllSelectedTypes={removeOfAllSelectedTypes}
removeOfAllSelectedTypesOfInspirations={removeOfAllSelectedTypesOfInspirations}
moveSelectedMoleculeInspirationsSettings={moveSelectedMoleculeInspirationsSettings}
L={ligandList.includes(data.id)}
P={proteinList.includes(data.id)}
C={complexList.includes(data.id)}
S={surfaceList.includes(data.id)}
V={false}
moveMolecule={moveMolecule}
/>
))}
</DndProvider>
)}
</InfiniteScroll>
</Grid>
<Grid item>
Expand Down
25 changes: 21 additions & 4 deletions js/components/datasets/datasetMoleculeView.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@ import {
showHideLigand
} from '../preview/compounds/redux/dispatchActions';
import { colourList } from '../preview/molecule/utils/color';
import { useDrag, useDrop } from 'react-dnd';
import { useDragDropMoleculeView } from './useDragDropMoleculeView';

const useStyles = makeStyles(theme => ({
container: {
padding: theme.spacing(1) / 4,
color: 'black',
height: 54
height: 54,
cursor: 'move'
},
contButtonsMargin: {
margin: theme.spacing(1) / 2
Expand Down Expand Up @@ -256,13 +259,18 @@ export const DatasetMoleculeView = memo(
C,
S,
V,
fromSelectedCompounds = false
fromSelectedCompounds = false,
moveMolecule
}) => {
const ref = useRef(null);

const { handlerId, isDragging } = useDragDropMoleculeView(ref, data.id, index, moveMolecule);
const opacity = isDragging ? 0 : 1;

const selectedAll = useRef(false);
const currentID = (data && data.id) || (data && data.smiles) || undefined;
const isFromVectorSelector = isCompoundFromVectorSelector(data);
const classes = useStyles();
const ref = useRef(null);
const dispatch = useDispatch();
const compoundsToBuyList = useSelector(state => state.datasetsReducers.compoundsToBuyDatasetMap[datasetID]);
const allInspirations = useSelector(state => state.datasetsReducers.allInspirations);
Expand Down Expand Up @@ -544,7 +552,16 @@ export const DatasetMoleculeView = memo(

return (
<>
<Grid container justify="space-between" direction="row" className={classes.container} wrap="nowrap" ref={ref}>
<Grid
container
justify="space-between"
direction="row"
className={classes.container}
wrap="nowrap"
ref={ref}
data-handler-id={handlerId}
style={{ opacity }}
>
{/*Site number*/}
<Grid item container justify="space-between" direction="column" className={classes.site}>
<Grid item>
Expand Down
65 changes: 65 additions & 0 deletions js/components/datasets/useDragDropMoleculeView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useDrag, useDrop } from 'react-dnd';

const DND_TYPE = 'DATASET_MOLECULE_VIEW';

// Taken and adjusted from https://react-dnd.github.io/react-dnd/examples/sortable/simple
export const useDragDropMoleculeView = (ref, id, index, moveMolecule) => {
const [{ handlerId }, drop] = useDrop({
accept: DND_TYPE,
collect(monitor) {
return {
handlerId: monitor.getHandlerId()
};
},
hover(item, monitor) {
if (!ref.current) {
return;
}
const dragIndex = item.index;
const hoverIndex = index;
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return;
}
// Determine rectangle on screen
const hoverBoundingRect = ref.current?.getBoundingClientRect();
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
// Determine mouse position
const clientOffset = monitor.getClientOffset();
// Get pixels to the top
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return;
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return;
}
// Time to actually perform the action
moveMolecule(dragIndex, hoverIndex);
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex;
}
});

const [{ isDragging }, drag] = useDrag({
type: DND_TYPE,
item: () => {
return { id, index };
},
collect: monitor => ({
isDragging: monitor.isDragging()
})
});
drag(drop(ref));

return { handlerId, isDragging };
};
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
"react": "^16.11.0",
"react-canvas-draw": "^1.1.0",
"react-color": "^2.19.3",
"react-dnd": "^14.0.4",
"react-dnd-html5-backend": "^14.0.2",
"react-dom": "^16.12.0",
"react-event-timeline": "^1.6.3",
"react-grid-gallery": "^0.5.5",
Expand Down

0 comments on commit 3c915ee

Please sign in to comment.