Commit 9c922d3b authored by hh1966's avatar hh1966
Browse files

Add add and delete fields to research plan detail

parent a477e61a
Pipeline #50337 canceled with stage
......@@ -26,7 +26,6 @@ import LoadingActions from './actions/LoadingActions';
import ResearchPlanDetailsNameField from './research_plan/ResearchPlanDetailsNameField';
import ResearchPlanDetailsBody from './research_plan/ResearchPlanDetailsBody';
const editorTooltip = exts => <Tooltip id="editor_tooltip">Available extensions: {exts}</Tooltip>;
const downloadTooltip = <Tooltip id="download_tooltip">Download attachment</Tooltip>;
......@@ -363,10 +362,12 @@ export default class ResearchPlanDetails extends Component {
});
}
handleBodyChange(value, index) {
handleBodyChange(value, id) {
let {research_plan} = this.state
research_plan.changed = true
let index = research_plan.body.findIndex(field => field.id == id)
research_plan.body[index].value = value
research_plan.changed = true
this.setState({
research_plan: research_plan
......@@ -377,6 +378,30 @@ export default class ResearchPlanDetails extends Component {
let {research_plan} = this.state
research_plan.body.splice(target, 0, research_plan.body.splice(source, 1)[0]);
research_plan.changed = true
this.setState({
research_plan: research_plan
});
}
handleBodyAdd(type) {
let {research_plan} = this.state
research_plan.addBodyField(type)
research_plan.changed = true
this.setState({
research_plan: research_plan
});
}
handleBodyDelete(id) {
let {research_plan} = this.state
let index = research_plan.body.findIndex(field => field.id == id)
research_plan.body.splice(index, 1)
research_plan.changed = true
this.setState({
research_plan: research_plan
......@@ -394,7 +419,9 @@ export default class ResearchPlanDetails extends Component {
onChange={this.handleNameChange.bind(this)} />
<ResearchPlanDetailsBody body={body} disabled={research_plan.isMethodDisabled('body')}
onChange={this.handleBodyChange.bind(this)}
onDrop={this.handleBodyDrop.bind(this)} />
onDrop={this.handleBodyDrop.bind(this)}
onAdd={this.handleBodyAdd.bind(this)}
onDelete={this.handleBodyDelete.bind(this)} />
<Row>
<Col md={12}>
<FormGroup>
......
......@@ -10,22 +10,7 @@ export default class ResearchPlan extends Element {
collection_id: collection_id,
type: 'research_plan',
name: 'New Research Plan',
body: [
{
id: uuidv4(),
type: 'ketcher',
value: {
svg_file: null,
svg_file: null,
thumb_svg: null
}
},
{
id: uuidv4(),
type: 'richtext',
value: null
}
]
body: []
});
}
......@@ -38,15 +23,46 @@ export default class ResearchPlan extends Element {
}
get svgPath() {
if (this.svg_file){
return `/images/research_plans/${this.svg_file}`;
} else {
return `/images/wild_card/no_image_180.svg`
for (var i = 0; i < this.body.length; i++) {
if (this.body[i].type == 'ketcher') {
return `/images/research_plans/${this.body[i].value.svg_file}`
} else if (this.body[i].type == 'image') {
}
}
return `/images/wild_card/no_image_180.svg`
}
// overwrite isPendingToSave method in models/Element.js
get isPendingToSave() {
return !isEmpty(this) && (this.isNew || this.changed);
}
addBodyField(type) {
switch (type) {
case 'richtext':
this.body.push({
id: uuidv4(),
type: 'richtext',
value: null
})
break;
case 'ketcher':
this.body.push({
id: uuidv4(),
type: 'ketcher',
value: {
svg_file: null,
svg_file: null,
thumb_svg: null
}
})
break;
case 'table':
break;
case 'image':
break;
}
}
}
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Button } from 'react-bootstrap'
export default class ResearchPlanDetailsAddField extends Component {
render() {
let { 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>
</div>
)
}
}
ResearchPlanDetailsAddField.propTypes = {
onAdd: PropTypes.func,
}
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Row } from 'react-bootstrap';
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { ControlLabel, Row, Col } from 'react-bootstrap'
import Field from './ResearchPlanDetailsField';
import ResearchPlanDetailsAddField from './ResearchPlanDetailsAddField'
import ResearchPlanDetailsDropTarget from './ResearchPlanDetailsDropTarget'
import Field from './ResearchPlanDetailsField'
export default class ResearchPlanDetailsBody extends Component {
constructor(props) {
super(props)
const { body, disabled, onChange, onDrop } = props
this.state = {
body,
disabled,
onChange,
onDrop
}
}
render() {
let { body, disabled, onChange, onDrop } = this.state
let { body, disabled, onChange, onDrop, onAdd, onDelete } = this.props
let fields = body.map((field, index) => {
return <Field key={field.id}
field={field} index={index} disabled={disabled}
onChange={onChange.bind(this)}
onDrop={onDrop.bind(this)} />
onDrop={onDrop.bind(this)}
onDelete={onDelete.bind(this)} />
})
return (
<Row className="research-plan-details-body">
<div className="research-plan-details-body">
<ControlLabel>Body</ControlLabel>
{fields}
</Row>
<Row>
<Col md={12}>
<div className="research-plan-details-body-footer">
<ResearchPlanDetailsAddField onAdd={onAdd}/>
<ResearchPlanDetailsDropTarget index={fields.length}/>
</div>
</Col>
</Row>
</div>
)
}
}
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { DragSource } from 'react-dnd';
import DragDropItemTypes from '../DragDropItemTypes';
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { DragSource } from 'react-dnd'
import DragDropItemTypes from '../DragDropItemTypes'
const spec = {
beginDrag(props) {
......@@ -11,7 +11,9 @@ const spec = {
},
endDrag(props, monitor) {
let target = monitor.getDropResult()
props.onDrop(props.index, target.index)
if (target) {
props.onDrop(props.index, target.index)
}
}
};
......@@ -21,11 +23,13 @@ const collect = (connect, monitor) => ({
});
class ResearchPlanDetailsDragSource extends Component {
render() {
const { connectDragSource, index } = this.props
return connectDragSource(<span className="fa fa-arrows dnd-arrow-enable text-info drag-source" />)
return connectDragSource(<span className="fa fa-lg fa-arrows text-info drag-source" />)
}
};
export default DragSource(DragDropItemTypes.RESEARCH_PLAN_FIELD, spec, collect)(ResearchPlanDetailsDragSource)
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { DropTarget } from 'react-dnd';
import DragDropItemTypes from '../DragDropItemTypes';
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { DropTarget } from 'react-dnd'
import DragDropItemTypes from '../DragDropItemTypes'
const spec = {
drop(props) {
......@@ -21,7 +21,7 @@ const collect = (connect, monitor) => ({
class ResearchPlanDetailsDropTarget extends Component {
render() {
const {index, connectDropTarget, isOver, canDrop} = this.props;
const {index, connectDropTarget, isOver, canDrop} = this.props
let className = 'drop-target'
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormGroup, Col } from 'react-bootstrap';
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { FormGroup, Button, Row, Col } from 'react-bootstrap'
import ResearchPlanDetailsDragSource from './ResearchPlanDetailsDragSource'
import ResearchPlanDetailsDropTarget from './ResearchPlanDetailsDropTarget';
import RichTextField from './ResearchPlanDetailsRichTextField';
import KetcherField from './ResearchPlanDetailsKetcherField';
import ResearchPlanDetailsDropTarget from './ResearchPlanDetailsDropTarget'
import RichTextField from './ResearchPlanDetailsRichTextField'
import KetcherField from './ResearchPlanDetailsKetcherField'
export default class ResearchPlanDetailsField extends Component {
render() {
let { field, index, disabled, onChange, onDrop } = this.props
let { field, index, disabled, onChange, onDrop, onDelete } = this.props
let field_component
switch (field.type) {
......@@ -27,13 +27,24 @@ export default class ResearchPlanDetailsField extends Component {
}
return (
<Col md={12}>
<ResearchPlanDetailsDragSource index={index} onDrop={onDrop.bind(this)}/>
<ResearchPlanDetailsDropTarget index={index}/>
<FormGroup>
{field_component}
</FormGroup>
</Col>
<Row>
<Col md={12}>
<div className="research-plan-details-body-seperator">
<Button bsStyle="danger" bsSize="xsmall" onClick={() => onDelete(field.id)} >
<i className="fa fa-times"></i>
</Button>
<ResearchPlanDetailsDragSource index={index} onDrop={onDrop.bind(this)}/>
<ResearchPlanDetailsDropTarget index={index}/>
</div>
</Col>
<Col md={12}>
<div className="research-plan-details-body-field">
<FormGroup>
{field_component}
</FormGroup>
</div>
</Col>
</Row>
)
}
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Glyphicon } from 'react-bootstrap';
import SVG from 'react-inlinesvg';
import { includes, last, findKey, values } from 'lodash';
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Glyphicon } from 'react-bootstrap'
import SVG from 'react-inlinesvg'
import { includes, last, findKey, values } from 'lodash'
import ResearchPlansFetcher from '../fetchers/ResearchPlansFetcher';
import StructureEditorModal from '../structure_editor/StructureEditorModal';
import QuillEditor from '../QuillEditor';
import ResearchPlansFetcher from '../fetchers/ResearchPlansFetcher'
import StructureEditorModal from '../structure_editor/StructureEditorModal'
import QuillEditor from '../QuillEditor'
export default class ResearchPlanDetailsKetcherField extends Component {
......@@ -55,7 +55,7 @@ export default class ResearchPlanDetailsKetcherField extends Component {
field: field,
loadingMolecule: false
});
onChange(field.value, index)
onChange(field.value, field.id)
this.hideStructureEditor();
});
}
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { ControlLabel, FormControl, FormGroup, Row, Col } from 'react-bootstrap';
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { ControlLabel, FormControl, FormGroup, Row, Col } from 'react-bootstrap'
export default class ResearchPlanDetailsNameField extends Component {
constructor(props) {
super(props)
const { value, disabled, onChange } = props
this.state = {
value,
disabled,
onChange
}
}
handleChange(event) {
let { value, onChange } = this.state
value = event.target.value
this.setState({
value: value
});
onChange(value)
}
render() {
let { value, disabled } = this.state
let { value, disabled, onChange } = this.props
return (
<Row>
......@@ -37,7 +15,7 @@ export default class ResearchPlanDetailsNameField extends Component {
<FormControl
type="text"
value={value || ''}
onChange={this.handleChange.bind(this)}
onChange={(event) => onChange(event.target.value)}
disabled={disabled}
/>
</FormGroup>
......@@ -45,6 +23,7 @@ export default class ResearchPlanDetailsNameField extends Component {
</Row>
)
}
}
ResearchPlanDetailsNameField.propTypes = {
......
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import QuillEditor from '../QuillEditor';
import QuillEditor from '../QuillEditor'
export default class ResearchPlanDetailsRichTextField extends Component {
constructor(props) {
super(props)
const { field, index, disabled, onChange } = props
this.state = {
field,
index,
disabled,
onChange
}
}
handleChange(event) {
let { field, index, onChange } = this.state
field.value = event
this.setState({
field: field
});
onChange(field.value, index)
}
render() {
let { field, disabled } = this.state
let { field, index, disabled, onChange } = this.props
return (
<QuillEditor value={field.value}
onChange={this.handleChange.bind(this)}
onChange={(value) => onChange(value, field.id)}
disabled={disabled}
/>
)
}
}
ResearchPlanDetailsRichTextField.propTypes = {
......
.research-plan-details-body {
.form-group {
margin-bottom: 20px;
.research-plan-details-body-seperator,
.research-plan-details-body-footer {
height: 40px;
position: relative;
margin-bottom: 0;
}
.drag-source {
float: right;
margin-top: 10px;
margin-bottom: 6px;
.research-plan-details-body-seperator {
button {
float: right;
margin-top: 10px;
}
.drag-source {
float: right;
margin-top: 14px;
margin-right: 5px;
}
.drop-target {
left: 0;
right: 50px;
}
}
.research-plan-details-body-footer {
.drop-target {
left: 280px;
right: 0;
}
}
.form-group {
margin-bottom: 0;
}
.drop-target {
position: absolute;
height: 40px;
padding-top: 10px;
.indicator {
height: 24px;
margin-right: 35px;
height: 13px;
}
&.can-drop {
......@@ -31,4 +58,15 @@
}
}
}
.add-field {
float: left;
margin-top: 10px;
button {
height: 30px;
width: 60px;
margin-right: 10px;
}
}
}
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