Интегрировал Finish с PanelTransition

This commit is contained in:
SleepWalker
2016-03-15 07:40:18 +02:00
parent 1119354226
commit 8fcfc35d95
5 changed files with 67 additions and 45 deletions

View File

@@ -1,58 +1,55 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { FormattedMessage as Message } from 'react-intl'; import { FormattedMessage as Message } from 'react-intl';
import Helmet from 'react-helmet';
import classNames from 'classnames'; import classNames from 'classnames';
import buttons from 'components/ui/buttons.scss'; import buttons from 'components/ui/buttons.scss';
import { Input } from 'components/ui/Form';
import BaseAuthBody from './BaseAuthBody';
import messages from './Finish.messages'; import messages from './Finish.messages';
import styles from './finish.scss'; import styles from './finish.scss';
export default class Finish extends Component { class Finish extends Component {
static propTypes = { static displayName = 'Finish';
static propTypes = {
appName: PropTypes.string.isRequired,
code: PropTypes.string.isRequired,
displayCode: PropTypes.bool,
success: PropTypes.bool
}; };
state = { state = {
isSidebarHidden: false isCopySupported: document.queryCommandSupported && document.queryCommandSupported('copy')
}; };
handleCopyClick(selector) { handleCopyClick = (event) => {
event.preventDefault();
// http://stackoverflow.com/a/987376/5184751 // http://stackoverflow.com/a/987376/5184751
var text = document.querySelector(selector);
var range, selection;
if (document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(text);
range.select();
} else if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(text);
selection.removeAllRanges();
selection.addRange(range);
}
try { try {
var successful = document.execCommand('copy'); const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(this.code);
selection.removeAllRanges();
selection.addRange(range);
const successful = document.execCommand('copy');
selection.removeAllRanges();
// TODO: было бы ещё неплохо сделать какую-то анимацию, вроде "Скопировано", // TODO: было бы ещё неплохо сделать какую-то анимацию, вроде "Скопировано",
// ибо сейчас после клика как-то неубедительно, скопировалось оно или нет // ибо сейчас после клика как-то неубедительно, скопировалось оно или нет
console.log('Copying text command was ' + (successful ? 'successful' : 'unsuccessful')); console.log('Copying text command was ' + (successful ? 'successful' : 'unsuccessful'));
} catch (err) { } catch (err) {}
console.error('Oops, unable to copy'); };
}
} setCode = (el) => {
this.code = el;
};
render() { render() {
const withCode = true; const {appName, code, displayCode, success} = this.props;
const success = true; const {isCopySupported} = this.state;
const appName = 'TLauncher';
const code = 'HW9vkZA6Y4vRN3ciSm1IIDk98PHLkPPlv3jvo1MX';
const copySupported = document.queryCommandSupported('copy');
return ( return (
<div className={styles.finishPage}> <div className={styles.finishPage}>
@@ -64,19 +61,21 @@ export default class Finish extends Component {
appName: (<span className={styles.appName}>{appName}</span>) appName: (<span className={styles.appName}>{appName}</span>)
}} /> }} />
</div> </div>
{withCode ? ( {displayCode ? (
<div> <div>
<div className={styles.description}> <div className={styles.description}>
<Message {...messages.passCodeToApp} values={{appName}} /> <Message {...messages.passCodeToApp} values={{appName}} />
</div> </div>
<div className={styles.code}>{code}</div> <div className={styles.codeContainer}>
{copySupported ? ( <div className={styles.code} ref={this.setCode}>{code}</div>
<div </div>
{isCopySupported ? (
<button
className={classNames(buttons.smallButton, buttons.green)} className={classNames(buttons.smallButton, buttons.green)}
onClick={this.handleCopyClick.bind(this, '.' + styles.code)} onClick={this.handleCopyClick}
> >
<Message {...messages.copy} /> <Message {...messages.copy} />
</div> </button>
) : ( ) : (
'' ''
)} )}
@@ -104,3 +103,10 @@ export default class Finish extends Component {
); );
} }
} }
export default connect((state) => ({
appName: state.auth.client ? state.auth.client.name : 'Undefined',
code: 'HW9vkZA6Y4vRN3ciSm1IIDk98PHLkPPlv3jvo1MX',
displayCode: true,
success: true
}))(Finish);

View File

@@ -38,10 +38,11 @@ class PanelTransition extends Component {
// local props // local props
path: PropTypes.string.isRequired, path: PropTypes.string.isRequired,
Title: PropTypes.element.isRequired, Title: PropTypes.element,
Body: PropTypes.element.isRequired, Body: PropTypes.element,
Footer: PropTypes.element.isRequired, Footer: PropTypes.element,
Links: PropTypes.element.isRequired Links: PropTypes.element,
children: PropTypes.element
}; };
static childContextTypes = { static childContextTypes = {
@@ -101,6 +102,12 @@ class PanelTransition extends Component {
const {path, Title, Body, Footer, Links} = this.props; const {path, Title, Body, Footer, Links} = this.props;
if (this.props.children) {
return this.props.children;
} else if (!Title || !Body || !Footer || !Links) {
throw new Error('Title, Body, Footer and Links are required');
}
return ( return (
<TransitionMotion <TransitionMotion
styles={[ styles={[

View File

@@ -4,7 +4,10 @@
.finishPage { .finishPage {
font-family: $font-family-title; font-family: $font-family-title;
position: relative; position: relative;
max-width: 515px;
padding-top: 40px; padding-top: 40px;
margin: 0 auto;
text-align: center;
} }
.iconBackground { .iconBackground {
@@ -56,12 +59,18 @@
margin-bottom: 10px; margin-bottom: 10px;
} }
.codeContainer {
margin-bottom: 5px;
margin-top: 35px;
}
.code { .code {
$border: 5px solid darker($green); $border: 5px solid darker($green);
display: inline-block;
border-right: $border; border-right: $border;
border-left: $border; border-left: $border;
padding: 5px 0; padding: 5px 10px;
margin-bottom: 5px;
word-break: break-all; word-break: break-all;
text-align: center;
} }

View File

@@ -33,7 +33,7 @@ class AuthPage extends Component {
<AppInfo {...client} onGoToAuth={this.onGoToAuth} /> <AppInfo {...client} onGoToAuth={this.onGoToAuth} />
</div> </div>
<div className={styles.content}> <div className={styles.content}>
<Finish {...this.props} /> <PanelTransition {...this.props} />
</div> </div>
</div> </div>
); );

View File

@@ -46,9 +46,9 @@ export default function routesFactory(store) {
<Route path="/register" components={new Register()} {...onEnter} /> <Route path="/register" components={new Register()} {...onEnter} />
<Route path="/activation" components={new Activation()} {...onEnter} /> <Route path="/activation" components={new Activation()} {...onEnter} />
<Route path="/oauth/permissions" components={new Permissions()} {...onEnter} /> <Route path="/oauth/permissions" components={new Permissions()} {...onEnter} />
<Route path="/oauth/finish" component={Finish} />
<Route path="/password-change" components={new PasswordChange()} {...onEnter} /> <Route path="/password-change" components={new PasswordChange()} {...onEnter} />
<Route path="/forgot-password" components={new ForgotPassword()} {...onEnter} /> <Route path="/forgot-password" components={new ForgotPassword()} {...onEnter} />
<Route path="/oauth/finish" components={new Finish()} />
</Route> </Route>
</Route> </Route>
); );