В первом приближении заинтегрировался с беком

This commit is contained in:
SleepWalker
2016-02-13 17:28:47 +02:00
parent 19eec8f7a4
commit a94ddaf131
29 changed files with 1171 additions and 492 deletions

View File

@@ -1,48 +1,73 @@
import React, { Component } from 'react';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { routeActions } from 'react-router-redux';
import { TransitionMotion, spring } from 'react-motion';
import ReactHeight from 'react-height';
import { Panel, PanelBody, PanelFooter, PanelHeader } from 'components/ui/Panel';
import { Form } from 'components/ui/Form';
import {helpLinks as helpLinksStyles} from 'components/auth/helpLinks.scss';
import panelStyles from 'components/ui/panel.scss';
import icons from 'components/ui/icons.scss';
import * as actions from './actions';
const opacitySpringConfig = [300, 20];
const transformSpringConfig = [500, 50];
const changeContextSpringConfig = [500, 20];
export default class PanelTransition extends Component {
class PanelTransition extends Component {
static displayName = 'PanelTransition';
static propTypes = {
auth: PropTypes.shape({
error: PropTypes.string,
login: PropTypes.shape({
login: PropTypes.string,
password: PropTypes.string
})
}).isRequired,
goBack: React.PropTypes.func.isRequired,
setError: React.PropTypes.func.isRequired,
clearErrors: React.PropTypes.func.isRequired,
path: PropTypes.string.isRequired,
Title: PropTypes.element.isRequired,
Body: PropTypes.element.isRequired,
Footer: PropTypes.element.isRequired,
Links: PropTypes.element.isRequired
};
state = {
height: {},
contextHeight: 0
};
componentWillReceiveProps(nextProps) {
var previousRoute = this.props.location;
var nextPath = nextProps.path;
var previousPath = this.props.path;
var next = nextProps.path;
var prev = previousRoute && previousRoute.pathname;
if (nextPath !== previousPath) {
var direction = this.getDirection(nextPath, previousPath);
var forceHeight = direction === 'Y' && nextPath !== previousPath ? 1 : 0;
var direction = this.getDirection(next, next, prev);
var forceHeight = direction === 'Y' && next !== prev ? 1 : 0;
this.props.clearErrors();
this.setState({
direction,
forceHeight,
previousPath
});
this.setState({
direction,
forceHeight,
previousRoute
});
if (forceHeight) {
setTimeout(() => {
this.setState({forceHeight: 0});
}, 100);
if (forceHeight) {
setTimeout(() => {
this.setState({forceHeight: 0});
}, 100);
}
}
}
render() {
var {previousRoute, height, contextHeight, forceHeight} = this.state;
const {height, canAnimateHeight, contextHeight, forceHeight} = this.state;
const {path, Title, Body, Footer, Links} = this.props;
@@ -54,7 +79,7 @@ export default class PanelTransition extends Component {
Body,
Footer,
Links,
hasBackButton: previousRoute && previousRoute.pathname === Title.type.goBack,
hasBackButton: Title.type.goBack,
transformSpring: spring(0, transformSpringConfig),
opacitySpring: spring(1, opacitySpringConfig)
},
@@ -67,24 +92,28 @@ export default class PanelTransition extends Component {
willLeave={this.willLeave}
>
{(items) => {
var keys = Object.keys(items).filter((key) => key !== 'common');
const keys = Object.keys(items).filter((key) => key !== 'common');
const contentHeight = {
overflow: 'hidden',
height: forceHeight ? items.common.switchContextHeightSpring : 'auto'
};
const bodyHeight = {
position: 'relative',
height: `${canAnimateHeight ? items.common.heightSpring : height[path]}px`
};
return (
<div>
<Form id={path} onSubmit={this.onFormSubmit} onInvalid={this.onFormInvalid}>
<Panel>
<PanelHeader>
{keys.map((key) => this.getHeader(key, items[key]))}
</PanelHeader>
<div style={{
overflow: 'hidden',
height: forceHeight ? items.common.switchContextHeightSpring : 'auto'
}}>
<ReactHeight onHeightReady={this.updateContextHeight}>
<div style={contentHeight}>
<ReactHeight onHeightReady={this.onUpdateContextHeight}>
<PanelBody>
<div style={{
position: 'relative',
height: `${previousRoute ? items.common.heightSpring : height[path]}px`
}}>
<div style={bodyHeight}>
{keys.map((key) => this.getBody(key, items[key]))}
</div>
</PanelBody>
@@ -97,21 +126,24 @@ export default class PanelTransition extends Component {
<div className={helpLinksStyles}>
{keys.map((key) => this.getLinks(key, items[key]))}
</div>
</div>
</Form>
);
}}
</TransitionMotion>
);
}
willEnter = (key, styles) => {
return this.getTransitionStyles(key, styles);
onFormSubmit = () => {
this.body.onFormSubmit();
};
willLeave = (key, styles) => {
return this.getTransitionStyles(key, styles, {isLeave: true});
onFormInvalid = (errorMessage) => {
this.props.setError(errorMessage);
};
willEnter = (key, styles) => this.getTransitionStyles(key, styles);
willLeave = (key, styles) => this.getTransitionStyles(key, styles, {isLeave: true});
/**
* @param {string} key
* @param {Object} styles
@@ -140,8 +172,11 @@ export default class PanelTransition extends Component {
};
}
updateHeight = (height) => {
onUpdateHeight = (height) => {
const canAnimateHeight = Object.keys(this.state.height).length > 1 || this.state.height[[this.props.path]];
this.setState({
canAnimateHeight,
height: {
...this.state.height,
[this.props.path]: height
@@ -149,7 +184,7 @@ export default class PanelTransition extends Component {
});
};
updateContextHeight = (height) => {
onUpdateContextHeight = (height) => {
this.setState({
contextHeight: height
});
@@ -158,10 +193,11 @@ export default class PanelTransition extends Component {
onGoBack = (event) => {
event.preventDefault();
this.props.history.goBack();
this.body.onGoBack && this.body.onGoBack();
this.props.goBack();
};
getDirection(key, next, prev) {
getDirection(next, prev) {
var not = (path) => prev !== path && next !== path;
var map = {
@@ -172,7 +208,7 @@ export default class PanelTransition extends Component {
'/oauth/permissions': 'Y'
};
return map[key];
return map[next];
}
getHeader(key, props) {
@@ -192,7 +228,7 @@ export default class PanelTransition extends Component {
};
var backButton = (
<button style={sideScrollStyle} onClick={this.onGoBack} className={panelStyles.headerControl}>
<button style={sideScrollStyle} type="button" onClick={this.onGoBack} className={panelStyles.headerControl}>
<span className={icons.arrowLeft} />
</button>
);
@@ -201,7 +237,7 @@ export default class PanelTransition extends Component {
<div key={`header${key}`} style={style}>
{hasBackButton ? backButton : null}
<div style={scrollStyle}>
{Title}
{React.cloneElement(Title, this.props)}
</div>
</div>
);
@@ -228,8 +264,13 @@ export default class PanelTransition extends Component {
};
return (
<ReactHeight key={`body${key}`} style={style} onHeightReady={this.updateHeight}>
{Body}
<ReactHeight key={`body${key}`} style={style} onHeightReady={this.onUpdateHeight}>
{React.cloneElement(Body, {
...this.props,
ref: (body) => {
this.body = body;
}
})}
</ReactHeight>
);
}
@@ -241,7 +282,7 @@ export default class PanelTransition extends Component {
return (
<div key={`footer${key}`} style={style}>
{Footer}
{React.cloneElement(Footer, this.props)}
</div>
);
}
@@ -253,7 +294,7 @@ export default class PanelTransition extends Component {
return (
<div key={`links${key}`} style={style}>
{Links}
{React.cloneElement(Links, this.props)}
</div>
);
}
@@ -293,3 +334,16 @@ export default class PanelTransition extends Component {
}
}
export default connect((state) => ({
user: state.user,
auth: state.auth,
path: state.routing.location.pathname
}), {
goBack: routeActions.goBack,
login: actions.login,
logout: actions.logout,
register: actions.register,
activate: actions.activate,
clearErrors: actions.clearErrors,
setError: actions.setError
})(PanelTransition);