Update readme, add stack+support. Add redis env vars. Add disable registration flag

This commit is contained in:
Daniel Mason 2021-03-28 10:39:08 +13:00
parent dc1a2df968
commit feb2ac37da
Signed by: idanoo
GPG key ID: 387387CDBC02F132
14 changed files with 367 additions and 100 deletions

View file

@ -2,14 +2,12 @@ import './App.css';
import Home from './Components/Pages/Home';
import About from './Components/Pages/About';
import Login from './Components/Pages/Login';
import Settings from './Components/Pages/Settings';
import Register from './Components/Pages/Register';
import Navigation from './Components/Navigation';
import { Route, Switch, HashRouter } from 'react-router-dom';
import { Route, Switch } from 'react-router-dom';
import { connect } from "react-redux";
import { ToastProvider } from 'react-toast-notifications';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
function mapStateToProps(state) {
@ -28,17 +26,16 @@ function mapDispatchToProps(dispatch) {
const App = () => {
let exact = true
return (
<HashRouter>
<ToastProvider autoDismiss="true" autoDismissTimeout="5000" placement="bottom-right">
<Navigation />
<Switch>
<Route exact={exact} path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
</Switch>
</ToastProvider>
</HashRouter>
<div>
<Navigation />
<Switch>
<Route exact={exact} path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/settings" component={Settings} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
</Switch>
</div>
);
}

View file

@ -0,0 +1 @@
// https://stackoverflow.com/questions/38397653/redux-what-is-the-correct-place-to-save-cookie-after-login-request

View file

@ -0,0 +1,45 @@
import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { persistStore } from 'redux-persist';
class AppProvider extends Component {
static propTypes = {
store: PropTypes.object.isRequired,
children: PropTypes.node
}
constructor(props) {
super(props);
this.state = { rehydrated: false };
}
componentWillMount() {
const opts = {
whitelist: ['user'] // <-- Your auth/user reducer storing the cookie
};
persistStore(this.props.store, opts, () => {
this.setState({ rehydrated: true });
});
}
render() {
if (!this.state.rehydrated) {
return null;
}
return (
<Provider store={this.props.store}>
{this.props.children}
</Provider>
);
}
}
AppProvider.propTypes = {
store: PropTypes.object.isRequired,
children: PropTypes.node
}
export default AppProvider;

View file

@ -2,7 +2,7 @@ import React from 'react';
import '../../App.css';
import './Login.css';
import { Button } from 'reactstrap';
import { Formik, Form, Field } from 'formik';
import { useToasts } from 'react-toast-notifications';
function withToast(Component) {
@ -29,16 +29,15 @@ class Login extends React.Component {
this.setState({password: event.target.value});
}
handleSubmit(event) {
event.preventDefault();
handleSubmit(values) {
this.setState({loading: true});
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
timeout: 5000,
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
username: values.username,
password: values.password,
})
};
const apiUrl = process.env.REACT_APP_API_URL + '/api/v1/login';
@ -47,7 +46,7 @@ class Login extends React.Component {
.then((function(data) {
if (data.error) {
this.props.addToast(data.error, { appearance: 'error' });
} else {
} else if (data.token) {
this.props.addToast(data.token, { appearance: 'success' });
}
this.setState({loading: false});
@ -59,30 +58,35 @@ class Login extends React.Component {
}
render() {
let trueBool = true;
return (
<div className="pageWrapper">
<h1>
Login
</h1>
<div className="loginBody">
<form onSubmit={this.handleSubmit}>
<Formik
initialValues={{ username: '', password: '' }}
onSubmit={async values => this.handleSubmit(values)}
>
<Form>
<label>
Email / Username<br/>
<input
<Field
name="username"
type="text"
required={trueBool}
className="loginFields"
value={this.state.username}
onChange={this.handleUsernameChange}
/>
</label>
<br/>
<label>
Password<br/>
<input
<Field
name="password"
type="password"
required={trueBool}
className="loginFields"
value={this.state.password}
onChange={this.handlePasswordChange}
/>
</label>
<br/><br/>
@ -92,7 +96,8 @@ class Login extends React.Component {
className="loginButton"
disabled={this.state.loading}
>Login</Button>
</form>
</Form>
</Formik>
</div>
</div>
);

View file

@ -2,7 +2,6 @@ import React from 'react';
import '../../App.css';
import './Login.css';
import { Button } from 'reactstrap';
import { useToasts } from 'react-toast-notifications';
function withToast(Component) {
@ -84,64 +83,73 @@ class Register extends React.Component {
}
render() {
let trueBool = true;
return (
<div className="pageWrapper">
<h1>
Register
</h1>
<div className="loginBody">
<form onSubmit={this.handleSubmit}>
<label>
Username*<br/>
<input
type="text"
required="true"
className="loginFields"
value={this.state.username}
onChange={this.handleUsernameChange}
/>
</label>
<br/>
<label>
Email<br/>
<input
type="email"
className="loginFields"
value={this.state.email}
onChange={this.handleEmailChange}
/>
</label>
<br/>
<label>
Password<br/>
<input
type="password"
required="true"
className="loginFields"
value={this.state.password}
onChange={this.handlePasswordChange}
/>
</label>
<br/>
<label>
Password<br/>
<input
type="password"
required="true"
className="loginFields"
value={this.state.passwordconfirm}
onChange={this.handlePasswordConfirmChange}
/>
</label>
<br/><br/>
<Button
color="primary"
type="submit"
className="loginButton"
disabled={this.state.loading}
>Login</Button>
</form>
</div>
{
// TODO: Move to DB:config REGISTRATION_DISABLED=1|0
process.env.REACT_APP_REGISTRATION_DISABLED === "true" ?
<p>Registration is temporarily disabled. Please try again soon!</p>
:
<div>
<h1>
Register
</h1>
<div className="loginBody">
<form onSubmit={this.handleSubmit}>
<label>
Username*<br/>
<input
type="text"
required={trueBool}
className="loginFields"
value={this.state.username}
onChange={this.handleUsernameChange}
/>
</label>
<br/>
<label>
Email<br/>
<input
type="email"
className="loginFields"
value={this.state.email}
onChange={this.handleEmailChange}
/>
</label>
<br/>
<label>
Password<br/>
<input
type="password"
required={trueBool}
className="loginFields"
value={this.state.password}
onChange={this.handlePasswordChange}
/>
</label>
<br/>
<label>
Password<br/>
<input
type="password"
required={trueBool}
className="loginFields"
value={this.state.passwordconfirm}
onChange={this.handlePasswordConfirmChange}
/>
</label>
<br/><br/>
<Button
color="primary"
type="submit"
className="loginButton"
disabled={this.state.loading}
>Login</Button>
</form>
</div>
</div>
}
</div>
);
}

View file

View file

@ -0,0 +1,36 @@
import React from 'react';
import '../../App.css';
import './Settings.css';
import { useToasts } from 'react-toast-notifications';
function withToast(Component) {
return function WrappedComponent(props) {
const toastFuncs = useToasts()
return <Component {...props} {...toastFuncs} />;
}
}
class Settings extends React.Component {
constructor(props) {
super(props);
this.state = {username: '', password: '', loading: false};
}
render() {
return (
<div className="pageWrapper">
<h1>
Settings
</h1>
<div className="loginBody">
<p>
All the settings
</p>
</div>
</div>
);
}
}
export default withToast(Settings);

View file

@ -2,7 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom'
import { HashRouter } from 'react-router-dom'
import { ToastProvider } from 'react-toast-notifications';
import { Provider } from 'react-redux'
import { createStore } from 'redux'
@ -14,10 +15,12 @@ const goScorbbleStore = (state = false, logIn) => {
const store = createStore(goScorbbleStore);
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
<HashRouter>
<ToastProvider autoDismiss="true" autoDismissTimeout="5000" placement="bottom-right">
<Provider store={store}>
<App />
</Provider>
</ToastProvider>
</HashRouter>,
document.getElementById('root')
);