Massive refactor complete
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
export const LOGIN = 'LOGIN';
|
||||
export const LOGOUT = 'LOGOUT';
|
||||
export const SESSIONCHANGE = 'SESSIONCHANGE';
|
||||
export const SESSION_CHANGE = 'SESSION_CHANGE';
|
||||
|
||||
export function login(id, email, username, token) {
|
||||
export const login = (id, email, username, token) => {
|
||||
return {
|
||||
type: LOGIN,
|
||||
id: id,
|
||||
@@ -12,15 +12,15 @@ export function login(id, email, username, token) {
|
||||
};
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
export const logout = () => {
|
||||
return {
|
||||
type: LOGOUT
|
||||
};
|
||||
}
|
||||
|
||||
export function sessionChange(token) {
|
||||
export const sessionChange = (token) => {
|
||||
return {
|
||||
type: SESSIONCHANGE,
|
||||
type: SESSION_CHANGE,
|
||||
token: token
|
||||
};
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export const SET_ATTACK_DISABLED = 'SET_ATTACK_DISABLED';
|
||||
|
||||
export function setAttackDisabled(disabled) {
|
||||
return {
|
||||
type: SET_ATTACK_DISABLED,
|
||||
disabled: disabled
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
export const STORE_PROFILE = 'STORE_PROFILE';
|
||||
export const STORE_USERNAME = 'STORE_USERNAME';
|
||||
export const STORE_GOLD = 'STORE_GOLD';
|
||||
export const STORE_RECRUITS = 'STORE_RECRUITS';
|
||||
export const STORE_SOLDIERS = 'STORE_SOLDIERS';
|
||||
export const STORE_SPIES = 'STORE_SPIES';
|
||||
export const STORE_SCIENTISTS = 'STORE_SCIENTISTS';
|
||||
|
||||
export const storeProfile = (username, gold, recruits, soldiers, spies, scientists) => {
|
||||
return {
|
||||
type: STORE_PROFILE,
|
||||
username: username,
|
||||
gold: gold,
|
||||
recruits: recruits,
|
||||
soldiers: soldiers,
|
||||
spies: spies,
|
||||
scientists: scientists
|
||||
};
|
||||
}
|
||||
|
||||
export const storeUsername = (username) => {
|
||||
return {
|
||||
type: STORE_USERNAME,
|
||||
username: username
|
||||
};
|
||||
}
|
||||
|
||||
export const storeGold = (gold) => {
|
||||
return {
|
||||
type: STORE_GOLD,
|
||||
gold: gold
|
||||
};
|
||||
}
|
||||
|
||||
export const storeRecruits = (recruits) => {
|
||||
return {
|
||||
type: STORE_RECRUITS,
|
||||
recruits: recruits
|
||||
};
|
||||
}
|
||||
|
||||
export const storeSoldiers = (soldiers) => {
|
||||
return {
|
||||
type: STORE_SOLDIERS,
|
||||
soldiers: soldiers
|
||||
};
|
||||
}
|
||||
|
||||
export const storeSpies = (spies) => {
|
||||
return {
|
||||
type: STORE_SPIES,
|
||||
spies: spies
|
||||
};
|
||||
}
|
||||
|
||||
export const storeScientists = (scientists) => {
|
||||
return {
|
||||
type: STORE_SCIENTISTS,
|
||||
scientists: scientists
|
||||
};
|
||||
}
|
||||
@@ -59,6 +59,7 @@ export default class App extends React.Component {
|
||||
{ GA.init() && <GA.RouteTracker /> }
|
||||
<Switch>
|
||||
<LazyRoute exact path='/' component={() => import('./pages/home.jsx')} />
|
||||
|
||||
<LazyRoute path='/signup' component={() => import('./pages/signup.jsx')} />
|
||||
<LazyRoute path='/login' component={() => import('./pages/login.jsx')} />
|
||||
<LazyRoute path='/passwordchange' component={() => import('./pages/password_change.jsx')} />
|
||||
@@ -67,6 +68,7 @@ export default class App extends React.Component {
|
||||
|
||||
<LazyRoute path='/profile' component={() => import('./pages/profile.jsx')} />
|
||||
<LazyRoute path='/ladder' component={() => import('./pages/ladder.jsx')} />
|
||||
<LazyRoute path='/combatlog' component={() => import('./pages/combat_log.jsx')} />
|
||||
|
||||
<LazyRoute path='*' component={() => import('./pages/page_not_found.jsx')} />
|
||||
</Switch>
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import queryString from 'query-string';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
//panels
|
||||
import CommonLinks from '../panels/common_links.jsx';
|
||||
import PagedCombatLog from '../panels/paged_combat_log.jsx';
|
||||
|
||||
class CombatLog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
let params = queryString.parse(props.location.search);
|
||||
|
||||
this.state = {
|
||||
params: params,
|
||||
start: parseInt(params.log) || 0,
|
||||
length: parseInt(params.length) || 20,
|
||||
|
||||
fetch: null,
|
||||
|
||||
warning: ''
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.loggedIn) {
|
||||
this.props.history.replace('/login');
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (JSON.stringify(this.state) !== JSON.stringify(prevState)) {
|
||||
this.state.fetch();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let warningStyle = {
|
||||
display: this.state.warning.length > 0 ? 'flex' : 'none'
|
||||
};
|
||||
|
||||
let ButtonHeader = this.buttonHeader.bind(this);
|
||||
|
||||
return (
|
||||
<div className='panel'>
|
||||
<div className='sidePanelPage'>
|
||||
<div className='sidePanel'>
|
||||
<CommonLinks />
|
||||
</div>
|
||||
|
||||
<div className='mainPanel'>
|
||||
<div className='warning' style={warningStyle}>
|
||||
<p>{this.state.warning}</p>
|
||||
</div>
|
||||
|
||||
<ButtonHeader />
|
||||
<PagedCombatLog
|
||||
setWarning={this.setWarning.bind(this)}
|
||||
username={this.props.username}
|
||||
start={this.state.start}
|
||||
length={this.state.length}
|
||||
getFetch={this.getFetch.bind(this)}
|
||||
onReceived={this.onReceived.bind(this)}
|
||||
/>
|
||||
<ButtonHeader />
|
||||
</div>
|
||||
</div>
|
||||
</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}`);
|
||||
}
|
||||
}
|
||||
|
||||
setWarning(s) {
|
||||
this.setState({ warning: s });
|
||||
}
|
||||
};
|
||||
|
||||
CombatLog.propTypes = {
|
||||
username: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
const mapStoreToProps = (store) => {
|
||||
return {
|
||||
username: store.account.username,
|
||||
loggedIn: store.account.id !== 0
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
//
|
||||
};
|
||||
};
|
||||
|
||||
CombatLog = connect(mapStoreToProps, mapDispatchToProps)(CombatLog);
|
||||
|
||||
export default CombatLog;
|
||||
@@ -1,23 +1,28 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter, Link } from 'react-router-dom';
|
||||
|
||||
//panels
|
||||
import CommonLinks from '../panels/common_links.jsx';
|
||||
import Blurb from '../panels/blurb.jsx';
|
||||
import NewsPanel from '../panels/news_panel.jsx';
|
||||
import News from '../panels/news.jsx';
|
||||
|
||||
class Home extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
//
|
||||
warning: '', //TODO: unified warning?
|
||||
fetch: null
|
||||
};
|
||||
}
|
||||
|
||||
//rendering function
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
this.state.fetch();
|
||||
}
|
||||
|
||||
render() {
|
||||
//return the home page
|
||||
let warningStyle = {
|
||||
display: this.state.warning.length > 0 ? 'flex' : 'none'
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='page'>
|
||||
<div className='sidePanelPage'>
|
||||
@@ -26,29 +31,23 @@ class Home extends React.Component {
|
||||
</div>
|
||||
|
||||
<div className='mainPanel'>
|
||||
<div className='warning' style={warningStyle}>
|
||||
<p>{this.state.warning}</p>
|
||||
</div>
|
||||
|
||||
<h1 className='centered'>About</h1>
|
||||
<Blurb />
|
||||
<h1 className='centered'>News</h1>
|
||||
<NewsPanel />
|
||||
<News setWarning={this.setWarning.bind(this)} getFetch={ (fn) => this.setState({ fetch: fn }) } />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStoreToProps(store) {
|
||||
return {
|
||||
id: store.account.id
|
||||
setWarning(s) {
|
||||
this.setState({ warning: s });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
Home = connect(mapStoreToProps, mapDispatchToProps)(Home);
|
||||
|
||||
export default withRouter(Home);
|
||||
export default Home;
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import queryString from 'query-string';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
import CommonLinks from '../panels/common_links.jsx';
|
||||
import PagedLadder from '../panels/paged_ladder.jsx';
|
||||
@@ -38,7 +37,12 @@ class Ladder extends React.Component {
|
||||
<div className='mainPanel'>
|
||||
<h1 className='centered'>Game Ladder</h1>
|
||||
<ButtonHeader />
|
||||
<PagedLadder start={this.state.start} length={this.state.length} getFetch={this.getFetch.bind(this)} onReceived={this.onReceived.bind(this)} />
|
||||
<PagedLadder
|
||||
start={this.state.start}
|
||||
length={this.state.length}
|
||||
getFetch={this.getFetch.bind(this)}
|
||||
onReceived={this.onReceived.bind(this)}
|
||||
/>
|
||||
<ButtonHeader />
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,6 +97,6 @@ class Ladder extends React.Component {
|
||||
this.props.history.replace(`${this.props.location.pathname}?rank=${start}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default withRouter(Ladder);
|
||||
export default Ladder;
|
||||
@@ -15,7 +15,7 @@ class Login extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className='page constrained'>
|
||||
<LoginPanel onSubmit={() => this.props.history.push('/profile')} />
|
||||
<LoginPanel onSuccess={(msg) => this.props.history.push('/profile')} />
|
||||
<Link to='/' className='centered'>Return Home</Link>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,13 +4,16 @@ import { withRouter, Link } from 'react-router-dom';
|
||||
class PageNotFound extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
this.state = {
|
||||
//
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
let style = {
|
||||
justifyContent: 'center'
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='page centered' style={style}>
|
||||
<h1>Page Not Found</h1>
|
||||
@@ -18,6 +21,6 @@ class PageNotFound extends React.Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default withRouter(PageNotFound);
|
||||
@@ -9,13 +9,12 @@ class PasswordChange extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
changeSent: false,
|
||||
changeMsg: ''
|
||||
changed: ''
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.id) {
|
||||
if (!this.props.loggedIn) {
|
||||
this.props.history.push('/');
|
||||
}
|
||||
}
|
||||
@@ -23,13 +22,13 @@ class PasswordChange extends React.Component {
|
||||
render() {
|
||||
let Panel;
|
||||
|
||||
if (!this.state.changeSent) {
|
||||
if (!this.state.changed) {
|
||||
Panel = () => {
|
||||
return (<PasswordChangePanel onPasswordChange={(msg) => this.setState({ changeSent: true, changeMsg: msg }) } />);
|
||||
return (<PasswordChangePanel onSuccess={(msg) => this.setState({ changed: msg }) } />);
|
||||
}
|
||||
} else {
|
||||
Panel = () => {
|
||||
return (<p>{this.state.changeMsg}</p>);
|
||||
return (<p>{this.state.changed}</p>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,17 +41,17 @@ class PasswordChange extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
function mapStoreToProps(store) {
|
||||
const mapStoreToProps = (store) => {
|
||||
return {
|
||||
id: store.account.id
|
||||
}
|
||||
}
|
||||
loggedIn: store.account.id !== 0
|
||||
};
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
//
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
PasswordChange = connect(mapStoreToProps, mapDispatchToProps)(PasswordChange);
|
||||
|
||||
|
||||
@@ -8,21 +8,20 @@ class PasswordRecover extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
recoverSent: false,
|
||||
recoverMsg: ''
|
||||
recovered: ''
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let Panel;
|
||||
|
||||
if (!this.state.recoverSent) {
|
||||
if (!this.state.recovered) {
|
||||
Panel = () => {
|
||||
return (<PasswordRecoverPanel onEmailSent={(msg) => this.setState( {recoverSent: true, recoverMsg: msg} )} />);
|
||||
return (<PasswordRecoverPanel onSuccess={(msg) => this.setState( {recovered: msg} )} />);
|
||||
}
|
||||
} else {
|
||||
Panel = () => {
|
||||
return (<p>{this.state.recoverMsg}</p>);
|
||||
return (<p>{this.state.recovered}</p>);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { withRouter, Link } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import queryString from 'query-string';
|
||||
|
||||
//panels
|
||||
@@ -10,8 +9,7 @@ class PasswordReset extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
reset: false,
|
||||
resetMsg: '',
|
||||
reset: '',
|
||||
params: queryString.parse(props.location.search)
|
||||
}
|
||||
}
|
||||
@@ -21,11 +19,11 @@ class PasswordReset extends React.Component {
|
||||
|
||||
if (!this.state.reset) {
|
||||
Panel = () => {
|
||||
return (<PasswordResetPanel email={this.state.params.email} token={this.state.params.token} onPasswordReset={(msg) => this.setState( {reset: true, resetMsg: msg} )}/>);
|
||||
return (<PasswordResetPanel email={this.state.params.email} token={this.state.params.token} onSuccess={ (msg) => this.setState({reset: msg}) } />);
|
||||
}
|
||||
} else {
|
||||
Panel = () => {
|
||||
return (<p>{this.state.resetMsg}</p>);
|
||||
return (<p>{this.state.reset}</p>);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+120
-147
@@ -1,49 +1,25 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter, Link } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import queryString from 'query-string';
|
||||
|
||||
//actions
|
||||
import { storeProfile } from '../../actions/profile.js';
|
||||
|
||||
//panels
|
||||
import CommonLinks from '../panels/common_links.jsx';
|
||||
import AttackButton from '../panels/attack_button.jsx';
|
||||
import Equipment from '../panels/equipment.jsx';
|
||||
import CombatLog from '../panels/combat_log.jsx';
|
||||
|
||||
class Profile extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
let params = queryString.parse(props.location.search);
|
||||
|
||||
this.state = {
|
||||
params: params,
|
||||
|
||||
username: '',
|
||||
gold: 0,
|
||||
recruits: 0,
|
||||
soldiers: 0,
|
||||
spies: 0,
|
||||
scientists: 0,
|
||||
|
||||
warning: '',
|
||||
|
||||
//combat log
|
||||
start: params.log,
|
||||
|
||||
//equipment
|
||||
fetchStatistics: null,
|
||||
fetchEquipment: null
|
||||
params: queryString.parse(props.location.search),
|
||||
warning: '', //TODO: unified warning?
|
||||
};
|
||||
|
||||
this.sendRequest('/profilerequest', this.state.params.username ? this.state.params.username : this.props.username);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (JSON.stringify(this.state) !== JSON.stringify(prevState)) {
|
||||
// if (this.state.fetchStatistics) this.state.fetchStatistics();
|
||||
// if (this.state.fetchEquipment) this.state.fetchEquipment();
|
||||
}
|
||||
this.sendRequest('/profilerequest', {username: this.state.params.username ? this.state.params.username : this.props.account.username});
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -54,8 +30,8 @@ class Profile extends React.Component {
|
||||
//side panel stuff
|
||||
let SidePanel;
|
||||
|
||||
if (this.props.id) {
|
||||
if (this.props.username === this.state.username) {
|
||||
if (this.props.account.id) {
|
||||
if (this.props.account.username === this.props.profile.username) {
|
||||
SidePanel = this.MyProfileSidePanel.bind(this);
|
||||
} else {
|
||||
SidePanel = this.NotMyProfileSidePanel.bind(this);
|
||||
@@ -67,13 +43,12 @@ class Profile extends React.Component {
|
||||
//main panel
|
||||
let MainPanel;
|
||||
|
||||
if (this.props.id) {
|
||||
if (this.props.account.id) {
|
||||
//logged in
|
||||
if (this.state.username === this.props.username) {
|
||||
if (this.props.account.username === this.props.profile.username) {
|
||||
MainPanel = this.MyProfileMainPanel.bind(this);
|
||||
} else {
|
||||
//not logged in
|
||||
if (this.state.username !== '') {
|
||||
if (this.props.profile.username) {
|
||||
MainPanel = this.NotMyProfileMainPanel.bind(this);
|
||||
} else {
|
||||
MainPanel = this.ProfileNotFoundMainPanel.bind(this);
|
||||
@@ -81,7 +56,7 @@ class Profile extends React.Component {
|
||||
}
|
||||
} else {
|
||||
//not logged in
|
||||
if (this.state.username !== '') {
|
||||
if (this.props.profile.username) {
|
||||
MainPanel = this.LoggedOutMainPanel.bind(this);
|
||||
} else {
|
||||
MainPanel = this.ProfileNotFoundMainPanel.bind(this);
|
||||
@@ -107,23 +82,17 @@ class Profile extends React.Component {
|
||||
}
|
||||
|
||||
//gameplay functions
|
||||
sendRequest(url, username = this.props.username, role = '') { //NOTE: merged all requests here
|
||||
//request this profile's info, using my credentials
|
||||
let formData = new FormData();
|
||||
|
||||
formData.append('id', this.props.id);
|
||||
formData.append('token', this.props.token);
|
||||
|
||||
formData.append('username', username);
|
||||
formData.append('role', role);
|
||||
|
||||
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);
|
||||
this.storeProfile(
|
||||
|
||||
this.props.storeProfile(
|
||||
json.username,
|
||||
json.gold,
|
||||
json.recruits,
|
||||
@@ -136,27 +105,18 @@ class Profile extends React.Component {
|
||||
this.setWarning(xhr.responseText);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//send
|
||||
xhr.open('POST', url, true);
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
storeProfile(username, gold, recruits, soldiers, spies, scientists) {
|
||||
this.setState({
|
||||
username: username,
|
||||
gold: gold,
|
||||
recruits: recruits,
|
||||
soldiers: soldiers,
|
||||
spies: spies,
|
||||
scientists: scientists
|
||||
});
|
||||
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
xhr.send(JSON.stringify({
|
||||
id: this.props.account.id,
|
||||
token: this.props.account.token,
|
||||
...args
|
||||
}));
|
||||
}
|
||||
|
||||
//panel functions
|
||||
MyProfileSidePanel() {
|
||||
//return the side panel
|
||||
return (
|
||||
<div className='sidePanel'>
|
||||
<CommonLinks />
|
||||
@@ -171,52 +131,50 @@ class Profile extends React.Component {
|
||||
<div className='table noCollapse'>
|
||||
<div className='row'>
|
||||
<p className='col'>Username:</p>
|
||||
<p className='col'>{this.state.username}</p>
|
||||
<p className='col'>{this.props.profile.username}</p>
|
||||
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Gold:</p>
|
||||
<p className='col'>{this.state.gold}</p>
|
||||
<div className='col' style={{flex: '2 1 1.5%'}}>(+1 gold for each recruit every half hour)</div>
|
||||
<p className='col'>{this.props.profile.gold}</p>
|
||||
|
||||
<p className='col' style={{flex: '2 1 1%'}}>(+1 gold for each recruit every half hour)</p>
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Recruits:</p>
|
||||
<p className='col'>{this.state.recruits}</p>
|
||||
<button className='col' style={{flex: '2 1 1.5%'}} onClick={() => this.sendRequest('/recruitrequest')}>Recruit More Units</button>
|
||||
<p className='col'>{this.props.profile.recruits}</p>
|
||||
|
||||
<button className='col' style={{flex: '2 1 1%'}} onClick={ () => this.sendRequest('/recruitrequest') }>Recruit More Units</button>
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Soldiers:</p>
|
||||
<p className='col'>{this.state.soldiers}</p>
|
||||
<button className='col' onClick={() => this.sendRequest('/trainrequest', this.props.username, 'soldier')}>Train Soldier (100 gold)</button>
|
||||
<button className='col' onClick={() => this.sendRequest('/untrainrequest', this.props.username, 'soldier')}>Untrain Soldier</button>
|
||||
<p className='col'>{this.props.profile.soldiers}</p>
|
||||
|
||||
<button className='col' onClick={ () => this.sendRequest('/trainrequest', {role: 'soldier'}) }>Train Soldier (100 gold)</button>
|
||||
<button className='col' onClick={ () => this.sendRequest('/untrainrequest', {role: 'soldier'}) }>Untrain Soldier</button>
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Spies:</p>
|
||||
<p className='col'>{this.state.spies}</p>
|
||||
<button className='col' onClick={() => this.sendRequest('/trainrequest', this.props.username, 'spy')}>Train Spy (200 gold)</button>
|
||||
<button className='col' onClick={() => this.sendRequest('/untrainrequest', this.props.username, 'spy')}>Untrain Spy</button>
|
||||
<p className='col'>{this.props.profile.spies}</p>
|
||||
|
||||
<button className='col' onClick={ () => this.sendRequest('/trainrequest', {role: 'spy'}) }>Train Spy (200 gold)</button>
|
||||
<button className='col' onClick={ () => this.sendRequest('/untrainrequest', {role: 'spy'}) }>Untrain Spy</button>
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Scientists:</p>
|
||||
<p className='col'>{this.state.scientists}</p>
|
||||
<button className='col' onClick={() => this.sendRequest('/trainrequest', this.props.username, 'scientist')}>Train Scientist (120 gold)</button>
|
||||
<button className='col' onClick={() => this.sendRequest('/untrainrequest', this.props.username, 'scientist')}>Untrain Scientist</button>
|
||||
<p className='col'>{this.props.profile.scientists}</p>
|
||||
|
||||
<button className='col' onClick={ () => this.sendRequest('/trainrequest', {role: 'scientist'}) }>Train Scientist (120 gold)</button>
|
||||
<button className='col' onClick={ () => this.sendRequest('/untrainrequest', {role: 'scientist'}) }>Untrain Scientist</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<h1 className='centered'>Equipment</h1>
|
||||
<Equipment username={this.props.username} token={this.props.token} scientists={1} getFetchSattistics={ (fn) => this.setState({ fetchStatistics: fn }) } getFetchEquipment={ (fn) => this.setState({ fetchEquipment: fn}) } />
|
||||
|
||||
<br />
|
||||
<h1 className='centered'>Combat Log</h1>
|
||||
<CombatLog username={this.props.username} start={this.state.start} length={this.state.length} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -225,7 +183,12 @@ class Profile extends React.Component {
|
||||
//return the side panel
|
||||
return (
|
||||
<div className='sidePanel'>
|
||||
<CommonLinks onClickProfile={() => {e.preventDefault(); this.sendRequest('/profilerequest', this.props.username); this.setWarning(''); this.props.history.push('/profile');}} />
|
||||
<CommonLinks onClickProfile={(e) => {
|
||||
e.preventDefault();
|
||||
this.sendRequest('/profilerequest', {username: this.props.account.username});
|
||||
this.setWarning('');
|
||||
this.props.history.push('/profile');
|
||||
}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -233,47 +196,60 @@ class Profile extends React.Component {
|
||||
NotMyProfileMainPanel() {
|
||||
return (
|
||||
<div className='panel'>
|
||||
<h1 className='centered'>{this.state.username}'s Kingdom</h1>
|
||||
<h1 className='centered'>{this.props.profile.username}'s Kingdom</h1>
|
||||
<div className='table noCollapse'>
|
||||
<div className='row'>
|
||||
<p className='col'>Username:</p>
|
||||
<p className='col'>{this.state.username}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.username}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Gold:</p>
|
||||
<p className='col'>{this.state.gold}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.gold}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Recruits:</p>
|
||||
<p className='col'>{this.state.recruits}</p>
|
||||
<AttackButton className='col' style={{flex: '2 1 1.5%'}} setWarning={this.setWarning.bind(this)} attacker={this.props.username} defender={this.state.username} token={this.props.token} />
|
||||
<p className='col'>{this.props.profile.recruits}</p>
|
||||
|
||||
<AttackButton
|
||||
className='col'
|
||||
style={{flex: '2 1 1%'}}
|
||||
setWarning={this.setWarning.bind(this)}
|
||||
attacker={this.props.account.username}
|
||||
defender={this.props.profile.username}
|
||||
token={this.props.account.token}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Soldiers:</p>
|
||||
<p className='col'>{this.state.soldiers}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.soldiers}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Spies:</p>
|
||||
<p className='col'>{this.state.spies}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.spies}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Scientists:</p>
|
||||
<p className='col'>{this.state.scientists}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.scientists}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -291,48 +267,54 @@ class Profile extends React.Component {
|
||||
LoggedOutMainPanel() {
|
||||
return (
|
||||
<div className='panel'>
|
||||
<h1 className='centered'>{this.state.username}'s Kingdom</h1>
|
||||
<h1 className='centered'>{this.props.profile.username}'s Kingdom</h1>
|
||||
<div className='table noCollapse'>
|
||||
<div className='row'>
|
||||
<p className='col'>Username:</p>
|
||||
<p className='col'>{this.state.username}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.username}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Gold:</p>
|
||||
<p className='col'>{this.state.gold}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.gold}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Recruits:</p>
|
||||
<p className='col'>{this.state.recruits}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.recruits}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Soldiers:</p>
|
||||
<p className='col'>{this.state.soldiers}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.soldiers}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Spies:</p>
|
||||
<p className='col'>{this.state.spies}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.spies}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
|
||||
<div className='row'>
|
||||
<p className='col'>Scientists:</p>
|
||||
<p className='col'>{this.state.scientists}</p>
|
||||
<div className='col'></div>
|
||||
<div className='col'></div>
|
||||
<p className='col'>{this.props.profile.scientists}</p>
|
||||
|
||||
<div className='col' />
|
||||
<div className='col' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -341,38 +323,29 @@ class Profile extends React.Component {
|
||||
|
||||
ProfileNotFoundMainPanel() {
|
||||
return (
|
||||
<div className='page' />
|
||||
<div className='page'>
|
||||
<p className='centered'>Profile Not Found!</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
setWarning(s) {
|
||||
this.setState({
|
||||
warning: s
|
||||
});
|
||||
this.setState({ warning: s });
|
||||
}
|
||||
}
|
||||
|
||||
Profile.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
email: PropTypes.string.isRequired,
|
||||
username: PropTypes.string.isRequired,
|
||||
token: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
function mapStoreToProps(store) {
|
||||
const mapStoreToProps = (store) => {
|
||||
return {
|
||||
id: store.account.id,
|
||||
email: store.account.email,
|
||||
username: store.account.username,
|
||||
token: store.account.token
|
||||
}
|
||||
}
|
||||
account: store.account,
|
||||
profile: store.profile,
|
||||
};
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
//
|
||||
}
|
||||
}
|
||||
storeProfile: (username, gold, recruits, soldiers, spies, scientists) => dispatch(storeProfile(username, gold, recruits, soldiers, spies, scientists))
|
||||
};
|
||||
};
|
||||
|
||||
Profile = connect(mapStoreToProps, mapDispatchToProps)(Profile);
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ class Signup extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
signupSent: false,
|
||||
signupMsg: ''
|
||||
signedUp: ''
|
||||
}
|
||||
|
||||
//TODO: referral links
|
||||
@@ -18,13 +17,13 @@ class Signup extends React.Component {
|
||||
render() {
|
||||
let Panel;
|
||||
|
||||
if (!this.state.signupSent) {
|
||||
if (!this.state.signedUp) {
|
||||
Panel = () => {
|
||||
return (<SignupPanel onSignup={(msg) => this.setState( {signupSent: true, signupMsg: msg} )} />);
|
||||
return (<SignupPanel onSuccess={ (msg) => this.setState({signedUp: msg}) } />);
|
||||
}
|
||||
} else {
|
||||
Panel = () => {
|
||||
return (<p>{this.state.signupMsg}</p>);
|
||||
return (<p className='centered'>{this.state.signedUp}</p>);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -21,5 +21,5 @@ export default class Blurb extends React.Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
//TODO: incomplete
|
||||
|
||||
class Equipment extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { LOGIN, LOGOUT, SESSIONCHANGE } from "../actions/accounts.js";
|
||||
import { LOGIN, LOGOUT, SESSION_CHANGE } from "../actions/account.js";
|
||||
|
||||
const initialStore = {
|
||||
id: 0,
|
||||
@@ -7,7 +7,7 @@ const initialStore = {
|
||||
token: 0
|
||||
};
|
||||
|
||||
export function accountReducer(store = initialStore, action) {
|
||||
export const accountReducer = (store = initialStore, action) => {
|
||||
switch(action.type) {
|
||||
case LOGIN: {
|
||||
let newStore = JSON.parse(JSON.stringify(initialStore));
|
||||
@@ -23,7 +23,7 @@ export function accountReducer(store = initialStore, action) {
|
||||
case LOGOUT:
|
||||
return initialStore;
|
||||
|
||||
case SESSIONCHANGE: {
|
||||
case SESSION_CHANGE: {
|
||||
let newStore = JSON.parse(JSON.stringify(store));
|
||||
|
||||
newStore.token = action.token;
|
||||
@@ -33,6 +33,6 @@ export function accountReducer(store = initialStore, action) {
|
||||
|
||||
default:
|
||||
return store;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import { SET_ATTACK_DISABLED } from '../actions/combat.js';
|
||||
|
||||
const initialStore = {
|
||||
attackDisabled: false
|
||||
};
|
||||
|
||||
export function combatReducer(store = initialStore, action) {
|
||||
switch(action.type) {
|
||||
case SET_ATTACK_DISABLED: {
|
||||
let newStore = JSON.parse(JSON.stringify(initialStore));
|
||||
newStore.attackDisabled = action.disabled;
|
||||
return newStore;
|
||||
}
|
||||
|
||||
default:
|
||||
return store;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import {
|
||||
STORE_PROFILE,
|
||||
STORE_USERNAME,
|
||||
STORE_GOLD,
|
||||
STORE_RECRUITS,
|
||||
STORE_SOLDIERS,
|
||||
STORE_SPIES,
|
||||
STORE_SCIENTISTS
|
||||
} from '../actions/profile.js';
|
||||
|
||||
const initialStore = {
|
||||
username: '',
|
||||
gold: 0,
|
||||
recruits: 0,
|
||||
soldiers: 0,
|
||||
spies: 0,
|
||||
scientists: 0
|
||||
};
|
||||
|
||||
export const profileReducer = (store = initialStore, action) => {
|
||||
let newStore = JSON.parse(JSON.stringify(store));
|
||||
|
||||
switch(action.type) {
|
||||
case STORE_PROFILE:
|
||||
newStore.username = action.username;
|
||||
newStore.gold = action.gold;
|
||||
newStore.recruits = action.recruits;
|
||||
newStore.soldiers = action.soldiers;
|
||||
newStore.spies = action.spies;
|
||||
newStore.scientists = action.scientists;
|
||||
break;
|
||||
|
||||
case STORE_USERNAME:
|
||||
newStore.username = action.username;
|
||||
break;
|
||||
|
||||
case STORE_GOLD:
|
||||
newStore.gold = action.gold;
|
||||
break;
|
||||
|
||||
case STORE_RECRUITS:
|
||||
newStore.recruits = action.recruits;
|
||||
break;
|
||||
|
||||
case STORE_SOLDIERS:
|
||||
newStore.soldiers = action.soldiers;
|
||||
break;
|
||||
|
||||
case STORE_SPIES:
|
||||
newStore.spies = action.spies;
|
||||
break;
|
||||
|
||||
case STORE_SCIENTISTS:
|
||||
newStore.scientists = action.scientists;
|
||||
break;
|
||||
};
|
||||
|
||||
return newStore;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import { accountReducer } from './accounts.js';
|
||||
import { combatReducer } from './combat.js';
|
||||
import { accountReducer } from './account.js';
|
||||
import { profileReducer } from './profile.js';
|
||||
|
||||
//compile all reducers together
|
||||
export default combineReducers({
|
||||
account: accountReducer,
|
||||
/* combat: combatReducer */
|
||||
profile: profileReducer
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user