From 58d9bd9f3f03af70ea5d4ce0a6d8ed67052f505f Mon Sep 17 00:00:00 2001 From: Richard Gillams <37295433+ricgillams@users.noreply.github.com> Date: Mon, 17 Sep 2018 12:06:57 +0100 Subject: [PATCH 1/2] Merge XChem changes (#19) * Reshow colours when we move between vectors (#65) * Reshow colours when change vector * Update molecule viewer based on Brian's suggestions (#66) Update molecule view to * replace clunky sliders with buttons * add box around molecules --- js/components/compoundView.js | 35 +++++----- js/components/generalComponents.js | 2 +- js/components/moleculeView.js | 103 +++++++++++++++++++++-------- js/containers/fraggleBoxHolder.js | 1 - js/containers/previewHolder.js | 2 +- 5 files changed, 93 insertions(+), 50 deletions(-) diff --git a/js/components/compoundView.js b/js/components/compoundView.js index b8c6b6f24..1e4f52efc 100644 --- a/js/components/compoundView.js +++ b/js/components/compoundView.js @@ -45,14 +45,20 @@ class CompoundView extends GenericView { this.handleConf = this.handleConf.bind(this); } - checkInList() { - var isInToBuyList = false; - for(var item in this.props.to_buy_list) { - if (this.props.to_buy_list[item].smiles == this.send_obj.smiles) { - isInToBuyList = true + checkInList(nextProps) { + var isHighlighted = false; + if (nextProps.highlightedCompound.smiles == this.send_obj.smiles) { + isHighlighted = true; + } + this.setState(prevState => ({isHighlighted: isHighlighted})); + + var compoundClass = 0; + for(var item in nextProps.to_buy_list){ + if (nextProps.to_buy_list[item].smiles == this.send_obj.smiles) { + var compoundClass = nextProps.to_buy_list[item].class } } - this.setState(prevState => ({isInToBuyList: isInToBuyList})) + this.setState(prevState => ({compoundClass: compoundClass})) } handleClick(e) { @@ -119,22 +125,13 @@ class CompoundView extends GenericView { componentDidMount() { this.loadFromServer(this.props.width,this.props.height); + if(this.props.to_buy_list.length!=0){ + this.checkInList(this.props); + } } componentWillReceiveProps(nextProps) { - var isHighlighted = false; - if (nextProps.highlightedCompound.smiles == this.send_obj.smiles) { - isHighlighted = true; - } - this.setState(prevState => ({isHighlighted: isHighlighted})); - - var compoundClass = 0; - for(var item in nextProps.to_buy_list){ - if (nextProps.to_buy_list[item].smiles == this.send_obj.smiles) { - var compoundClass = nextProps.to_buy_list[item].class - } - } - this.setState(prevState => ({compoundClass: compoundClass})) + this.checkInList(nextProps); } render() { diff --git a/js/components/generalComponents.js b/js/components/generalComponents.js index 1dda93a9b..f02827da6 100644 --- a/js/components/generalComponents.js +++ b/js/components/generalComponents.js @@ -172,7 +172,7 @@ export class GenericView extends React.Component{ ' ' + ' ' + ' ' + - ''} + '', value: [], vectorOn: false, complexOn:false} this.selected_style = {width: props.width.toString+'px', height: props.height.toString()+'px', backgroundColor: "#B7C185"} this.conf_on_style = {borderStyle: "solid"} this.comp_on_style = {backgroundColor: "#B7C185"} diff --git a/js/components/moleculeView.js b/js/components/moleculeView.js index 58039a62b..b96816cd7 100644 --- a/js/components/moleculeView.js +++ b/js/components/moleculeView.js @@ -4,13 +4,13 @@ import React from "react"; import {connect} from "react-redux"; +import {ButtonToolbar, ToggleButtonGroup, ToggleButton} from "react-bootstrap"; import * as nglLoadActions from "../actions/nglLoadActions"; import {GenericView} from "./generalComponents"; import * as nglObjectTypes from "./nglObjectTypes"; import * as selectionActions from "../actions/selectionActions"; import * as listTypes from "./listTypes"; import "../../css/toggle.css"; -import Toggle from "react-bootstrap-toggle"; import SVGInline from "react-svg-inline"; import fetch from "cross-fetch"; @@ -25,12 +25,11 @@ class MoleculeView extends GenericView { this.getViewUrl = this.getViewUrl.bind(this); this.onVector = this.onVector.bind(this); this.onComplex = this.onComplex.bind(this); + this.handleChange = this.handleChange.bind(this); var base_url = window.location.protocol + "//" + window.location.host this.base_url = base_url; this.url = new URL(base_url + '/api/molimg/' + this.props.data.id + "/") this.key = "mol_image" - this.state.vectorOn = false - this.state.complexOn = false this.colourToggle = this.getRandomColor(); } @@ -125,33 +124,69 @@ class MoleculeView extends GenericView { this.props.setVectorList(objList) } + handleChange(value){ + var old = this.state.value; + var new_list = value.slice(); + var removed = old.filter(function(i) {return value.indexOf(i)<0;})[0] + var added = value.filter(function(i) {return old.indexOf(i)<0;})[0] + var changed = [removed,added]; + if (changed.indexOf(1)>-1){ + this.onComplex(new_list); + } + if (changed.indexOf(2)>-1){ + this.handleClick(new_list); + } + if (changed.indexOf(3)>-1){ + this.onVector(new_list); + } + } + componentDidMount() { this.loadFromServer(this.props.width,this.props.height); var thisToggleOn = this.props.fragmentDisplayList.has(this.props.data.id); var complexOn = this.props.complexList.has(this.props.data.id); - this.setState(prevState => ({complexOn: complexOn, isToggleOn: thisToggleOn})) + var value_list = [] + if(complexOn){ + value_list.push(1) + } + if(thisToggleOn){ + value_list.push(2) + } + if(this.props.to_query==this.props.data.smiles){ + value_list.push(3) + } + this.setState(prevState => ({value: value_list, complexOn: complexOn, isToggleOn: thisToggleOn})) + } + + componentWillReceiveProps(nextProps){ + var value_list = this.state.value.slice(); + if(nextProps.to_query!=this.props.data.smiles){ + var index = value_list.indexOf(3); + if (index > -1) { + value_list.splice(index, 1); + this.setState(prevState => ({value: value_list})) + } + } } + render() { const svg_image = ; const selected_style = {width: this.props.width.toString+'px', height: this.props.height.toString()+'px', backgroundColor: this.colourToggle} - this.current_style = this.state.isToggleOn ? selected_style : this.not_selected_style; - return
-
{svg_image}
+ this.current_style = this.state.isToggleOn || this.state.complexOn ? selected_style : this.not_selected_style; + return
+
{svg_image}
{this.props.data.protein_code}
- Complex ON

} - off={

Complex OFF

} - size="xs" - offstyle="danger" - active={this.state.complexOn}/> - Vector ON

} - off={

Vector OFF

} - size="xs" - offstyle="danger" - active={this.props.to_query==this.props.data.smiles}/> + + + Complex + Ligand + Vectors + +
} @@ -160,8 +195,13 @@ class MoleculeView extends GenericView { return colourList[this.props.data.id % colourList.length]; } - handleClick(e) { - this.setState(prevState => ({isToggleOn: !prevState.isToggleOn})) + handleClick(new_list=undefined) { + if(new_list!=undefined){ + this.setState(prevState => ({isToggleOn: !prevState.isToggleOn, value: new_list})); + } + else{ + this.setState(prevState => ({isToggleOn: !prevState.isToggleOn})) + } if(this.state.isToggleOn){ this.props.deleteObject(Object.assign({display_div: "major_view"}, this.generateMolObject())) this.props.removeFromFragmentDisplayList(this.generateMolId()) @@ -172,8 +212,13 @@ class MoleculeView extends GenericView { } } - onComplex() { - this.setState(prevState => ({complexOn: !prevState.complexOn})) + onComplex(new_list=undefined) { + if(new_list!=undefined) { + this.setState(prevState => ({complexOn: !prevState.complexOn, value: new_list})) + } + else{ + this.setState(prevState => ({complexOn: !prevState.complexOn})) + } if(this.state.complexOn){ this.props.deleteObject(Object.assign({display_div: "major_view"}, this.generateObject())) this.props.removeFromComplexList(this.generateMolId()) @@ -181,14 +226,16 @@ class MoleculeView extends GenericView { else{ this.props.loadObject(Object.assign({display_div: "major_view"}, this.generateObject())) this.props.appendComplexList(this.generateMolId()) - if(this.state.isToggleOn==false){ - this.handleClick() - } } } - onVector() { - this.setState(prevState => ({vectorOn: !prevState.vectorOn})) + onVector(new_list=undefined) { + if(new_list!=undefined) { + this.setState(prevState => ({vectorOn: !prevState.vectorOn, value: new_list})) + } + else{ + this.setState(prevState => ({vectorOn: !prevState.vectorOn})) + } if(this.state.vectorOn) { this.props.vector_list.forEach(item => this.props.deleteObject(Object.assign({display_div: "major_view"}, item))); this.props.setMol(""); diff --git a/js/containers/fraggleBoxHolder.js b/js/containers/fraggleBoxHolder.js index 5a0a228a5..f75248595 100644 --- a/js/containers/fraggleBoxHolder.js +++ b/js/containers/fraggleBoxHolder.js @@ -41,7 +41,6 @@ class FraggleBox extends Component { - diff --git a/js/containers/previewHolder.js b/js/containers/previewHolder.js index 0d2295971..350abfea7 100644 --- a/js/containers/previewHolder.js +++ b/js/containers/previewHolder.js @@ -119,7 +119,7 @@ class Preview extends Component { - + From f1bf2808794fda741311482a014a48507de1e774 Mon Sep 17 00:00:00 2001 From: Richard Gillams <37295433+ricgillams@users.noreply.github.com> Date: Mon, 17 Sep 2018 12:13:57 +0100 Subject: [PATCH 2/2] Bug Fix - compound loading and navigation (#20) - Compound list shows as loading during loading. - Fixed bug which caused navigation to end of compound list on rightClick after onClick action. - Cleaned up unused code. --- js/components/compoundList.js | 12 ++++++------ js/components/generalComponents.js | 2 +- js/components/header.js | 2 +- js/components/modalLoadingScreen.js | 1 - js/components/summaryView.js | 2 +- js/components/targetList.js | 2 +- js/configureStore.js | 2 +- js/containers/app.js | 3 +-- js/containers/fraggleBoxHolder.js | 2 +- js/containers/previewHolder.js | 2 +- js/utils/ngl_functions.js | 1 - js/utils/util.js | 24 +----------------------- 12 files changed, 15 insertions(+), 40 deletions(-) diff --git a/js/components/compoundList.js b/js/components/compoundList.js index cc6131fc7..8aacc310d 100644 --- a/js/components/compoundList.js +++ b/js/components/compoundList.js @@ -16,9 +16,8 @@ class CompoundList extends React.Component { this.handleClassNaming = this.handleClassNaming.bind(this); this.selectAll = this.selectAll.bind(this); this.clearAll = this.clearAll.bind(this); - this.highlightFirstCompound = this.highlightFirstCompound.bind(this) - this.colourClassBoxes = this.colourClassBoxes.bind(this) - + this.highlightFirstCompound = this.highlightFirstCompound.bind(this); + this.colourClassBoxes = this.colourClassBoxes.bind(this); } handleClassNaming(e){ @@ -28,7 +27,6 @@ class CompoundList extends React.Component { var classDescription = this.props.compoundClasses; var descriptionToSet = Object.assign(classDescription, newClassDescription); this.props.setCompoundClasses(descriptionToSet); - var newCurrentClass = e.target.id; this.props.setCurrentCompoundClass(e.target.id); } } @@ -93,14 +91,14 @@ class CompoundList extends React.Component { render() { var numMols = this.getNum(); - var mol_string = "No mols found!!!"; + var mol_string = "Loading..."; if(numMols){ mol_string = "Compounds to pick. Mol total: " + numMols } if(this.props.to_query=="" || this.props.to_query==undefined) { mol_string = "" } - if (this.props.currentVector != undefined) { + if (this.props.to_query != undefined) { var totArray = [] totArray.push() totArray.push() @@ -142,6 +140,8 @@ function mapStateToProps(state) { compoundClasses: state.selectionReducers.present.compoundClasses, currentCompoundClass: state.selectionReducers.present.currentCompoundClass, to_select: state.selectionReducers.present.to_select, + objectsInView: state.nglReducers.present.objectsInView, + querying: state.selectionReducers.present.querying, } } const mapDispatchToProps = { diff --git a/js/components/generalComponents.js b/js/components/generalComponents.js index f02827da6..e0c32d495 100644 --- a/js/components/generalComponents.js +++ b/js/components/generalComponents.js @@ -158,7 +158,7 @@ export class GenericView extends React.Component{ this.handleClick = this.handleClick.bind(this); this.not_selected_style = {width: props.width.toString+'px', height: props.height.toString()+'px'} this.old_url = '' - this.state = {isConfOn: false, isToggleOn: false, img_data: '' + + this.state = {isToggleOn: false, img_data: '' + '' + ' ' + ' ' + diff --git a/js/components/header.js b/js/components/header.js index 007711274..5a9ebc7a0 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -9,7 +9,7 @@ import * as apiActions from "../actions/apiActions"; import * as nglActions from "../actions/nglLoadActions"; import {connect} from "react-redux"; import * as nglObjectTypes from "../components/nglObjectTypes"; -import {withRouter, Link} from "react-router-dom"; +import {withRouter} from "react-router-dom"; class Header extends React.Component { diff --git a/js/components/modalLoadingScreen.js b/js/components/modalLoadingScreen.js index b06f7e03f..ed48edabe 100644 --- a/js/components/modalLoadingScreen.js +++ b/js/components/modalLoadingScreen.js @@ -5,7 +5,6 @@ import React from "react"; import {connect} from "react-redux"; import ReactModal from "react-modal"; -import {Button, Well, Col, Row} from "react-bootstrap"; const customStyles = { overlay : { diff --git a/js/components/summaryView.js b/js/components/summaryView.js index fe0ef2b76..8bd525b5e 100644 --- a/js/components/summaryView.js +++ b/js/components/summaryView.js @@ -209,7 +209,7 @@ class SummaryView extends React.Component{ var vector_counter = 0; for (var vector in to_buy_by_vect[mol]) { // TODO - something more meaningful for this name - var dock_name = f_name; + // var dock_name = f_name; var smiles = to_buy_by_vect[mol][vector]; var csvContent = "" smiles.forEach(function(smiles){ diff --git a/js/components/targetList.js b/js/components/targetList.js index dbd8d886c..1690e33fc 100644 --- a/js/components/targetList.js +++ b/js/components/targetList.js @@ -55,7 +55,7 @@ class TargetList extends GenericList { generateTargetObject(targetData) { // Now deal with this target var prot_to_load = window.location.protocol + "//" + window.location.host + targetData.template_protein - if(prot_to_load!=undefined) { + if(JSON.stringify(prot_to_load)!=JSON.stringify(undefined)) { var out_object = { "name": "PROTEIN_" + targetData.id.toString(), "prot_url": prot_to_load, diff --git a/js/configureStore.js b/js/configureStore.js index aad62e7df..5d88f6872 100644 --- a/js/configureStore.js +++ b/js/configureStore.js @@ -2,7 +2,7 @@ * Created by abradley on 07/03/2018. */ -import {commpose, createStore, applyMiddleware} from "redux"; +import {createStore, applyMiddleware} from "redux"; import thunkMiddleware from "redux-thunk"; import {createLogger} from "redux-logger"; import rootReducer from "./reducers/reducers"; diff --git a/js/containers/app.js b/js/containers/app.js index 7332c9755..1b32bd007 100644 --- a/js/containers/app.js +++ b/js/containers/app.js @@ -1,5 +1,4 @@ -import React, {Component} from "react"; -import {connect} from "react-redux"; +import React from "react"; import {Grid} from "react-bootstrap"; import Header from "../components/header"; import {MyMenu} from "../components/menuView"; diff --git a/js/containers/fraggleBoxHolder.js b/js/containers/fraggleBoxHolder.js index f75248595..b0137c0cc 100644 --- a/js/containers/fraggleBoxHolder.js +++ b/js/containers/fraggleBoxHolder.js @@ -12,7 +12,7 @@ import SummaryView from "../components/summaryView"; import CompoundList from '../components/compoundList'; import NGLView from "../components/nglComponents"; import NglViewerControls from "../components/nglViewerControls"; -import {Route, withRouter} from "react-router-dom"; +import {withRouter} from "react-router-dom"; import * as nglLoadActions from "../actions/nglLoadActions"; import ModalLoadingScreen from "../components/modalLoadingScreen"; import HotspotList from "../components/hotspotList"; diff --git a/js/containers/previewHolder.js b/js/containers/previewHolder.js index 350abfea7..cb5cf4c79 100644 --- a/js/containers/previewHolder.js +++ b/js/containers/previewHolder.js @@ -61,7 +61,7 @@ class Preview extends Component { this.props.setHighlighted(defaultSet) } else { - var indexToSet = Math.min(this.props.highlightedCompound["index"] + 1, this.props.this_vector_list[Object.keys(this.props.this_vector_list)].length - 1) + var indexToSet = Math.min(parseInt(this.props.highlightedCompound["index"]) + 1, this.props.this_vector_list[Object.keys(this.props.this_vector_list)].length - 1) this.props.setHighlighted({ index: indexToSet, smiles: this.props.this_vector_list[Object.keys(this.props.this_vector_list)][indexToSet] diff --git a/js/utils/ngl_functions.js b/js/utils/ngl_functions.js index 7901efd78..1d6cfc4f6 100644 --- a/js/utils/ngl_functions.js +++ b/js/utils/ngl_functions.js @@ -118,7 +118,6 @@ class NGLFunctions { display_view(response) { var res = JSON.parse(response); - var title = res.title; this.setJsonView(res.scene); } diff --git a/js/utils/util.js b/js/utils/util.js index 47633bbea..b308a002f 100644 --- a/js/utils/util.js +++ b/js/utils/util.js @@ -28,29 +28,7 @@ function inspect(obj) { console.log(typeof obj); } } -/** - * Utility to function to check if two arrays are the same - * @param a - * @param b - * @returns {boolean} - */ -function arraysEqual(a, b) { - if (a === b) { - return true; - } - if (a == null || b == null) { - return false; - } - if (a.length != b.length) { - return false; - } - for (var i = 0; i < a.length; i += 1) { - if (a[i] !== b[i]) { - return false; - } - } - return true; -} + export function shuffle(a) { for (let i = a.length - 1; i > 0; i -= 1) { const j = Math.floor(Math.random() * (i + 1));