Commit 96295931 authored by hh1966's avatar hh1966
Browse files

Add sample field to research plan detail

parent 7308272b
......@@ -47,7 +47,7 @@ const showDetails = (id) => {
};
const targets = {
sample: ['reaction', 'wellplate', 'device'],
sample: ['reaction', 'wellplate', 'device', 'research_plan'],
molecule: ['reaction'],
};
......
......@@ -26,7 +26,7 @@ export default class ResearchPlanDetails extends Component {
const { research_plan } = props;
this.state = {
research_plan,
edit: false,
edit: true,
update: false
};
}
......
......@@ -5,22 +5,25 @@ import { Button } from 'react-bootstrap'
export default class ResearchPlanDetailsAddField extends Component {
render() {
let { onAdd } = this.props
const { onAdd } = this.props
return (
<div className="add-field">
<Button bsStyle="primary" bsSize="small" onClick={() => onAdd('richtext')} >
<i className="fa fa-file-text-o"></i>&nbsp;<i className="fa fa-plus"></i>
</Button>
<Button bsStyle="primary" bsSize="small" onClick={() => onAdd('ketcher')} >
<i className="fa fa-flask"></i>&nbsp;<i className="fa fa-plus"></i>
</Button>
<Button bsStyle="primary" bsSize="small" onClick={() => onAdd('table')} >
<i className="fa fa-table"></i>&nbsp;<i className="fa fa-plus"></i>
</Button>
<Button bsStyle="primary" bsSize="small" onClick={() => onAdd('image')} >
<i className="fa fa-picture-o"></i>&nbsp;<i className="fa fa-plus"></i>
</Button>
<Button bsStyle="primary" bsSize="small" onClick={() => onAdd('ketcher')} >
<i className="fa fa-flask"></i>&nbsp;<i className="fa fa-plus"></i>
</Button>
<Button bsStyle="primary" bsSize="small" onClick={() => onAdd('sample')} >
<i className="icon-sample"></i>&nbsp;<i className="fa fa-plus"></i>
</Button>
</div>
)
}
......
......@@ -21,30 +21,31 @@ export default class ResearchPlanDetailsBody extends Component {
edit={edit} />
})
let className = 'research-plan-details-static'
let bodyFooter
if (edit) {
return (
<div className="research-plan-details-body">
{fields}
<Row>
<Col md={12}>
<ResearchPlanDetailsDropTarget index={fields.length}/>
className = 'research-plan-details-body'
bodyFooter = (
<Row>
<Col md={12}>
<ResearchPlanDetailsDropTarget index={fields.length}/>
<div>
<ControlLabel>Add field</ControlLabel>
<div>
<ControlLabel>Add field</ControlLabel>
<div>
<ResearchPlanDetailsAddField onAdd={onAdd}/>
</div>
<ResearchPlanDetailsAddField onAdd={onAdd}/>
</div>
</Col>
</Row>
</div>
)
} else {
return (
<div className="research-plan-details-static">
{fields}
</div>
</div>
</Col>
</Row>
)
}
return (
<div className={className}>
{fields}
{bodyFooter}
</div>
)
}
}
......
......@@ -23,7 +23,7 @@ class ResearchPlanDetailsDropTarget extends Component {
render() {
const {index, connectDropTarget, isOver, canDrop} = this.props
let className = 'drop-target'
let className = 'field-drop-target'
if (isOver) {
className += ' is-over'
......
......@@ -9,6 +9,7 @@ import ResearchPlanDetailsFieldRichText from './ResearchPlanDetailsFieldRichText
import ResearchPlanDetailsFieldKetcher from './ResearchPlanDetailsFieldKetcher'
import ResearchPlanDetailsFieldImage from './ResearchPlanDetailsFieldImage'
import ResearchPlanDetailsFieldTable from './ResearchPlanDetailsFieldTable'
import ResearchPlanDetailsFieldSample from './ResearchPlanDetailsFieldSample'
export default class ResearchPlanDetailsField extends Component {
......@@ -41,36 +42,44 @@ export default class ResearchPlanDetailsField extends Component {
field={field} index={index} disabled={disabled}
onChange={onChange.bind(this)} update={update} edit={edit} />
break;
case 'sample':
label = 'Sample'
component = <ResearchPlanDetailsFieldSample key={field.id}
field={field} index={index} disabled={disabled}
onChange={onChange.bind(this)} edit={edit} />
break;
}
let dropTarget, fieldHeader
if (edit) {
return (
<Row>
<Col md={12}>
<ResearchPlanDetailsDropTarget index={index}/>
</Col>
<Col md={12}>
<div className="field">
<Button className="pull-right" bsStyle="danger" bsSize="xsmall"
onClick={() => onDelete(field.id)} >
<i className="fa fa-times"></i>
</Button>
<ResearchPlanDetailsDragSource index={index} onDrop={onDrop.bind(this)}/>
<ControlLabel>{label}</ControlLabel>
{component}
</div>
</Col>
</Row>
dropTarget = (
<Col md={12}>
<ResearchPlanDetailsDropTarget index={index}/>
</Col>
)
} else {
return (
<Row>
<Col md={12}>
{component}
</Col>
</Row>
fieldHeader = (
<div className="field-header">
<Button className="pull-right" bsStyle="danger" bsSize="xsmall"
onClick={() => onDelete(field.id)} >
<i className="fa fa-times"></i>
</Button>
<ResearchPlanDetailsDragSource index={index} onDrop={onDrop.bind(this)}/>
<ControlLabel>{label}</ControlLabel>
</div>
)
}
return (
<Row>
{dropTarget}
<Col md={12}>
<div className="field">
{fieldHeader}
{component}
</div>
</Col>
</Row>
)
}
}
......
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { DropTarget } from 'react-dnd'
import DragDropItemTypes from '../DragDropItemTypes'
import { Row, Col, Button } from 'react-bootstrap'
import SVG from 'react-inlinesvg';
import ElementActions from '../actions/ElementActions';
import { UrlSilentNavigation } from '../utils/ElementUtils';
import PubchemLcss from '../PubchemLcss';
import SampleName from '../common/SampleName'
import SamplesFetcher from '../fetchers/SamplesFetcher'
const MWPrecision = 6;
const spec = {
drop(props, monitor) {
const { field, onChange } = props
const sample = monitor.getItem().element
onChange({ sample_id: sample.id }, field.id)
}
}
const collect = (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop()
})
class ResearchPlanDetailsFieldSample extends Component {
constructor(props) {
super(props);
this.state = {
idle: true,
sample: {
id: null
}
}
}
componentDidUpdate() {
const { field } = this.props
const { idle, sample } = this.state
if (idle && field.value.sample_id !== sample.id) {
this.setState({ idle: false }, this.fetch)
}
}
fetch() {
const { field } = this.props
SamplesFetcher.fetchById(field.value.sample_id).then(sample => {
this.setState({ idle: true, sample:sample })
})
}
// copied from SampleDetails.js
sampleAverageMW(sample) {
let mw = sample.molecule_molecular_weight;
if(mw)
return `${mw.toFixed(MWPrecision)} g/mol`;
else
return '';
}
// copied from SampleDetails.js
sampleExactMW(sample) {
let mw = sample.molecule_exact_molecular_weight
if(mw)
return `Exact mass: ${mw.toFixed(MWPrecision)} g/mol`;
else
return '';
}
// modified from SampleDetails.js
sampleInfo(sample) {
const style = { height: '200px' };
const pubchemLcss = sample.pubchem_tag && sample.pubchem_tag.pubchem_lcss ?
sample.pubchem_tag.pubchem_lcss.Record.Section[0].Section[0].Section[0].Information : null;
const pubchemCid = sample.pubchem_tag && sample.pubchem_tag.pubchem_cid ?
sample.pubchem_tag.pubchem_cid : 0;
const lcssSign = pubchemLcss ?
<PubchemLcss cid={pubchemCid} informArray={pubchemLcss} /> : <div />;
let svgPath = sample.svgPath
let svgClassName = svgPath ? 'svg-container' : 'svg-container-empty'
return (
<Row style={style}>
<Col md={4}>
<h4><SampleName sample={sample}/></h4>
<h5>{this.sampleAverageMW(sample)}</h5>
<h5>{this.sampleExactMW(sample)}</h5>
{lcssSign}
<p>
Sample: <a role="link" tabIndex={0} onClick={() => this.handleSampleClick()} style={{ cursor: 'pointer' }}>
{sample.title()}
</a>
</p>
</Col>
<Col md={8}>
<div>
<SVG src={svgPath} className="molecule-mid"/>
</div>
</Col>
</Row>
)
}
handleSampleClick() {
const { sample } = this.state;
UrlSilentNavigation(sample);
ElementActions.showReactionMaterial({ sample });
}
renderSample() {
const { sample } = this.state
}
renderEdit() {
const { field, index, connectDropTarget, isOver, canDrop } = this.props
const { sample } = this.state
let className = 'drop-target'
if (isOver) className += ' is-over'
if (canDrop) className += ' can-drop'
let content = 'Drop Sample here.'
if (sample.id !== null) {
content = this.sampleInfo(sample)
}
return connectDropTarget(
<div className={className}>
{content}
</div>
)
}
renderStatic() {
const { field } = this.props
const { sample } = this.state
let content = 'No sample.'
if (sample.id !== null) {
content = this.sampleInfo(sample)
}
return content
}
render() {
if (this.props.edit) {
return this.renderEdit()
} else {
return this.renderStatic()
}
}
}
ResearchPlanDetailsFieldSample.propTypes = {
field: PropTypes.object,
index: PropTypes.number,
disabled: PropTypes.bool,
onChange: PropTypes.func,
}
export default DropTarget([DragDropItemTypes.SAMPLE, DragDropItemTypes.MOLECULE, DragDropItemTypes.MATERIAL], spec, collect)(ResearchPlanDetailsFieldSample);
......@@ -16,7 +16,7 @@
margin-bottom: 0;
}
.drop-target {
.field-drop-target {
height: 20px;
.indicator {
......@@ -79,6 +79,17 @@
width: 100%;
}
}
.drop-target {
min-height: 50px;
width: 100%;
border: 3px dashed lightgray;
padding: 10px;
&.is-over {
border: 3px solid lightgray;
}
}
}
.research-plan-details-static {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment