Massive refactor complete

This commit is contained in:
2019-05-31 13:44:01 +10:00
parent b97d8fc184
commit 4a2bfb3db9
47 changed files with 1223 additions and 991 deletions
+45 -43
View File
@@ -1,4 +1,5 @@
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
class AttackButton extends React.Component {
@@ -8,85 +9,86 @@ class AttackButton extends React.Component {
message: ''
};
this.sendAttackingStatusRequest();
this.sendRequest('/attackstatusrequest', {attacker: this.props.attacker});
}
render() {
if (this.state.message !== '') {
if (this.state.message) {
return (
<p className={this.props.className} style={this.props.style}>{this.state.message}</p>
);
} else {
//inject something extra
let onClick = (e) => {
this.sendRequest('/attackrequest', {attacker: this.props.attacker, defender: this.props.defender});
if (this.props.onClick) {
this.props.onClick(e);
}
};
return (
<button className={this.props.className} style={this.props.style} onClick={this.sendAttackRequest.bind(this)}>Attack</button>
<button className={this.props.className} style={this.props.style} onClick={onClick}>Attack</button>
);
}
}
sendAttackRequest() {
//gameplay functions
sendRequest(url, args = {}) { //send a unified request, using my credentials
//build the XHR
let xhr = new XMLHttpRequest();
xhr.open('POST', '/attackrequest', true);
xhr.open('POST', url, true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let json = JSON.parse(xhr.responseText);
if (json.status === 'attacking') {
this.setState({ message: `Your soldiers are attacking ${json.defender}` });
}
} else if (xhr.status === 400) {
if (this.props.setWarning) {
this.props.setWarning(xhr.responseText);
}
}
}
}
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify({
attacker: this.props.attacker,
defender: this.props.defender,
token: this.props.token
}));
if (this.props.onClick) {
this.props.onClick();
}
this.props.setDisabled(true);
}
sendAttackingStatusRequest() {
let xhr = new XMLHttpRequest();
xhr.open('POST', '/attackstatusrequest', true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let json = JSON.parse(xhr.responseText);
//on success
if (json.status === 'attacking') {
this.setState({ message: `Your soldiers are attacking ${json.defender}` });
}
}
else if (xhr.status === 400 && this.props.setWarning) {
this.props.setWarning(xhr.responseText);
}
}
}
};
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify({
username: this.props.attacker
id: this.props.id,
token: this.props.token,
...args
}));
}
};
AttackButton.propTypes = {
id: PropTypes.number.isRequired,
token: PropTypes.number.isRequired,
attacker: PropTypes.string.isRequired,
defender: PropTypes.string.isRequired,
className: PropTypes.string,
style: PropTypes.object,
onClick: PropTypes.func,
setWarning: PropTypes.func,
attacker: PropTypes.string.isRequired,
defender: PropTypes.string.isRequired,
token: PropTypes.number.isRequired
setWarning: PropTypes.func
};
const mapStoreToProps = (store) => {
return {
id: store.account.id,
token: store.account.token
};
};
const mapDispatchToProps = (dispatch) => {
return {
//
};
};
AttackButton = connect(mapStoreToProps, mapDispatchToProps)(AttackButton);
export default AttackButton;
+1 -1
View File
@@ -21,5 +21,5 @@ export default class Blurb extends React.Component {
</div>
);
}
}
};
-89
View File
@@ -1,89 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import PagedCombatLog from './paged_combat_log.jsx';
class CombatLog extends React.Component {
constructor(props) {
super(props);
this.state = {
start: parseInt(props.start) || 0,
length: parseInt(props.length) || 20,
fetch: null
};
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (JSON.stringify(this.state) !== JSON.stringify(prevState)) {
this.state.fetch();
}
}
render() {
let ButtonHeader = this.buttonHeader.bind(this);
return (
<div className='panel'>
<ButtonHeader />
<PagedCombatLog username={this.props.username} start={this.state.start} length={this.state.length} getFetch={this.getFetch.bind(this)} onReceived={this.onReceived.bind(this)} />
<ButtonHeader />
</div>
);
}
buttonHeader() {
return (
<div className='table'>
<div className='row'>
<button className='col' onClick={this.decrement.bind(this)}>{'< Back'}</button>
<div className='col' />
<div className='col' />
<button className='col' onClick={this.increment.bind(this)}>{'Next >'}</button>
</div>
</div>
);
}
increment() {
let start = this.state.start + this.state.length;
this.props.history.push(`${this.props.location.pathname}?log=${start}`);
}
decrement() {
let start = Math.max(0, this.state.start - this.state.length);
//don't decrement too far
if (start === this.state.start) {
return;
}
this.props.history.push(`${this.props.location.pathname}?log=${start}`);
}
//bound callbacks
getFetch(fn) {
this.setState({ fetch: fn });
}
onReceived(data) {
if (data.length === 0) {
let start = Math.max(0, this.state.start - this.state.length);
//don't decrement too far
if (start === this.state.start) {
return;
}
this.props.history.replace(`${this.props.location.pathname}?log=${start}`);
}
}
}
CombatLog.propTypes = {
username: PropTypes.string.isRequired
};
export default withRouter(CombatLog);
+11 -6
View File
@@ -8,14 +8,16 @@ import Logout from './logout.jsx';
class CommonLinks extends React.Component {
constructor(props) {
super(props);
this.state = {
//
}
}
render() {
//render extra stuff
//render any extra stuff
let Extra;
if (this.props.extra) {
Extra = this.props.extra;
} else {
@@ -29,20 +31,21 @@ class CommonLinks extends React.Component {
<p><Link to='/' onClick={this.props.onClickHome}>Return Home</Link></p>
<p><Link to='/profile' onClick={this.props.onClickProfile}>Your Kingdom</Link></p>
<p><Link to='/ladder' onClick={this.props.onClickLadder}>Game Ladder</Link></p>
<p><Link to='/combatlog' onClick={this.props.onClickCombatLog}>Combat Log</Link></p>
<p><Link to='/passwordchange' onClick={this.props.onClickPasswordChange}>Change Password</Link></p>
<Extra />
<Logout onClick={() => this.props.history.push('/')} />
<Logout onClick={ () => this.props.history.push('/') } />
</div>
);
} else { //if not logged in
return (
<div className='panel'>
<p><Link to='/' onClick={this.props.onClickHome}>Return Home</Link></p>
<p><Link to='/signup' onClick={this.props.onClickSignup}>Sign Up</Link></p>
<p><Link to='/login' onClick={this.props.onClickLogin}>Login</Link></p>
<p><Link to='/passwordrecover' onClick={this.props.onClickPasswordRecover}>Recover Password</Link></p>
<p><Link to='/' onClick={this.props.onClickHome}>Return Home</Link></p>
<p><Link to='/ladder' onClick={this.props.onClickLadder}>Game Ladder</Link></p>
<Extra />
@@ -50,9 +53,11 @@ class CommonLinks extends React.Component {
);
}
}
}
};
CommonLinks.propTypes = {
loggedIn: PropTypes.bool.isRequired,
onClickSignup: PropTypes.func,
onClickLogin: PropTypes.func,
onClickPasswordRecover: PropTypes.func,
@@ -66,13 +71,13 @@ function mapStoreToProps(store) {
return {
loggedIn: store.account.id !== undefined && store.account.id !== 0
}
}
};
function mapDispatchToProps(dispatch) {
return {
//
}
}
};
CommonLinks = connect(mapStoreToProps, mapDispatchToProps)(CommonLinks);
+2
View File
@@ -1,6 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
//TODO: incomplete
class Equipment extends React.Component {
constructor(props) {
super(props);
+3 -2
View File
@@ -1,6 +1,6 @@
import React from 'react';
export default class Footer extends React.Component {
class Footer extends React.Component {
render() {
return (
<footer>
@@ -8,5 +8,6 @@ export default class Footer extends React.Component {
</footer>
);
}
}
};
export default Footer;
+33 -28
View File
@@ -1,6 +1,8 @@
import React from 'react';
import { connect } from 'react-redux';
import { login } from '../../actions/accounts.js';
import PropTypes from 'prop-types';
import { login } from '../../actions/account.js';
import { validateEmail } from '../../../common/utilities.js';
class Login extends React.Component {
@@ -14,7 +16,7 @@ class Login extends React.Component {
}
render() {
let warningStyle = {
let warningStyle = { //TODO: lift the warning out to the page?
display: this.state.warning.length > 0 ? 'flex' : 'none'
};
@@ -26,15 +28,15 @@ class Login extends React.Component {
<p>{this.state.warning}</p>
</div>
<form action='/loginrequest' method='post' onSubmit={(e) => this.submit(e)}>
<form action='/loginrequest' method='post' onSubmit={ this.submit.bind(this) } >
<div>
<label>Email:</label>
<input type='text' name='email' value={this.state.email} onChange={this.updateEmail.bind(this)} />
<input type='text' name='email' value={this.state.email} onChange={ this.updateEmail.bind(this) } />
</div>
<div>
<label>Password:</label>
<input type='password' name='password' value={this.state.password} onChange={this.updatePassword.bind(this)} />
<input type='password' name='password' value={this.state.password} onChange={ this.updatePassword.bind(this) } />
</div>
<button type='submit' disabled={!this.state.email}>Login</button>
@@ -50,19 +52,26 @@ class Login extends React.Component {
return;
}
//build the XHR
//build the XHR (around an existing form object)
let form = e.target;
let formData = new FormData(form);
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let json = JSON.parse(xhr.responseText);
this.props.login(json.id, json.email, json.username, json.token);
if (this.props.onSubmit) {
this.props.onSubmit();
this.props.login(
json.id,
json.email,
json.username,
json.token
);
if (this.props.onSuccess) {
this.props.onSuccess(json.msg); //NOTE: could use this as a redirect to a special offer or sonmething
}
}
@@ -94,43 +103,39 @@ class Login extends React.Component {
}
setWarning(s) {
this.setState({
warning: s
});
this.setState({ warning: s });
}
clearInput() {
this.setState({
email: '',
password: '',
warning: ''
});
this.setState({ email: '', password: '', warning: '' });
}
updateEmail(evt) {
this.setState({
email: evt.target.value
});
this.setState({ email: evt.target.value });
}
updatePassword(evt) {
this.setState({
password: evt.target.value
});
this.setState({ password: evt.target.value });
}
}
};
function mapStoreToProps(store) {
Login.propTypes = {
login: PropTypes.func.isRequired,
onSubmit: PropTypes.func
};
const mapStoreToProps = (store) => {
return {
//
}
}
};
function mapDispatchToProps(dispatch) {
const mapDispatchToProps = (dispatch) => {
return {
login: (id, email, username, token) => dispatch(login(id, email, username, token))
}
}
};
Login = connect(mapStoreToProps, mapDispatchToProps)(Login);
+21 -14
View File
@@ -1,58 +1,65 @@
import React from 'react';
import { connect } from 'react-redux';
import { logout } from '../../actions/accounts.js';
import PropTypes from 'prop-types';
import { logout } from '../../actions/account.js';
class Logout extends React.Component {
constructor(props) {
super(props);
this.state = {
//
}
}
render() {
return (
<button className='logoutButton' type='submit' onClick={(e) => this.submit(e)}>Logout</button>
<button className='logoutButton' type='submit' onClick={(e) => { e.preventDefault(); this.sendRequest('/logoutrequest') }} >Logout</button>
);
}
submit(e) {
e.preventDefault();
sendRequest(url, args = {}) { //send a unified request, using my credentials
//build the XHR
let xhr = new XMLHttpRequest();
xhr.open('POST', '/logoutrequest', true);
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify({
email: this.props.email,
token: this.props.token
id: this.props.id,
token: this.props.token,
...args
}));
//Don't wait for a response
this.props.logout();
if (this.props.onClick) {
this.props.onClick();
}
}
}
};
Logout.propTypes = {
email: PropTypes.string.isRequired,
id: PropTypes.number.isRequired,
token: PropTypes.number.isRequired,
logout: PropTypes.func.isRequired,
onClick: PropTypes.func
}
};
function mapStoreToProps(store) {
return {
email: store.account.email,
id: store.account.id,
token: store.account.token
}
}
};
function mapDispatchToProps(dispatch) {
return {
logout: () => { dispatch(logout()) }
}
}
};
Logout = connect(mapStoreToProps, mapDispatchToProps)(Logout);
+62
View File
@@ -0,0 +1,62 @@
import React from 'react';
import ReactMarkdown from 'react-markdown/with-html';
import PropTypes from 'prop-types';
class News extends React.Component {
constructor(props) {
super(props);
this.state = {
//
};
if (props.getFetch) {
props.getFetch( () => this.sendRequest('/newsrequest', {length: this.props.length || 10}) );
}
}
render() {
return (
<div className='panel'>
{Object.keys(this.state).map((key) => <div key={key}>
<ReactMarkdown source={this.state[key]} escapeHtml={false} />
<hr className='newsLine' />
</div>)}
</div>
);
}
sendRequest(url, args = {}) { //send a unified request, using my credentials
//build the XHR
let xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let json = JSON.parse(xhr.responseText);
//on success
this.setState(json);
}
else if (xhr.status === 400 && this.props.setWarning) {
this.props.setWarning(xhr.responseText);
}
}
};
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify({
//NOTE: No id or token needed for the news
...args
}));
}
};
News.propTypes = {
length: PropTypes.number,
setWarning: PropTypes.func,
getFetch: PropTypes.func
};
export default News;
-44
View File
@@ -1,44 +0,0 @@
import React from 'react';
import ReactMarkdown from 'react-markdown';
class NewsPanel extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {}
};
this.fetchNews(this.props.length || 10);
}
render() {
return (
<div>
{Object.keys(this.state.data).map((key) => <div key={key}>
<ReactMarkdown source={this.state.data[key]} escapeHTML={false} />
<hr className='newsLine' />
</div> )}
</div>
);
}
fetchNews(max) {
//build the XHR
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
this.setState({data: JSON.parse(xhr.responseText)});
}
}
}
xhr.open('POST', '/newsrequest', true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify({ max: max }));
}
};
export default NewsPanel;
+60 -22
View File
@@ -1,20 +1,31 @@
import React from 'react';
import { withRouter, Link } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
class PagedCombatLog extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {}
//
}
if (props.getFetch) {
props.getFetch(this.fetchCombatLog.bind(this));
props.getFetch(() => this.sendRequest('/combatlogrequest', {username: props.username, start: props.start, length: props.length}));
}
}
render() {
//make the enemy name a link
const PrettyName = (props) => {
if (props.name === this.props.username) {
return (<p {...props}>{props.name}</p>);
} else {
return (<p {...props}><Link to={`/profile?username=${props.name}`}>{props.name}</Link></p>);
}
};
return (
<div className='table'>
<div className='row'>
@@ -28,44 +39,51 @@ class PagedCombatLog extends React.Component {
<p className='col centered minWidth'>Gold Transferred</p>
<p className='col centered minWidth'>Victor Casualties</p>
</div>
{Object.keys(this.state.data).map((key) => <div key={key} className={'row'}>
<p className='col centered minWidth'>{ this.parseDate(this.state.data[key].eventTime) }</p>
<p className='col centered minWidth'><Link to={`/profile?username=${this.state.data[key].attackerUsername}`} className={'col'}>{this.state.data[key].attackerUsername}</Link></p>
<p className='col centered minWidth'><Link to={`/profile?username=${this.state.data[key].defenderUsername}`} className={'col'}>{this.state.data[key].defenderUsername}</Link></p>
<p className='col centered minWidth'>{this.state.data[key].attackingUnits}</p>
<p className='col centered minWidth'>{this.state.data[key].defendingUnits}</p>
<p className='col centered minWidth'>{this.state.data[key].undefended ? 'yes' : 'no'}</p>
<p className='col centered minWidth'>{this.state.data[key].victor}</p>
<p className='col centered minWidth'>{this.state.data[key].spoilsGold}</p>
<p className='col centered minWidth'>{this.state.data[key].casualtiesVictor}</p>
{Object.keys(this.state).map((key) => <div key={key} className={'row'}>
<p className='col centered minWidth'>{ this.parseDate(this.state[key].eventTime) }</p>
<PrettyName className='col centered minWidth' name={this.state[key].attacker} />
<PrettyName className='col centered minWidth' name={this.state[key].defender} />
<p className='col centered minWidth'>{this.state[key].attackingUnits}</p>
<p className='col centered minWidth'>{this.state[key].defendingUnits}</p>
<p className='col centered minWidth'>{this.state[key].undefended ? 'yes' : 'no'}</p>
<p className='col centered minWidth'>{this.state[key].victor}</p>
<p className='col centered minWidth'>{this.state[key].spoilsGold}</p>
<p className='col centered minWidth'>{this.state[key].casualtiesVictor}</p>
</div>)}
</div>
);
}
fetchCombatLog(username = this.props.username, start = this.props.start, length = this.props.length) {
//gameplay functions
sendRequest(url, args = {}) { //send a unified request, using my credentials
//build the XHR
let xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let data = JSON.parse(xhr.responseText);
this.setState({data: data});
let json = JSON.parse(xhr.responseText);
//on success
this.setState(json);
if (this.props.onReceived) {
this.props.onReceived(data);
this.props.onReceived(json);
}
}
else if (xhr.status === 400 && this.props.setWarning) {
this.props.setWarning(xhr.responseText);
}
}
}
};
xhr.open('POST', '/combatlogrequest', true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify({
username: username,
start: start,
length: length
id: this.props.id,
token: this.props.token,
...args
}));
}
@@ -75,14 +93,34 @@ class PagedCombatLog extends React.Component {
let date = new Date(eventTime);
return `${date.getDate()} ${month[date.getMonth()]}`;
}
}
};
PagedCombatLog.propTypes = {
id: PropTypes.number.isRequired,
token: PropTypes.number.isRequired,
username: PropTypes.string.isRequired,
start: PropTypes.number.isRequired,
length: PropTypes.number.isRequired,
setWarning: PropTypes.func,
getFetch: PropTypes.func,
onReceived: PropTypes.func
};
const mapStoreToProps = (store) => {
return {
id: store.account.id,
token: store.account.token
};
};
const mapDispatchToProps = (dispatch) => {
return {
//
};
};
PagedCombatLog = connect(mapStoreToProps, mapDispatchToProps)(PagedCombatLog);
export default withRouter(PagedCombatLog);
+24 -18
View File
@@ -6,11 +6,11 @@ class PagedLadder extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {}
//
}
if (props.getFetch) {
props.getFetch(this.fetchLadder.bind(this));
props.getFetch( () => this.sendRequest('/ladderrequest', {start: this.props.start || 0, length: this.props.length || 20}) );
}
}
@@ -23,45 +23,51 @@ class PagedLadder extends React.Component {
<p className='col centered'>Recruits</p>
<p className='col centered'>Gold</p>
</div>
{Object.keys(this.state.data).map((key) => <div key={key} className={'row centered'}>
<p className={'col centered'}><Link to={`/profile?username=${this.state.data[key].username}`}>{this.state.data[key].username}</Link></p>
<p className={'col centered'}>{this.state.data[key].soldiers}</p>
<p className={'col centered'}>{this.state.data[key].recruits}</p>
<p className={'col centered'}>{this.state.data[key].gold}</p>
{Object.keys(this.state).map((key) => <div key={key} className={'row'}>
<p className={'col centered'}><Link to={`/profile?username=${this.state[key].username}`}>{this.state[key].username}</Link></p>
<p className={'col centered'}>{this.state[key].soldiers}</p>
<p className={'col centered'}>{this.state[key].recruits}</p>
<p className={'col centered'}>{this.state[key].gold}</p>
</div> )}
</div>
);
}
fetchLadder(start = this.props.start, length = this.props.length) {
sendRequest(url, args = {}) { //send a unified request, using my credentials
//build the XHR
let xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let data = JSON.parse(xhr.responseText);
this.setState({data: data});
let json = JSON.parse(xhr.responseText);
//on success
this.setState(json);
if (this.props.onReceived) {
this.props.onReceived(data);
this.props.onReceived(json);
}
}
else if (xhr.status === 400 && this.props.setWarning) {
this.props.setWarning(xhr.responseText);
}
}
}
};
xhr.open('POST', '/ladderrequest', true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify({
start: start,
length: length
//NOTE: No id or token needed for the news
...args
}));
}
}
};
PagedLadder.propTypes = {
start: PropTypes.number.isRequired,
length: PropTypes.number.isRequired,
start: PropTypes.number,
length: PropTypes.number,
setWarning: PropTypes.func,
getFetch: PropTypes.func,
onReceived: PropTypes.func
};
+40 -35
View File
@@ -1,10 +1,13 @@
import React from 'react';
import { connect } from 'react-redux';
import { sessionChange } from '../../actions/accounts.js';
import PropTypes from 'prop-types';
import { sessionChange } from '../../actions/account.js';
class PasswordChange extends React.Component {
constructor(props) {
super(props);
this.state = {
password: '',
retype: '',
@@ -13,7 +16,7 @@ class PasswordChange extends React.Component {
}
render() {
let warningStyle = {
let warningStyle = { //TODO: lift the warning out to the page?
display: this.state.warning.length > 0 ? 'flex' : 'none'
};
@@ -25,7 +28,7 @@ class PasswordChange extends React.Component {
<p>{this.state.warning}</p>
</div>
<form action='/passwordchangerequest' method='post' onSubmit={(e) => this.submit(e)}>
<form action='/passwordchangerequest' method='post' onSubmit={this.submit.bind(this)}>
<div>
<label>Password:</label>
<input type='password' name='password' value={this.state.password} onChange={this.updatePassword.bind(this)} />
@@ -49,23 +52,25 @@ class PasswordChange extends React.Component {
return;
}
//build the XHR
//build the XHR (around an existing form object)
let form = e.target;
let formData = new FormData(form);
let xhr = new XMLHttpRequest();
formData.append('email', this.props.email);
formData.append('id', this.props.id);
formData.append('token', this.props.token);
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let json = JSON.parse(xhr.responseText);
//on success
this.props.sessionChange(json.token);
//DEBUGGING
if (this.props.onPasswordChange) {
this.props.onPasswordChange(json.msg);
if (this.props.onSuccess) {
this.props.onSuccess(json.msg);
}
}
@@ -78,6 +83,8 @@ class PasswordChange extends React.Component {
//send the XHR
xhr.open('POST', form.action, true);
xhr.send(formData);
this.clearInput();
}
validateInput(e) {
@@ -94,45 +101,43 @@ class PasswordChange extends React.Component {
return true;
}
setWarning(s) {
this.setState({
warning: s
});
}
clearInput() {
this.setState({
password: '',
retype: '',
warning: ''
});
this.setState({ password: '', retype: '', warning: '' });
}
updatePassword(evt) {
this.setState({
password: evt.target.value
});
this.setState({ password: evt.target.value });
}
updateRetype(evt) {
this.setState({
retype: evt.target.value
});
this.setState({ retype: evt.target.value });
}
}
function mapStoreToProps(store) {
setWarning(s) {
this.setState({ warning: s });
}
};
PasswordChange.propTypes = {
id: PropTypes.number.isRequired,
token: PropTypes.number.isRequired,
sessionChange: PropTypes.func.isRequired,
onSuccess: PropTypes.func
};
const mapStoreToProps = (store) => {
return {
email: store.account.email,
id: store.account.id,
token: store.account.token
}
}
};
};
function mapDispatchToProps(dispatch) {
const mapDispatchToProps = (dispatch) => {
return {
sessionChange: (token) => { dispatch(sessionChange(token)); }
}
}
sessionChange: (token) => dispatch(sessionChange(token))
};
};
PasswordChange = connect(mapStoreToProps, mapDispatchToProps)(PasswordChange);
+18 -17
View File
@@ -1,9 +1,11 @@
import React from 'react';
import { validateEmail } from '../../../common/utilities.js';
import { validateEmail } from '../../../common/utilities.js'; //TODO: move utilities to a better position
import PropTypes from 'prop-types';
class PasswordRecover extends React.Component {
constructor(props) {
super(props);
this.state = {
email: '',
warning: ''
@@ -23,7 +25,7 @@ class PasswordRecover extends React.Component {
<p>{this.state.warning}</p>
</div>
<form action='/passwordrecoverrequest' method='post' onSubmit={(e) => this.submit(e)}>
<form action='/passwordrecoverrequest' method='post' onSubmit={this.submit.bind(this)}>
<div>
<label>Email:</label>
<input type='text' name='email' value={this.state.email} onChange={this.updateEmail.bind(this)} />
@@ -42,17 +44,19 @@ class PasswordRecover extends React.Component {
return;
}
//build the XHR
//build the XHR (around an existing form object)
let form = e.target;
let formData = new FormData(form);
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
//DEBUGGING
if (this.props.onEmailSent) {
this.props.onEmailSent(xhr.responseText);
let json = JSON.parse(xhr.responseText);
if (this.props.onSuccess) {
this.props.onSuccess(json.msg);
}
}
@@ -79,23 +83,20 @@ class PasswordRecover extends React.Component {
}
setWarning(s) {
this.setState({
warning: s
});
this.setState({ warning: s });
}
clearInput() {
this.setState({
email: '',
warning: ''
});
this.setState({ email: '', warning: '' });
}
updateEmail(evt) {
this.setState({
email: evt.target.value
});
this.setState({ email: evt.target.value });
}
}
};
PasswordRecover.propTypes = {
onSuccess: PropTypes.func
};
export default PasswordRecover;
+17 -21
View File
@@ -1,11 +1,12 @@
import React from 'react';
import { connect } from 'react-redux';
import { sessionChange } from '../../actions/accounts.js';
import { sessionChange } from '../../actions/account.js';
import PropTypes from 'prop-types';
class PasswordReset extends React.Component {
constructor(props) {
super(props);
this.state = {
password: '',
retype: '',
@@ -26,7 +27,7 @@ class PasswordReset extends React.Component {
<p>{this.state.warning}</p>
</div>
<form action='/passwordresetrequest' method='post' onSubmit={(e) => this.submit(e)}>
<form action='/passwordresetrequest' method='post' onSubmit={this.submit.bind(this)}>
<div>
<label>Password:</label>
<input type='password' name='password' value={this.state.password} onChange={this.updatePassword.bind(this)} />
@@ -53,16 +54,19 @@ class PasswordReset extends React.Component {
//build the XHR
let form = e.target;
let formData = new FormData(form);
let xhr = new XMLHttpRequest();
formData.append('email', this.props.email);
formData.append('token', this.props.token);
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (this.props.onPasswordReset) {
this.props.onPasswordReset(xhr.responseText);
let json = JSON.parse(xhr.responseText);
if (this.props.onSuccess) {
this.props.onSuccess(json.msg);
}
}
@@ -92,35 +96,27 @@ class PasswordReset extends React.Component {
}
setWarning(s) {
this.setState({
warning: s
});
this.setState({ warning: s });
}
clearInput() {
this.setState({
password: '',
retype: '',
warning: ''
});
this.setState({ password: '', retype: '', warning: '' });
}
updatePassword(evt) {
this.setState({
password: evt.target.value
});
this.setState({ password: evt.target.value });
}
updateRetype(evt) {
this.setState({
retype: evt.target.value
});
this.setState({ retype: evt.target.value });
}
}
};
PasswordReset.propTypes = {
email: PropTypes.string.isRequired,
token: PropTypes.number.isRequired
token: PropTypes.number.isRequired,
onSuccess: PropTypes.func
};
export default PasswordReset;
+15 -28
View File
@@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
class Signup extends React.Component {
constructor(props) {
super(props);
this.state = {
email: '',
username: '',
@@ -27,7 +28,7 @@ class Signup extends React.Component {
<p>{this.state.warning}</p>
</div>
<form action='/signuprequest' method='post' onSubmit={(e) => this.submit(e)}>
<form action='/signuprequest' method='post' onSubmit={this.submit.bind(this)}>
<div>
<label>Email:</label>
<input type='text' name='email' value={this.state.email} onChange={this.updateEmail.bind(this)} />
@@ -64,14 +65,16 @@ class Signup extends React.Component {
//build the XHR
let form = e.target;
let formData = new FormData(form);
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (this.props.onSignup) {
this.props.onSignup(xhr.responseText);
console.log('trying to...');
let json = JSON.parse(xhr.responseText);
if (this.props.onSuccess) {
this.props.onSuccess(json.msg);
}
}
@@ -114,48 +117,32 @@ class Signup extends React.Component {
}
setWarning(s) {
this.setState({
warning: s
});
this.setState({ warning: s });
}
clearInput() {
this.setState({
email: '',
username: '',
password: '',
retype: '',
warning: ''
});
this.setState({ email: '', username: '', password: '', retype: '', warning: '' });
}
updateEmail(evt) {
this.setState({
email: evt.target.value
});
this.setState({ email: evt.target.value });
}
updateUsername(evt) {
this.setState({
username: evt.target.value
});
this.setState({ username: evt.target.value });
}
updatePassword(evt) {
this.setState({
password: evt.target.value
});
this.setState({ password: evt.target.value });
}
updateRetype(evt) {
this.setState({
retype: evt.target.value
});
this.setState({ retype: evt.target.value });
}
}
};
Signup.propTypes = {
onSignup: PropTypes.func
onSuccess: PropTypes.func
};
export default Signup;