Skip to content

Commit

Permalink
Merge 3772606 into 0406924
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonYCHuang committed Nov 14, 2016
2 parents 0406924 + 3772606 commit a52b39a
Show file tree
Hide file tree
Showing 17 changed files with 724 additions and 595 deletions.
230 changes: 220 additions & 10 deletions app/assets/javascripts/components/ElementDetails.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,237 @@
import React, {Component} from 'react';
import StickyDiv from 'react-stickydiv'
import {Tabs, Tab, Label} from 'react-bootstrap';
import SampleDetails from './SampleDetails';
import ReactionDetails from './ReactionDetails';
import WellplateDetails from './WellplateDetails';
import ScreenDetails from './ScreenDetails';
import ReportContainer from './report/ReportContainer';
import { SameEleTypId, UrlSilentNavigation } from './utils/ElementUtils';
import ElementActions from './actions/ElementActions';
import ElementStore from './stores/ElementStore';
import { ConfirmModal } from './common/ConfirmModal';

export default class ElementDetails extends Component {
render() {
const {currentElement} = this.props;
switch (currentElement.type) {
constructor(props) {
super(props);
this.state = {
selecteds: [],
offsetTop: 70,
fullScreen: false,
activeKey: 0,
deletingElement: null,
}
this.handleResize = this.handleResize.bind(this);
this.toggleFullScreen = this.toggleFullScreen.bind(this);
this.closeDetails = this.closeDetails.bind(this);
this.selectTab = this.selectTab.bind(this);
this.confirmDelete = this.confirmDelete.bind(this);
}

componentDidMount() {
window.addEventListener('resize', this.handleResize);
this.onChangeCurrentElement(null, this.props.currentElement);
}

componentWillReceiveProps(nextProps) {
const oriProps = this.props;
this.onChangeCurrentElement(oriProps.currentElement, nextProps.currentElement);
}

componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
this.setState({ selecteds: [] });
}

onChangeCurrentElement(oriEl, nextEl) {
const { selecteds } = this.state;
const index = this.elementIndex(selecteds, nextEl);
let activeKey = index;
let newSelecteds = null;
if(!oriEl || index === -1) {
activeKey = selecteds.length;
newSelecteds = this.addElement(nextEl);
} else {
newSelecteds = this.updateElement(nextEl, index);
}
this.setState({ selecteds: newSelecteds });
this.resetActiveKey(activeKey);
}

addElement(addEl) {
const { selecteds } = this.state;
return [...selecteds, addEl];
}

updateElement(updateEl, index) {
const { selecteds } = this.state;
return [ ...selecteds.slice(0, index),
updateEl,
...selecteds.slice(index + 1) ];
}

deleteElement(deleteEl) {
const { selecteds } = this.state;
return selecteds.map( s => {
const isSame = SameEleTypId(s, deleteEl);
return isSame ? null : s;
}).filter(r => r != null);
}

elementIndex(selecteds, newSelected) {
let index = -1;
selecteds.forEach( (s, i) => {
const isSame = SameEleTypId(s, newSelected);
if(isSame) { index = i; }
});
return index;
}

resetCurrentElement(newKey, newSelecteds) {
const newCurrentElement = newKey < 0 ? newSelecteds[0] : newSelecteds[newKey];
if(newSelecteds.length === 0) {
ElementActions.deselectCurrentElement();
} else {
ElementActions.setCurrentElement(newCurrentElement);
}
UrlSilentNavigation(newCurrentElement);
}

deleteCurrentElement(deleteEl) {
const newSelecteds = this.deleteElement(deleteEl);
const left = this.state.activeKey - 1;
this.setState(
{ selecteds: newSelecteds },
this.resetCurrentElement.bind(this, left, newSelecteds)
);
}

isDeletable(deleteEl) {
return deleteEl.isPendingToSave ? false : true;
}

closeDetails(deleteEl, force = false) {
const isDeletable = this.isDeletable(deleteEl);
if(force || isDeletable) {
this.deleteCurrentElement(deleteEl);
} else {
this.setState({ deletingElement: deleteEl });
}
}

confirmDelete(confirm) {
const deleteEl = this.state.deletingElement;
if(confirm) {
this.deleteCurrentElement(deleteEl);
}
this.setState({ deletingElement: null });
}

confirmDeleteContent() {
return (
<div>
<p>If you select Yes, you will lose the unsaved data.</p>
<p>Are you sure to close it?</p>
</div>
);
}

selectTab(index) {
this.resetCurrentElement(index, this.state.selecteds);
}

resetActiveKey(activeKey) {
setTimeout(this.setState.bind(this, { activeKey }), 300);
}

toggleFullScreen() {
const { fullScreen } = this.state;
this.setState({ fullScreen: !fullScreen });
}

handleResize(e = null) {
let windowHeight = window.innerHeight || 1;
if (this.state.fullScreen || windowHeight < 500) {
this.setState({offsetTop: 0});
} else {this.setState( {offsetTop: 70}) }
}

content(el) {
switch (el.type) {
case 'sample':
return <SampleDetails sample={currentElement}/>;
return <SampleDetails sample={el}
closeDetails={this.closeDetails}
toggleFullScreen={this.toggleFullScreen}/>;
case 'reaction':
return <ReactionDetails reaction={currentElement}/>;
return <ReactionDetails reaction={el}
closeDetails={this.closeDetails}
toggleFullScreen={this.toggleFullScreen}/>;
case 'wellplate':
return <WellplateDetails wellplate={currentElement}/>;
return <WellplateDetails wellplate={el}
closeDetails={this.closeDetails}
toggleFullScreen={this.toggleFullScreen}/>;
case 'screen':
return <ScreenDetails screen={currentElement}/>;
case 'report':
return <ReportContainer />;
return <ScreenDetails screen={el}
closeDetails={this.closeDetails}
toggleFullScreen={this.toggleFullScreen}/>;
}
}

category(type) {
const { elements } = ElementStore.getState();
if(!elements) { return null; }
switch (type) {
case 'sample':
let samples = [];
elements.samples.elements.forEach( e => samples = [...samples, ...e]);
return samples;
case 'reaction':
return elements.reactions.elements;
case 'wellplate':
return elements.wellplates.elements;
case 'screen':
return elements.screens.elements;
default:
return null;
}
}

tabTitle(el, elKey) {
const bsStyle = el.isPendingToSave ? 'info' : 'primary';
const focusing = elKey === this.state.activeKey;
const icon = focusing
? <i className={`icon-${el.type}`}/>
: <Label bsStyle={bsStyle}>
<i className={`icon-${el.type}`}/>
</Label>
return <div>{icon} &nbsp; {el.title()} </div>
}

render() {
const { fullScreen, selecteds, activeKey, offsetTop, deletingElement } = this.state;
const fScrnClass = fullScreen ? "full-screen" : "";

return(
<div className={fScrnClass}>
<StickyDiv zIndex={2} offsetTop={offsetTop}>
<Tabs activeKey={activeKey} onSelect={this.selectTab} id="elements-tabs" >
{selecteds.map( (el, i) => {
return el
? <Tab eventKey={i} title={this.tabTitle(el, i)} unmountOnExit={true} >
{this.content(el)}
</Tab>
: null;
})}
</Tabs>
</StickyDiv>
<ConfirmModal showModal={deletingElement !== null}
title="Confirm Delete"
content={this.confirmDeleteContent()}
onClick={this.confirmDelete} />
</div>
)
}
}

ElementDetails.propTypes = {
currentElement: React.PropTypes.object,
}
21 changes: 15 additions & 6 deletions app/assets/javascripts/components/Elements.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import HTML5Backend from 'react-dnd-html5-backend';
import List from './List';
import ElementDetails from './ElementDetails';
import ElementStore from './stores/ElementStore';
import ReportContainer from './report/ReportContainer';

class Elements extends Component {
constructor(props) {
super(props);
this.state = {
currentElement: null
currentElement: null,
};
this.handleOnChange = this.handleOnChange.bind(this)
}
Expand All @@ -25,21 +26,29 @@ class Elements extends Component {
}

handleOnChange(state) {
const {currentElement} = state;
this.setState({currentElement});
const { currentElement } = state;
this.setState({ currentElement });
}

rightHalfPage(showReport, currentElement) {
return (
showReport
? <ReportContainer />
: <ElementDetails currentElement={currentElement} />
);
}

render() {
const {currentElement} = this.state;
const showReport = currentElement && currentElement.type === 'report' ? true : false
const { currentElement } = this.state;
const showReport = currentElement && currentElement.type === 'report' ? true : false;
if (currentElement) {
return (
<div>
<Col md={4}>
<List overview={false} showReport={showReport}/>
</Col>
<Col md={8}>
<ElementDetails currentElement={currentElement}/>
{this.rightHalfPage(showReport, currentElement)}
</Col>
</div>
)
Expand Down
3 changes: 3 additions & 0 deletions app/assets/javascripts/components/Material.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import DragDropItemTypes from './DragDropItemTypes';
import NumeralInputWithUnitsCompo from './NumeralInputWithUnitsCompo';
import SampleName from './common/SampleName'
import ElementActions from './actions/ElementActions'
import { UrlSilentNavigation } from './utils/ElementUtils';

const source = {
beginDrag(props) {
Expand All @@ -20,6 +21,8 @@ const collect = (connect, monitor) => ({
class Material extends Component {
handleMaterialClick(sample) {
let { reaction } = this.props;
UrlSilentNavigation(sample);
sample.updateChecksum();
ElementActions.showReactionMaterial({ sample: sample, reaction: reaction })
}

Expand Down
Loading

0 comments on commit a52b39a

Please sign in to comment.