Merge branch 'auth' of Asara/sudoscientist-js-frontend into master
This commit is contained in:
commit
430a53bbd9
8 changed files with 6365 additions and 6069 deletions
12152
package-lock.json
generated
12152
package-lock.json
generated
File diff suppressed because it is too large
Load diff
17
package.json
17
package.json
|
@ -3,17 +3,18 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.18.1",
|
||||||
"github-markdown-css": "^3.0.1",
|
"github-markdown-css": "^3.0.1",
|
||||||
"react": "^16.8.6",
|
"react": "^16.10.2",
|
||||||
"react-dom": "^16.8.6",
|
"react-cookie": "^4.0.1",
|
||||||
"react-markdown": "^4.0.8",
|
"react-dom": "^16.10.2",
|
||||||
"react-redux": "^7.0.3",
|
"react-markdown": "^4.2.2",
|
||||||
"react-router-dom": "^5.0.1",
|
"react-redux": "^7.1.1",
|
||||||
|
"react-router-dom": "^5.1.2",
|
||||||
"react-scripts": "3.0.0",
|
"react-scripts": "3.0.0",
|
||||||
"redux": "^4.0.1",
|
"redux": "^4.0.4",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"semantic-ui-react": "^0.87.1"
|
"semantic-ui-react": "^0.87.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|
|
@ -17,3 +17,17 @@ export const fetchUserProfile = (user) => async (dispatch) => {
|
||||||
const response = { ...profile.data, ...test }
|
const response = { ...profile.data, ...test }
|
||||||
dispatch({ type: 'FETCH_USER', payload: response })
|
dispatch({ type: 'FETCH_USER', payload: response })
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const userLogin = (username, password) => async (dispatch) => {
|
||||||
|
const response = await sudoscientist.post('/auth/signin', {
|
||||||
|
username: username,
|
||||||
|
password: password
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (response.status === 401) {
|
||||||
|
console.log("Please check your credentials")
|
||||||
|
}
|
||||||
|
if (response.status === 200) {
|
||||||
|
dispatch({ type: 'USER_LOGIN', payload: response })
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
export default axios.create({
|
export default axios.create({
|
||||||
baseURL: 'https://api.sudoscientist.com/v1/api/'
|
baseURL: 'http://api.sudosci.test:8080/v1/api/',
|
||||||
|
withCredentials: true
|
||||||
});
|
});
|
||||||
|
|
182
src/components/AuthMenu.js
Normal file
182
src/components/AuthMenu.js
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import Cookies from 'universal-cookie';
|
||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { userLogin } from '../actions';
|
||||||
|
|
||||||
|
class AuthMenu extends Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
user_authed: false,
|
||||||
|
where_in_auth_menu: "requestUsername",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
email: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handleInputChange = this.handleInputChange.bind(this)
|
||||||
|
|
||||||
|
this.handleEmailRequestForAccountCreation = this.handleEmailRequestForAccountCreation.bind(this)
|
||||||
|
|
||||||
|
this.handlePasswordForLogin = this.handlePasswordForLogin.bind(this)
|
||||||
|
this.handlePasswordForAccountCreation = this.handlePasswordForAccountCreation.bind(this)
|
||||||
|
|
||||||
|
this.handleLogin = this.handleLogin.bind(this)
|
||||||
|
this.handleCreateAccount = this.handleCreateAccount.bind(this)
|
||||||
|
|
||||||
|
this.authMenu = this.authMenu.bind(this)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
handleInputChange(event) {
|
||||||
|
const target = event.target;
|
||||||
|
const value = target.value;
|
||||||
|
const name = target.name;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
[name]: value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEmailRequestForAccountCreation() {
|
||||||
|
this.setState(state => ({
|
||||||
|
where_in_auth_menu: "requestEmail",
|
||||||
|
auth_menu_visible: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePasswordForLogin() {
|
||||||
|
this.setState(state => ({
|
||||||
|
where_in_auth_menu: "requestPasswordForLogin",
|
||||||
|
auth_menu_visible: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePasswordForAccountCreation() {
|
||||||
|
this.setState(state => ({
|
||||||
|
where_in_auth_menu: "requestPasswordForCreation",
|
||||||
|
auth_menu_visible: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLogin() {
|
||||||
|
const cookies = new Cookies();
|
||||||
|
this.props.userLogin(this.state.username, this.state.password)
|
||||||
|
.then(res => {
|
||||||
|
this.setState(state => ({
|
||||||
|
auth_menu_visible: false
|
||||||
|
}))
|
||||||
|
this.props.close()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(console.log(cookies.getAll()))
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCreateAccount() {
|
||||||
|
this.setState(state => ({
|
||||||
|
where_in_auth_menu: "requestPasswordForCreation",
|
||||||
|
auth_menu_visible: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
authMenu() {
|
||||||
|
if (!this.props.auth_menu_visible) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { username, password, email } = this.state;
|
||||||
|
switch(this.state.where_in_auth_menu) {
|
||||||
|
case 'requestUsername':
|
||||||
|
return (
|
||||||
|
<div className="ui menu dropdown" style={{display: "inline"}}>
|
||||||
|
<div className="ui left icon input">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Username"
|
||||||
|
name="username"
|
||||||
|
value={username}
|
||||||
|
onChange={this.handleInputChange}
|
||||||
|
></input>
|
||||||
|
<i className="users icon"></i>
|
||||||
|
</div>
|
||||||
|
<div className="fluid ui buttons">
|
||||||
|
<button onClick={this.handleEmailRequestForAccountCreation} className="blue ui button">Sign Up</button>
|
||||||
|
<div className="or"></div>
|
||||||
|
<button onClick={this.handlePasswordForLogin} className="ui teal button">Sign In</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
case 'requestPasswordForLogin':
|
||||||
|
return (
|
||||||
|
<div className="ui menu dropdown" style={{display: "inline"}}>
|
||||||
|
<div className="ui left icon input">
|
||||||
|
<input
|
||||||
|
type={"password"}
|
||||||
|
placeholder="Password"
|
||||||
|
name="password"
|
||||||
|
value={password}
|
||||||
|
onChange={this.handleInputChange}
|
||||||
|
></input>
|
||||||
|
<i className="lock icon"></i>
|
||||||
|
</div>
|
||||||
|
<button onClick={this.handleLogin} className="fluid ui positive button">Log In</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
case 'requestEmail':
|
||||||
|
return (
|
||||||
|
<div className="ui menu dropdown" style={{display: "inline"}}>
|
||||||
|
<div className="ui left icon input">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="email@address.tld"
|
||||||
|
name="email"
|
||||||
|
value={email}
|
||||||
|
onChange={this.handleInputChange}
|
||||||
|
></input>
|
||||||
|
<i className="mail icon"></i>
|
||||||
|
</div>
|
||||||
|
<button onClick={this.handlePasswordForAccountCreation} className="fluid ui teal button">Next</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
case 'requestPasswordForCreation':
|
||||||
|
return (
|
||||||
|
<div className="ui menu dropdown" style={{display: "inline"}}>
|
||||||
|
<div className="ui left icon input">
|
||||||
|
<input
|
||||||
|
type={"password"}
|
||||||
|
placeholder="Password"
|
||||||
|
name="password"
|
||||||
|
value={password}
|
||||||
|
onChange={this.handleInputChange}
|
||||||
|
></input>
|
||||||
|
<i className="lock icon"></i>
|
||||||
|
</div>
|
||||||
|
<button onClick={this.handleCreateAccount} className="fluid ui positive button">Create Account!</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
this.authMenu(this.state.auth_menu_visible)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
username: state.username,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
{ userLogin }
|
||||||
|
)(AuthMenu);
|
|
@ -1,16 +1,48 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import AuthMenu from './AuthMenu';
|
||||||
|
|
||||||
class NavBar extends Component {
|
class NavBar extends Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
logged_in: false,
|
||||||
|
auth_menu_visible: false,
|
||||||
|
}
|
||||||
|
this.handleLoginDropdown = this.handleLoginDropdown.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoginDropdown() {
|
||||||
|
this.setState(state => ({
|
||||||
|
auth_menu_visible: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="ui three item secondary menu">
|
<div>
|
||||||
<NavLink exact to="/" className='item'>sudoscientist:~#</NavLink>
|
<div className="ui four item secondary menu">
|
||||||
<NavLink to="/posts/" className='item' activeClassName='active'>Posts</NavLink>
|
<NavLink exact to="/" className='item'>sudoscientist:~#</NavLink>
|
||||||
<NavLink to="/about/" className='item' activeClassName='active'>About</NavLink>
|
<NavLink to="/posts/" className='item' activeClassName='active'>Posts</NavLink>
|
||||||
</div>
|
<NavLink to="/about/" className='item' activeClassName='active'>About</NavLink>
|
||||||
|
<div onClick={this.handleLoginDropdown} className='item ui button dropdown'>
|
||||||
|
Login
|
||||||
|
<i className="dropdown icon"></i>
|
||||||
|
<AuthMenu auth_menu_visible={this.state.auth_menu_visible} close={ () => this.setState({auth_menu_visible: false})}></AuthMenu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NavBar;
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
auth: state.auth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
)(NavBar);
|
||||||
|
|
18
src/reducers/authReducer.js
Normal file
18
src/reducers/authReducer.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const initialState = {
|
||||||
|
user_logged_in: false,
|
||||||
|
username: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default (state = initialState, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'USER_LOGIN':
|
||||||
|
return {...state, ...{
|
||||||
|
username: action.payload.data.username,
|
||||||
|
user_logged_in: true
|
||||||
|
}}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,8 +1,10 @@
|
||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
import postsReducer from './postsReducer';
|
import postsReducer from './postsReducer';
|
||||||
import userReducer from './userReducer';
|
import userReducer from './userReducer';
|
||||||
|
import authReducer from './authReducer';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
posts: postsReducer,
|
posts: postsReducer,
|
||||||
user: userReducer
|
user: userReducer,
|
||||||
|
auth: authReducer
|
||||||
});
|
});
|
||||||
|
|
Reference in a new issue