Skip to content

Commit 5900e62

Browse files
committed
unify navigation for authentication pages, add authorization to front end, fixes #650
1 parent 7f2529a commit 5900e62

File tree

17 files changed

+220
-218
lines changed

17 files changed

+220
-218
lines changed

client/components/Nav.jsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33
import { connect } from 'react-redux';
44
import { withRouter } from 'react-router';
5-
import { Link } from 'react-router';
5+
import { Link, browserHistory } from 'react-router';
66
import InlineSVG from 'react-inlinesvg';
77
import classNames from 'classnames';
88
import * as IDEActions from '../modules/IDE/actions/ide';
@@ -93,11 +93,12 @@ class Nav extends React.PureComponent {
9393
}
9494

9595
handleNew() {
96-
if (!this.props.unsavedChanges) {
96+
const { unsavedChanges, warnIfUnsavedChanges } = this.props;
97+
if (!unsavedChanges) {
9798
this.props.showToast(1500);
9899
this.props.setToastText('Opened new sketch.');
99100
this.props.newProject();
100-
} else if (this.props.warnIfUnsavedChanges()) {
101+
} else if (warnIfUnsavedChanges && warnIfUnsavedChanges()) {
101102
this.props.showToast(1500);
102103
this.props.setToastText('Opened new sketch.');
103104
this.props.newProject();
@@ -166,6 +167,8 @@ class Nav extends React.PureComponent {
166167

167168
handleLogout() {
168169
this.props.logoutUser();
170+
// if you're on the settings page, probably.
171+
browserHistory.push('/');
169172
this.setDropdown('none');
170173
}
171174

@@ -535,13 +538,13 @@ class Nav extends React.PureComponent {
535538
renderUnauthenticatedUserMenu(navDropdownState) {
536539
return (
537540
<ul className="nav__items-right" title="user-menu">
538-
<li>
541+
<li className="nav__item">
539542
<Link to="/login">
540543
<span className="nav__item-header">Log in</span>
541544
</Link>
542545
</li>
543546
<span className="nav__item-spacer">or</span>
544-
<li>
547+
<li className="nav__item">
545548
<Link to="/signup">
546549
<span className="nav__item-header">Sign up</span>
547550
</Link>
@@ -708,7 +711,7 @@ Nav.propTypes = {
708711
showShareModal: PropTypes.func.isRequired,
709712
showErrorModal: PropTypes.func.isRequired,
710713
unsavedChanges: PropTypes.bool.isRequired,
711-
warnIfUnsavedChanges: PropTypes.func.isRequired,
714+
warnIfUnsavedChanges: PropTypes.func,
712715
showKeyboardShortcutModal: PropTypes.func.isRequired,
713716
cmController: PropTypes.shape({
714717
tidyCode: PropTypes.func,
@@ -731,7 +734,8 @@ Nav.defaultProps = {
731734
owner: undefined
732735
},
733736
cmController: {},
734-
layout: 'project'
737+
layout: 'project',
738+
warnIfUnsavedChanges: undefined
735739
};
736740

737741
function mapStateToProps(state) {

client/modules/User/components/APIKeyForm.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ class APIKeyForm extends React.Component {
8686
disabled={this.state.keyLabel === ''}
8787
type="submit"
8888
>
89-
<InlineSVG src={plusIcon} alt="" /> Create
89+
<InlineSVG src={plusIcon} className="api-key-form__create-icon" />
90+
Create
9091
</button>
9192
</form>
9293

client/modules/User/pages/AccountView.jsx

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33
import { reduxForm } from 'redux-form';
44
import { bindActionCreators } from 'redux';
5-
import { browserHistory } from 'react-router';
65
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
76
import axios from 'axios';
87
import { Helmet } from 'react-helmet';
@@ -11,48 +10,37 @@ import AccountForm from '../components/AccountForm';
1110
import { validateSettings } from '../../../utils/reduxFormUtils';
1211
import GithubButton from '../components/GithubButton';
1312
import APIKeyForm from '../components/APIKeyForm';
14-
import NavBasic from '../../../components/NavBasic';
13+
import Nav from '../../../components/Nav';
1514

16-
class AccountView extends React.Component {
17-
constructor(props) {
18-
super(props);
19-
this.closeAccountPage = this.closeAccountPage.bind(this);
20-
this.gotoHomePage = this.gotoHomePage.bind(this);
21-
}
15+
const __process = (typeof global !== 'undefined' ? global : window).process;
16+
const ROOT_URL = __process.env.API_URL;
2217

18+
class AccountView extends React.Component {
2319
componentDidMount() {
2420
document.body.className = this.props.theme;
2521
}
2622

27-
closeAccountPage() {
28-
browserHistory.push(this.props.previousPath);
29-
}
30-
31-
gotoHomePage() {
32-
browserHistory.push('/');
33-
}
34-
3523
render() {
3624
const accessTokensUIEnabled = window.process.env.UI_ACCESS_TOKEN_ENABLED;
3725

3826
return (
39-
<div className="user">
27+
<div className="account-settings__container">
4028
<Helmet>
41-
<title>p5.js Web Editor | Account</title>
29+
<title>p5.js Web Editor | Account Settings</title>
4230
</Helmet>
4331

44-
<NavBasic onBack={this.closeAccountPage} />
32+
<Nav layout="dashboard" />
4533

46-
<section className="modal">
47-
<div className="modal-content">
48-
<div className="modal__header">
49-
<h2 className="modal__title">My Account</h2>
50-
</div>
34+
<section className="account-settings">
35+
<header className="account-settings__header">
36+
<h1 className="account-settings__title">Account Settings</h1>
37+
</header>
38+
{accessTokensUIEnabled &&
5139
<Tabs className="account__tabs">
5240
<TabList>
5341
<div className="tabs__titles">
5442
<Tab><h4 className="tabs__title">Account</h4></Tab>
55-
{accessTokensUIEnabled && <Tab><h4 className="tabs__title">Access Tokens</h4></Tab>}
43+
<Tab><h4 className="tabs__title">Access Tokens</h4></Tab>
5644
</div>
5745
</TabList>
5846
<TabPanel>
@@ -67,7 +55,17 @@ class AccountView extends React.Component {
6755
<APIKeyForm {...this.props} />
6856
</TabPanel>
6957
</Tabs>
70-
</div>
58+
}
59+
{!accessTokensUIEnabled &&
60+
<div>
61+
<AccountForm {...this.props} />
62+
<h2 className="form-container__divider">Social Login</h2>
63+
<p className="account__social-text">
64+
Link this account with your GitHub account to allow login from both.
65+
</p>
66+
<GithubButton buttonText="Login with GitHub" />
67+
</div>
68+
}
7169
</section>
7270
</div>
7371
);
@@ -96,7 +94,7 @@ function asyncValidate(formProps, dispatch, props) {
9694
const queryParams = {};
9795
queryParams[fieldToValidate] = formProps[fieldToValidate];
9896
queryParams.check_type = fieldToValidate;
99-
return axios.get('/api/signup/duplicate_check', { params: queryParams })
97+
return axios.get(`${ROOT_URL}/signup/duplicate_check`, { params: queryParams })
10098
.then((response) => {
10199
if (response.data.exists) {
102100
const error = {};

client/modules/User/pages/EmailVerificationView.jsx

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,17 @@ import React from 'react';
33
import { connect } from 'react-redux';
44
import { bindActionCreators } from 'redux';
55
import { browserHistory } from 'react-router';
6-
import InlineSVG from 'react-inlinesvg';
76
import get from 'lodash/get';
87
import { Helmet } from 'react-helmet';
98
import { verifyEmailConfirmation } from '../actions';
10-
11-
const exitUrl = require('../../../images/exit.svg');
12-
const logoUrl = require('../../../images/p5js-logo.svg');
9+
import Nav from '../../../components/Nav';
1310

1411

1512
class EmailVerificationView extends React.Component {
1613
static defaultProps = {
1714
emailVerificationTokenState: null,
1815
}
1916

20-
constructor(props) {
21-
super(props);
22-
this.closeLoginPage = this.closeLoginPage.bind(this);
23-
this.gotoHomePage = this.gotoHomePage.bind(this);
24-
}
25-
2617
componentWillMount() {
2718
const verificationToken = this.verificationToken();
2819
if (verificationToken != null) {
@@ -32,14 +23,6 @@ class EmailVerificationView extends React.Component {
3223

3324
verificationToken = () => get(this.props, 'location.query.t', null);
3425

35-
closeLoginPage() {
36-
browserHistory.push(this.props.previousPath);
37-
}
38-
39-
gotoHomePage() {
40-
browserHistory.push('/');
41-
}
42-
4326
render() {
4427
let status = null;
4528
const {
@@ -48,7 +31,7 @@ class EmailVerificationView extends React.Component {
4831

4932
if (this.verificationToken() == null) {
5033
status = (
51-
<p>That link is invalid</p>
34+
<p>That link is invalid.</p>
5235
);
5336
} else if (emailVerificationTokenState === 'checking') {
5437
status = (
@@ -58,26 +41,20 @@ class EmailVerificationView extends React.Component {
5841
status = (
5942
<p>All done, your email address has been verified.</p>
6043
);
44+
setTimeout(() => browserHistory.push('/'), 1000);
6145
} else if (emailVerificationTokenState === 'invalid') {
6246
status = (
6347
<p>Something went wrong.</p>
6448
);
6549
}
6650

6751
return (
68-
<div className="user">
52+
<div className="email-verification">
53+
<Nav layout="dashboard" />
6954
<div className="form-container">
7055
<Helmet>
7156
<title>p5.js Web Editor | Email Verification</title>
7257
</Helmet>
73-
<div className="form-container__header">
74-
<button className="form-container__logo-button" onClick={this.gotoHomePage}>
75-
<InlineSVG src={logoUrl} alt="p5js Logo" />
76-
</button>
77-
<button className="form-container__exit-button" onClick={this.closeLoginPage}>
78-
<InlineSVG src={exitUrl} alt="Close Login Page" />
79-
</button>
80-
</div>
8158
<div className="form-container__content">
8259
<h2 className="form-container__title">Verify your email</h2>
8360
{status}
@@ -91,7 +68,6 @@ class EmailVerificationView extends React.Component {
9168
function mapStateToProps(state) {
9269
return {
9370
emailVerificationTokenState: state.user.emailVerificationTokenState,
94-
previousPath: state.ide.previousPath
9571
};
9672
}
9773

@@ -103,7 +79,6 @@ function mapDispatchToProps(dispatch) {
10379

10480

10581
EmailVerificationView.propTypes = {
106-
previousPath: PropTypes.string.isRequired,
10782
emailVerificationTokenState: PropTypes.oneOf([
10883
'checking', 'verified', 'invalid'
10984
]),

client/modules/User/pages/LoginView.jsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33
import { reduxForm } from 'redux-form';
44
import { Link, browserHistory } from 'react-router';
5-
import InlineSVG from 'react-inlinesvg';
65
import { Helmet } from 'react-helmet';
76
import { validateAndLoginUser } from '../actions';
87
import LoginForm from '../components/LoginForm';
98
import { validateLogin } from '../../../utils/reduxFormUtils';
109
import GithubButton from '../components/GithubButton';
1110
import GoogleButton from '../components/GoogleButton';
12-
13-
const exitUrl = require('../../../images/exit.svg');
14-
const logoUrl = require('../../../images/p5js-logo.svg');
11+
import Nav from '../../../components/Nav';
1512

1613
class LoginView extends React.Component {
1714
constructor(props) {
@@ -34,19 +31,12 @@ class LoginView extends React.Component {
3431
return null;
3532
}
3633
return (
37-
<div className="user">
34+
<div className="login">
35+
<Nav layout="dashboard" />
3836
<div className="form-container">
3937
<Helmet>
4038
<title>p5.js Web Editor | Login</title>
4139
</Helmet>
42-
<div className="form-container__header">
43-
<button className="form-container__logo-button" onClick={this.gotoHomePage}>
44-
<InlineSVG src={logoUrl} alt="p5js Logo" />
45-
</button>
46-
<button className="form-container__exit-button" onClick={this.closeLoginPage}>
47-
<InlineSVG src={exitUrl} alt="Close Login Page" />
48-
</button>
49-
</div>
5040
<div className="form-container__content">
5141
<h2 className="form-container__title">Log In</h2>
5242
<LoginForm {...this.props} />

0 commit comments

Comments
 (0)