From 360bd95304eb940ce9b5b3acf660e47dcafcfcd1 Mon Sep 17 00:00:00 2001
From: Ravi Sri Ram Chowdary
Date: Sat, 26 Dec 2020 15:12:20 +0530
Subject: [PATCH 1/5] Installed redux-thunk and introduced action creators
---
package-lock.json | 5 +++++
package.json | 3 ++-
src/index.js | 5 +++--
src/store/actions/actionCreators.js | 1 +
src/store/{actions.js => actions/actionTypes.js} | 2 --
src/store/actions/theme.js | 10 ++++++++++
src/store/reducer.js | 2 +-
src/views/About.js | 4 ++--
8 files changed, 24 insertions(+), 8 deletions(-)
create mode 100644 src/store/actions/actionCreators.js
rename src/store/{actions.js => actions/actionTypes.js} (72%)
create mode 100644 src/store/actions/theme.js
diff --git a/package-lock.json b/package-lock.json
index 3aec10b..5cddcc2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11424,6 +11424,11 @@
"symbol-observable": "^1.2.0"
}
},
+ "redux-thunk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
+ "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw=="
+ },
"regenerate": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
diff --git a/package.json b/package.json
index ab17ba8..7623ecb 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"react-uwp": "^1.3.1",
- "redux": "^4.0.5"
+ "redux": "^4.0.5",
+ "redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
diff --git a/src/index.js b/src/index.js
index 6a43f52..607ba3e 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,13 +1,14 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
-import { createStore } from 'redux';
+import { createStore, applyMiddleware } from 'redux';
+import thunk from 'redux-thunk';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import reducer from './store/reducer';
-const store = createStore(reducer);
+const store = createStore(reducer, applyMiddleware(thunk));
ReactDOM.render(
diff --git a/src/store/actions/actionCreators.js b/src/store/actions/actionCreators.js
new file mode 100644
index 0000000..f494b80
--- /dev/null
+++ b/src/store/actions/actionCreators.js
@@ -0,0 +1 @@
+export { setTheme } from './theme';
diff --git a/src/store/actions.js b/src/store/actions/actionTypes.js
similarity index 72%
rename from src/store/actions.js
rename to src/store/actions/actionTypes.js
index 8c4c173..4f81b6a 100644
--- a/src/store/actions.js
+++ b/src/store/actions/actionTypes.js
@@ -1,4 +1,2 @@
-// Methods or Actions
-
// Theme related actions
export const SET_THEME = 'SET_THEME'
diff --git a/src/store/actions/theme.js b/src/store/actions/theme.js
new file mode 100644
index 0000000..25c665a
--- /dev/null
+++ b/src/store/actions/theme.js
@@ -0,0 +1,10 @@
+import * as actionTypes from './actionTypes';
+
+export const setTheme = theme => {
+ return {
+ type: actionTypes.SET_THEME,
+ payload: {
+ theme: theme
+ }
+ }
+}
diff --git a/src/store/reducer.js b/src/store/reducer.js
index 1f426c6..9fbf373 100644
--- a/src/store/reducer.js
+++ b/src/store/reducer.js
@@ -1,4 +1,4 @@
-import * as actionTypes from './actions'
+import * as actionTypes from './actions/actionTypes'
const themeDictionary = {
Midnight: {
diff --git a/src/views/About.js b/src/views/About.js
index b2a34e3..10283cc 100644
--- a/src/views/About.js
+++ b/src/views/About.js
@@ -5,7 +5,7 @@ import { getTheme } from "react-uwp/Theme";
import HyperLink from "react-uwp/HyperLink";
import DropDownMenu from "react-uwp/DropDownMenu";
import AppBarButton from "react-uwp/AppBarButton";
-import * as actionTypes from '../store/actions'
+import * as actionCreators from '../store/actions/actionCreators'
class About extends React.Component {
@@ -120,7 +120,7 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
- setTheme: (theme) => dispatch({ type: actionTypes.SET_THEME, payload: { theme: theme } })
+ setTheme: (theme) => dispatch(actionCreators.setTheme(theme))
}
}
From 1208ba5a8ec052ef4378b92e46854bd17f08739f Mon Sep 17 00:00:00 2001
From: Ravi Sri Ram Chowdary
Date: Sat, 26 Dec 2020 18:41:20 +0530
Subject: [PATCH 2/5] Moved authentication related HTTP requests to store
---
src/main/ForgotPassword.js | 55 ++++-----
src/main/ResendEmail.js | 54 ++++----
src/main/SignIn.js | 60 ++++-----
src/main/SignUp.js | 65 ++++------
src/store/actions/actionCreators.js | 6 +
src/store/actions/actionTypes.js | 6 +
src/store/actions/auth.js | 185 ++++++++++++++++++++++++++++
src/store/reducer.js | 38 +++++-
8 files changed, 319 insertions(+), 150 deletions(-)
create mode 100644 src/store/actions/auth.js
diff --git a/src/main/ForgotPassword.js b/src/main/ForgotPassword.js
index 8744e87..9496978 100644
--- a/src/main/ForgotPassword.js
+++ b/src/main/ForgotPassword.js
@@ -1,47 +1,21 @@
import * as React from "react";
import * as PropTypes from "prop-types";
import { NavLink } from "react-router-dom";
-import axios from 'axios';
-
+import { connect } from "react-redux";
import TextBox from "react-uwp/TextBox";
import AppBarButton from "react-uwp/AppBarButton";
+import * as actionCreators from '../store/actions/actionCreators';
-
-export default class ForgotPassword extends React.Component {
+class ForgotPassword extends React.Component {
constructor(props) {
super(props);
- this.state = { email: '', errMessage: '' };
+ this.state = { email: '' };
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
-
- const axiosOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/reset/request`,
- 'data': {
- 'email': this.state.email,
- }
- }
-
- axios(axiosOptions)
- .then(response => {
- this.setState({ errMessage: "Ah, Dementia. Reset mail sent!" });
- })
- .catch(error => {
- let status = error.response.status
-
- if (status === 401) {
- this.setState({
- errMessage: "User is not registered. Please sign up first.",
- errHref: "/signup"
- });
- }
- else {
- this.setState({ errMessage: "It's not you, it's us. Try again later." })
- }
- })
+ this.props.submitForgotPass(this.state.email);
}
componentDidMount() {
@@ -111,7 +85,7 @@ export default class ForgotPassword extends React.Component {
/>
- {this.state.errMessage}
+ {this.props.message}
}
@@ -124,4 +98,19 @@ export default class ForgotPassword extends React.Component {
);
}
-}
\ No newline at end of file
+}
+
+const mapStateToProps = state => {
+ return {
+ message: state.forgotPassMessage,
+ followLink: state.forgotPassFollowLink
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ submitForgotPass: email => dispatch(actionCreators.submitForgotPass(email))
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ForgotPassword);
diff --git a/src/main/ResendEmail.js b/src/main/ResendEmail.js
index c664c4f..4bc1c5b 100644
--- a/src/main/ResendEmail.js
+++ b/src/main/ResendEmail.js
@@ -1,47 +1,22 @@
import * as React from "react";
import * as PropTypes from "prop-types";
-import axios from 'axios'
-
import { NavLink } from "react-router-dom";
+import { connect } from "react-redux";
import TextBox from "react-uwp/TextBox";
import AppBarButton from "react-uwp/AppBarButton";
+import * as actionCreators from '../store/actions/actionCreators';
-export default class ResendEmail extends React.Component {
+class ResendEmail extends React.Component {
constructor(props) {
super(props);
- this.state = { email: '', errMessage: '' };
+ this.state = { email: ''};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
-
- const axiosOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/resendVerificationEmail`,
- 'data': {
- 'email': this.state.email,
- }
- }
-
- axios(axiosOptions)
- .then(response => {
- this.setState({ errMessage: "Verification mail sent!" });
- })
- .catch(error => {
- let status = error.response.status
-
- if (status === 401) {
- this.setState({
- errMessage: "User is not registered. Please sign up first.",
- errHref: "/signup"
- });
- }
- else {
- this.setState({ errMessage: "It's not you, it's us. Try again later." })
- }
- })
+ this.props.resendEmail(this.state.email);
}
componentDidMount() {
@@ -111,7 +86,7 @@ export default class ResendEmail extends React.Component {
/>
- {this.state.errMessage}
+ {this.props.message}
}
@@ -124,4 +99,19 @@ export default class ResendEmail extends React.Component {
);
}
-}
\ No newline at end of file
+}
+
+const mapStateToProps = state => {
+ return{
+ message : state.resendEmailMessage,
+ followLink: state.resendEmailFollowLink
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return{
+ resendEmail : email => dispatch(actionCreators(email))
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ResendEmail);
diff --git a/src/main/SignIn.js b/src/main/SignIn.js
index 8139f9f..5eae26a 100644
--- a/src/main/SignIn.js
+++ b/src/main/SignIn.js
@@ -1,17 +1,17 @@
import * as React from "react";
import * as PropTypes from "prop-types";
import { NavLink, Link } from "react-router-dom";
-import axios from 'axios';
-
+import { connect } from "react-redux";
import TextBox from "react-uwp/TextBox";
import AppBarButton from "react-uwp/AppBarButton";
import PasswordBox from "react-uwp/PasswordBox";
+import * as actionCreators from '../store/actions/actionCreators';
-export default class SignIn extends React.Component {
+class SignIn extends React.Component {
constructor(props) {
super(props);
- this.state = { username: '', password: '', errMessage: '', errHref: '', remember: 'false' };
+ this.state = { username: '', password: '', remember: 'false' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
@@ -27,40 +27,7 @@ export default class SignIn extends React.Component {
}
handleSubmit(event) {
-
- const axiosOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/login`,
- 'data': {
- 'username': this.state.username,
- 'password': this.state.password,
- 'remember': this.state.remember
- }
- }
-
- axios(axiosOptions)
- .then(response => {
- localStorage.setItem('access_token', response.data.access_token);
- localStorage.setItem('refresh_token', response.data.refresh_token);
- localStorage.setItem('userID', response.data.id);
- localStorage.setItem('username', response.data.username);
- window.location.pathname = "/profile";
- })
- .catch(error => {
- let status = error.response.status;
- if (status === 401) {
- this.setState({ errMessage: "Couldn't verify. Please check credentials!" });
- }
-
- if (status === 402) {
- this.setState({ errMessage: "Please verify your email before signing in. ", errHref: "/resendVerification" });
- }
-
- if (status === 403) {
- this.setState({ errMessage: "Account not found. ", errHref: "/signup" });
- }
- })
-
+ this.props.signIn(this.state.username, this.state.password, this.state.remember);
}
componentDidMount() {
@@ -159,7 +126,7 @@ export default class SignIn extends React.Component {
- {this.state.errMessage}
+ {this.props.message}
{
+ return {
+ message: state.signInMessage,
+ followLink: state.signInFollowLink
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ signIn: (username, password, remember) => dispatch(actionCreators.signIn(username, password, remember))
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(SignIn);
diff --git a/src/main/SignUp.js b/src/main/SignUp.js
index a0102eb..38e0443 100644
--- a/src/main/SignUp.js
+++ b/src/main/SignUp.js
@@ -1,18 +1,17 @@
import * as React from "react";
import * as PropTypes from "prop-types";
-import axios from 'axios';
-
import { NavLink, Link } from "react-router-dom";
+import { connect } from 'react-redux';
import TextBox from "react-uwp/TextBox";
import AppBarButton from "react-uwp/AppBarButton";
import PasswordBox from "react-uwp/PasswordBox";
+import * as actionCreators from '../store/actions/actionCreators';
-
-export default class SignUp extends React.Component {
+class SignUp extends React.Component {
constructor(props) {
super(props);
- this.state = { email: '', username: '', bio: '', password: '', confPassword: '', errMessage: '', errHref: '' };
+ this.state = { email: '', username: '', bio: '', password: '', confPassword: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
@@ -28,42 +27,7 @@ export default class SignUp extends React.Component {
}
handleSubmit(event) {
-
- if (this.state.confPassword !== this.state.password) {
- this.setState({ errMessage: "Passwords don't match" })
- }
- else {
- const axiosOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/signup`,
- 'data': {
- 'email': this.state.email,
- 'username': this.state.username,
- 'password': this.state.password,
- 'bio': this.state.bio
- }
- }
-
- axios(axiosOptions)
- .then(response => {
- this.setState({ errMessage: "Signed Up! Please verify your email!" });
- })
- .catch(error => {
- let status = error.response.status
- //console.log(error.response);
-
- if (status === 402) {
- this.setState({ errMessage: "Username is taken" });
- }
-
- else if (status === 401) {
- this.setState({ errMessage: "This email is registered with another account." });
- }
- else {
- this.setState({ errMessage: "It's not you, it's us. Try again later." })
- }
- })
- }
+ this.props.signUp(this.state.email, this.state.username, this.state.password, this.state.bio, this.state.confPassword);
}
componentDidMount() {
@@ -183,7 +147,7 @@ export default class SignUp extends React.Component {
- {this.state.errMessage}
+ {this.props.message}
}
@@ -198,4 +162,19 @@ export default class SignUp extends React.Component {
);
}
-}
\ No newline at end of file
+}
+
+const mapStateToProps = state => {
+ return {
+ message: state.signUpMessage,
+ followLink: state.signUpFollowLink
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ signUp: (email, username, password, bio, confPassword) => dispatch(actionCreators.signUp(email, username, password, bio, confPassword))
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(SignUp);
diff --git a/src/store/actions/actionCreators.js b/src/store/actions/actionCreators.js
index f494b80..0b462b9 100644
--- a/src/store/actions/actionCreators.js
+++ b/src/store/actions/actionCreators.js
@@ -1 +1,7 @@
export { setTheme } from './theme';
+export {
+ signUp,
+ signIn,
+ submitForgotPass,
+ resendEmail
+} from './auth';
diff --git a/src/store/actions/actionTypes.js b/src/store/actions/actionTypes.js
index 4f81b6a..7fff4cf 100644
--- a/src/store/actions/actionTypes.js
+++ b/src/store/actions/actionTypes.js
@@ -1,2 +1,8 @@
// Theme related actions
export const SET_THEME = 'SET_THEME'
+
+// Authentication related actions
+export const SET_SIGNUP_MESSAGE = 'SET_SIGNUP_MESSAGE'
+export const SET_SIGNIN_MESSAGE = 'SET_SIGNIN_MESSAGE'
+export const SET_FORGOT_PASS_MESSAGE = 'SET_FORGOT_PASS_MESSAGE'
+export const SET_RESEND_EMAIL_MESSAGE = 'SET_RESEND_EMAIL_MESSAGE'
diff --git a/src/store/actions/auth.js b/src/store/actions/auth.js
new file mode 100644
index 0000000..1a68e64
--- /dev/null
+++ b/src/store/actions/auth.js
@@ -0,0 +1,185 @@
+import axios from 'axios';
+import * as actionTypes from './actionTypes';
+
+// Synchronous action creator for setting sign up message
+export const setSignupMessage = (message, link) => {
+ return {
+ type: actionTypes.SET_SIGNUP_MESSAGE,
+ payload: {
+ message: message,
+ link: link
+ }
+ }
+}
+
+// Asynchronous action Creator for sign Up
+export const signUp = (email, username, password, bio, confPassword) => {
+ return dispatch => {
+
+ if (confPassword !== password) {
+ dispatch(setSignupMessage("Passwords don't match", ''))
+ }
+ else {
+ const axiosOptions = {
+ 'method': 'POST',
+ 'url': `${process.env.REACT_APP_DB_HOST}/auth/signup`,
+ 'data': {
+ 'email': email,
+ 'username': username,
+ 'password': password,
+ 'bio': bio
+ }
+ }
+
+ axios(axiosOptions)
+ .then(response => {
+ dispatch(setSignupMessage("Signed Up! Please verify your email!", ''))
+ })
+ .catch(error => {
+ let status = error.response.status
+ //console.log(error.response);
+
+ if (status === 402) {
+ dispatch(setSignupMessage("Username is taken", ''))
+ }
+ else if (status === 401) {
+ dispatch(setSignupMessage("This email is registered with another account.", ''))
+ }
+ else {
+ dispatch(setSignupMessage("It's not you, it's us. Try again later.", ''))
+ }
+ })
+ }
+ }
+}
+
+// Synchronous action creator for setting sign in message
+export const setSignInMessage = (message, link) => {
+ return {
+ type: actionTypes.SET_SIGNIN_MESSAGE,
+ payload: {
+ message: message,
+ link: link
+ }
+ }
+}
+
+// Asynchronous action creator for sign In
+export const signIn = (username, password, remember) => {
+ return dispatch => {
+
+ const axiosOptions = {
+ 'method': 'POST',
+ 'url': `${process.env.REACT_APP_DB_HOST}/auth/login`,
+ 'data': {
+ 'username': username,
+ 'password': password,
+ 'remember': remember
+ }
+ }
+
+ axios(axiosOptions)
+ .then(response => {
+ localStorage.setItem('access_token', response.data.access_token);
+ localStorage.setItem('refresh_token', response.data.refresh_token);
+ localStorage.setItem('userID', response.data.id);
+ localStorage.setItem('username', response.data.username);
+ window.location.pathname = "/profile";
+ })
+ .catch(error => {
+ let status = error.response.status;
+ if (status === 401) {
+ dispatch(setSignInMessage("Couldn't verify. Please check credentials!", ''));
+ }
+
+ if (status === 402) {
+ dispatch(setSignInMessage("Please verify your email before signing in. ", '/resendVerification'));
+ }
+
+ if (status === 403) {
+ dispatch(setSignInMessage("Account not found. ", '/signup'));
+ }
+ })
+
+ }
+}
+
+// Synchronous action creator for setting Forgot pass message
+export const setForgotPassMessage = (message, link) => {
+ return {
+ type: actionTypes.SET_FORGOT_PASS_MESSAGE,
+ payload: {
+ message: message,
+ link: link
+ }
+ }
+}
+
+// Asynchronous action creator for forgot pass handler
+export const submitForgotPass = email => {
+ return dispatch => {
+
+ const axiosOptions = {
+ 'method': 'POST',
+ 'url': `${process.env.REACT_APP_DB_HOST}/auth/reset/request`,
+ 'data': {
+ 'email': email,
+ }
+ }
+
+ axios(axiosOptions)
+ .then(response => {
+ dispatch(setForgotPassMessage("Ah, Dementia. Reset mail sent!", ''));
+ })
+ .catch(error => {
+ let status = error.response.status
+
+ if (status === 401) {
+ dispatch(setForgotPassMessage("User is not registered. Please sign up first.", "/signup"));
+ }
+ else {
+ dispatch(setForgotPassMessage("It's not you, it's us. Try again later.", ''));
+ }
+ })
+ }
+}
+
+// Synchronous action creator for setting resend email message
+export const setResendEmailMessage = (message, link) => {
+ return {
+ type: actionTypes.SET_RESEND_EMAIL_MESSAGE,
+ payload: {
+ message: message,
+ link: link
+ }
+ }
+}
+
+// Asynchronous action creator for resend email handler
+export const resendEmail = email => {
+ return dispatch => {
+
+ const axiosOptions = {
+ 'method': 'POST',
+ 'url': `${process.env.REACT_APP_DB_HOST}/auth/resendVerificationEmail`,
+ 'data': {
+ 'email': email,
+ }
+ }
+
+ axios(axiosOptions)
+ .then(response => {
+ dispatch(setResendEmailMessage("Verification mail sent!"));
+ })
+ .catch(error => {
+ let status = error.response.status
+
+ if (status === 401) {
+ dispatch(setResendEmailMessage("User is not registered. Please sign up first.", "/signup"));
+ }
+ else {
+ dispatch(setResendEmailMessage("It's not you, it's us. Try again later.", ''));
+ }
+ })
+ }
+}
diff --git a/src/store/reducer.js b/src/store/reducer.js
index 9fbf373..166a929 100644
--- a/src/store/reducer.js
+++ b/src/store/reducer.js
@@ -80,23 +80,55 @@ else {
// Initial State
const initialState = {
Theme: { ...presetTheme },
- themeDict: themeDictionary
+ themeDict: themeDictionary,
+ signUpMessage: '',
+ signUpFollowLink: '',
+ signInMessage: '',
+ signInFollowLink: '',
+ forgotPassMessage: '',
+ forgotPassFollowLink: '',
+ resendEmailMessage: '',
+ resendEmailFollowLink: ''
}
function reducer(state = initialState, action) {
switch (action.type) {
case actionTypes.SET_THEME:
localStorage.setItem("themeSet", JSON.stringify(action.payload.theme))
- if (action.payload.theme === "Auto-change")
+ if (action.payload.theme === "Auto-change")
return {
...initialState,
Theme: { ...themeDictionary[timeSlot] }
}
- else
+ else
return {
...initialState,
Theme: { ...themeDictionary[action.payload.theme] }
}
+ case actionTypes.SET_SIGNUP_MESSAGE:
+ return {
+ ...initialState,
+ signUpMessage: action.payload.message,
+ signUpFollowLink: action.payload.link
+ }
+ case actionTypes.SET_SIGNIN_MESSAGE:
+ return {
+ ...initialState,
+ signInMessage: action.payload.message,
+ signInFollowLink: action.payload.link
+ }
+ case actionTypes.SET_FORGOTPASS_MESSAGE:
+ return {
+ ...initialState,
+ forgotPassMessage: action.payload.message,
+ forgotPassFollowLink: action.payload.link
+ }
+ case actionTypes.SET_RESEND_EMAIL_MESSAGE:
+ return {
+ ...initialState,
+ resendEmailMessage: action.payload.message,
+ resendEmailFollowLink: action.payload.link
+ }
default:
return {
...state
From 80887771d435be2d87caaab879a73a8c435dcfea Mon Sep 17 00:00:00 2001
From: Ravi Sri Ram Chowdary
Date: Sat, 26 Dec 2020 18:49:12 +0530
Subject: [PATCH 3/5] Fixed small bugs and corrected 'initialState' where it
has to be 'state' in reducer
---
src/main/ResendEmail.js | 2 +-
src/store/reducer.js | 14 +++++++-------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/main/ResendEmail.js b/src/main/ResendEmail.js
index 4bc1c5b..a1109ee 100644
--- a/src/main/ResendEmail.js
+++ b/src/main/ResendEmail.js
@@ -110,7 +110,7 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return{
- resendEmail : email => dispatch(actionCreators(email))
+ resendEmail : email => dispatch(actionCreators.resendEmail(email))
}
}
diff --git a/src/store/reducer.js b/src/store/reducer.js
index 166a929..2cb9774 100644
--- a/src/store/reducer.js
+++ b/src/store/reducer.js
@@ -97,35 +97,35 @@ function reducer(state = initialState, action) {
localStorage.setItem("themeSet", JSON.stringify(action.payload.theme))
if (action.payload.theme === "Auto-change")
return {
- ...initialState,
+ ...state,
Theme: { ...themeDictionary[timeSlot] }
}
else
return {
- ...initialState,
+ ...state,
Theme: { ...themeDictionary[action.payload.theme] }
}
case actionTypes.SET_SIGNUP_MESSAGE:
return {
- ...initialState,
+ ...state,
signUpMessage: action.payload.message,
signUpFollowLink: action.payload.link
}
case actionTypes.SET_SIGNIN_MESSAGE:
return {
- ...initialState,
+ ...state,
signInMessage: action.payload.message,
signInFollowLink: action.payload.link
}
- case actionTypes.SET_FORGOTPASS_MESSAGE:
+ case actionTypes.SET_FORGOT_PASS_MESSAGE:
return {
- ...initialState,
+ ...state,
forgotPassMessage: action.payload.message,
forgotPassFollowLink: action.payload.link
}
case actionTypes.SET_RESEND_EMAIL_MESSAGE:
return {
- ...initialState,
+ ...state,
resendEmailMessage: action.payload.message,
resendEmailFollowLink: action.payload.link
}
From e5f032e5c43c034cd01fb7e7c930781a08275e8e Mon Sep 17 00:00:00 2001
From: Ravi Sri Ram Chowdary
Date: Sun, 27 Dec 2020 12:26:57 +0530
Subject: [PATCH 4/5] Moved logic for logout and refreshing token to redux
---
src/store/actions/actionCreators.js | 6 ++-
src/store/actions/auth.js | 52 +++++++++++++++++++-
src/store/reducer.js | 12 +++++
src/views/CreatePost.js | 48 ++++++++----------
src/views/Movie.js | 51 ++++++++------------
src/views/Post.js | 63 +++++++++---------------
src/views/Profile.js | 75 ++++++++---------------------
7 files changed, 150 insertions(+), 157 deletions(-)
diff --git a/src/store/actions/actionCreators.js b/src/store/actions/actionCreators.js
index 0b462b9..09a9e3f 100644
--- a/src/store/actions/actionCreators.js
+++ b/src/store/actions/actionCreators.js
@@ -1,7 +1,9 @@
export { setTheme } from './theme';
-export {
+export {
signUp,
signIn,
submitForgotPass,
- resendEmail
+ resendEmail,
+ registerRefreshToken,
+ logout
} from './auth';
diff --git a/src/store/actions/auth.js b/src/store/actions/auth.js
index 1a68e64..aed27ec 100644
--- a/src/store/actions/auth.js
+++ b/src/store/actions/auth.js
@@ -1,4 +1,5 @@
import axios from 'axios';
+import createAuthRefreshInterceptor from 'axios-auth-refresh';
import * as actionTypes from './actionTypes';
// Synchronous action creator for setting sign up message
@@ -158,7 +159,7 @@ export const setResendEmailMessage = (message, link) => {
// Asynchronous action creator for resend email handler
export const resendEmail = email => {
return dispatch => {
-
+
const axiosOptions = {
'method': 'POST',
'url': `${process.env.REACT_APP_DB_HOST}/auth/resendVerificationEmail`,
@@ -183,3 +184,52 @@ export const resendEmail = email => {
})
}
}
+
+// Asynchronous action creator for registering to refresh auth-token
+export const registerRefreshToken = (axiosInstance) => {
+
+ const refreshOptions = {
+ 'method': 'POST',
+ 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`,
+ 'headers': {
+ 'Authorization': localStorage.getItem("refresh_token")
+ }
+ }
+
+ const refreshAuthLogic = failedRequest => axios(refreshOptions)
+ .then(tokenRefreshResponse => {
+ localStorage.setItem('access_token', tokenRefreshResponse.data.access_token);
+ localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token);
+ failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token;
+ return Promise.resolve();
+ });
+
+ // return refreshAuthLogic;
+ createAuthRefreshInterceptor(axiosInstance, refreshAuthLogic);
+}
+
+// Asynchronous action creator for logout
+export const logout = () => {
+
+ const axiosOptions = {
+ 'method': 'POST',
+ 'url': `${process.env.REACT_APP_DB_HOST}/auth/logout`,
+ headers: {
+ 'Authorization': localStorage.getItem("access_token")
+ }
+ }
+
+ registerRefreshToken(axios);
+
+ axios(axiosOptions)
+ .then(response => {
+ //console.log(response.data);
+ localStorage.removeItem("username");
+ localStorage.removeItem("userID");
+ localStorage.removeItem("access_token");
+ localStorage.removeItem("refresh_token");
+ // localStorage.clear(); Else it removes the saved theme also
+ window.location.pathname = "/";
+ })
+ .catch(error => { /* console.log(error) */ })
+}
diff --git a/src/store/reducer.js b/src/store/reducer.js
index 2cb9774..97e92b9 100644
--- a/src/store/reducer.js
+++ b/src/store/reducer.js
@@ -79,20 +79,27 @@ else {
// Initial State
const initialState = {
+
Theme: { ...presetTheme },
themeDict: themeDictionary,
+
signUpMessage: '',
signUpFollowLink: '',
+
signInMessage: '',
signInFollowLink: '',
+
forgotPassMessage: '',
forgotPassFollowLink: '',
+
resendEmailMessage: '',
resendEmailFollowLink: ''
+
}
function reducer(state = initialState, action) {
switch (action.type) {
+
case actionTypes.SET_THEME:
localStorage.setItem("themeSet", JSON.stringify(action.payload.theme))
if (action.payload.theme === "Auto-change")
@@ -105,30 +112,35 @@ function reducer(state = initialState, action) {
...state,
Theme: { ...themeDictionary[action.payload.theme] }
}
+
case actionTypes.SET_SIGNUP_MESSAGE:
return {
...state,
signUpMessage: action.payload.message,
signUpFollowLink: action.payload.link
}
+
case actionTypes.SET_SIGNIN_MESSAGE:
return {
...state,
signInMessage: action.payload.message,
signInFollowLink: action.payload.link
}
+
case actionTypes.SET_FORGOT_PASS_MESSAGE:
return {
...state,
forgotPassMessage: action.payload.message,
forgotPassFollowLink: action.payload.link
}
+
case actionTypes.SET_RESEND_EMAIL_MESSAGE:
return {
...state,
resendEmailMessage: action.payload.message,
resendEmailFollowLink: action.payload.link
}
+
default:
return {
...state
diff --git a/src/views/CreatePost.js b/src/views/CreatePost.js
index 50c74da..fb0a43f 100644
--- a/src/views/CreatePost.js
+++ b/src/views/CreatePost.js
@@ -1,11 +1,12 @@
import * as React from "react";
import * as PropTypes from "prop-types";
+import axios from "axios";
+import { connect } from 'react-redux';
import TextBox from "react-uwp/TextBox";
import AppBarButton from "react-uwp/AppBarButton";
-import axios from "axios";
-import createAuthRefreshInterceptor from 'axios-auth-refresh';
+import * as actionCreators from '../store/actions/actionCreators';
-export default class CreatePost extends React.Component {
+class CreatePost extends React.Component {
constructor(props) {
super(props);
@@ -25,27 +26,6 @@ export default class CreatePost extends React.Component {
};
this.handleMovieSearch = this.handleMovieSearch.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
- this.refreshToken = this.refreshToken.bind(this);
- }
-
- refreshToken() {
- const refreshOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`,
- 'headers': {
- 'Authorization': localStorage.getItem("refresh_token")
- }
- }
-
- const refreshAuthLogic = failedRequest => axios(refreshOptions)
- .then(tokenRefreshResponse => {
- localStorage.setItem('access_token', tokenRefreshResponse.data.access_token);
- localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token);
- failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token;
- return Promise.resolve();
- });
-
- return refreshAuthLogic;
}
handleMovieSearch(event) {
@@ -95,9 +75,7 @@ export default class CreatePost extends React.Component {
}
}
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
+ this.props.registerRefreshToken(axios);
axios(axiosOptions)
.then(response => {
@@ -260,4 +238,18 @@ export default class CreatePost extends React.Component {
);
}
-}
\ No newline at end of file
+}
+
+const mapStateToProps = null/*state => {
+ return {
+
+ }
+}*/
+
+const mapDispatchToProps = dispatch => {
+ return {
+ registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance))
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(CreatePost);
diff --git a/src/views/Movie.js b/src/views/Movie.js
index 6c518a7..8f1bfb0 100644
--- a/src/views/Movie.js
+++ b/src/views/Movie.js
@@ -1,12 +1,12 @@
import * as React from "react";
import * as PropTypes from "prop-types";
import axios from 'axios';
-import createAuthRefreshInterceptor from 'axios-auth-refresh';
-
+import { connect } from "react-redux";
import AppBarButton from "react-uwp/AppBarButton";
import Button from "react-uwp/Button";
+import * as actionCreators from '../store/actions/actionCreators';
-export default class Movie extends React.Component {
+class Movie extends React.Component {
constructor(props) {
super(props);
@@ -34,27 +34,6 @@ export default class Movie extends React.Component {
this.getData = this.getData.bind(this);
this.handleAddSeen = this.handleAddSeen.bind(this);
this.handleAddBucket = this.handleAddBucket.bind(this);
- this.refreshToken = this.refreshToken.bind(this);
- }
-
- refreshToken() {
- const refreshOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`,
- 'headers': {
- 'Authorization': localStorage.getItem("refresh_token")
- }
- }
-
- const refreshAuthLogic = failedRequest => axios(refreshOptions)
- .then(tokenRefreshResponse => {
- localStorage.setItem('access_token', tokenRefreshResponse.data.access_token);
- localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token);
- failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token;
- return Promise.resolve();
- });
-
- return refreshAuthLogic;
}
getData() {
@@ -123,9 +102,7 @@ export default class Movie extends React.Component {
}
}
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
+ this.props.registerRefreshToken(axios);
axios(axiosOptions)
.then(response => {
@@ -156,9 +133,7 @@ export default class Movie extends React.Component {
}
}
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
+ this.props.registerRefreshToken(axios);
axios(axiosOptions)
.then(response => {
@@ -268,4 +243,18 @@ export default class Movie extends React.Component {
);
}
-}
\ No newline at end of file
+}
+
+const mapStateToProps = null/*state => {
+ return {
+
+ }
+}*/
+
+const mapDispatchToProps = dispatch => {
+ return {
+ registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance))
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(Movie);
diff --git a/src/views/Post.js b/src/views/Post.js
index fab5687..695ed6d 100644
--- a/src/views/Post.js
+++ b/src/views/Post.js
@@ -1,14 +1,14 @@
import * as React from "react";
import * as PropTypes from "prop-types";
import axios from 'axios';
-import createAuthRefreshInterceptor from 'axios-auth-refresh';
import { Link } from "react-router-dom";
-
+import { connect } from 'react-redux';
import TextBox from "react-uwp/TextBox";
import AppBarButton from "react-uwp/AppBarButton";
import MarkdownRender from "react-uwp/MarkdownRender";
+import * as actionCreators from '../store/actions/actionCreators';
-export default class Post extends React.Component {
+class Post extends React.Component {
constructor(props) {
super(props);
@@ -42,27 +42,6 @@ export default class Post extends React.Component {
this.handleCreateComment = this.handleCreateComment.bind(this);
this.handleCommentUpvote = this.handleCommentUpvote.bind(this);
this.handleCommentDownvote = this.handleCommentDownvote.bind(this);
- this.refreshToken = this.refreshToken.bind(this);
- }
-
- refreshToken() {
- const refreshOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`,
- 'headers': {
- 'Authorization': localStorage.getItem("refresh_token")
- }
- }
-
- const refreshAuthLogic = failedRequest => axios(refreshOptions)
- .then(tokenRefreshResponse => {
- localStorage.setItem('access_token', tokenRefreshResponse.data.access_token);
- localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token);
- failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token;
- return Promise.resolve();
- });
-
- return refreshAuthLogic;
}
getData() {
@@ -141,9 +120,7 @@ export default class Post extends React.Component {
}
}
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
+ this.props.registerRefreshToken();
axios(axiosOptions)
.then(response => {
@@ -171,9 +148,7 @@ export default class Post extends React.Component {
}
}
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
+ this.props.registerRefreshToken();
axios(axiosOptions)
.then(response => {
@@ -203,9 +178,7 @@ export default class Post extends React.Component {
}
}
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
+ this.props.registerRefreshToken();
axios(axiosOptions)
@@ -230,9 +203,7 @@ export default class Post extends React.Component {
}
}
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
+ this.props.registerRefreshToken();
axios(axiosOptions)
.then(response => {
@@ -258,9 +229,7 @@ export default class Post extends React.Component {
}
}
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
+ this.props.registerRefreshToken();
axios(axiosOptions)
.then(response => {
@@ -400,4 +369,18 @@ export default class Post extends React.Component {
);
}
-}
\ No newline at end of file
+}
+
+const mapStateToProps = null/*state => {
+ return {
+
+ }
+}*/
+
+const mapDispatchToProps = dispatch => {
+ return {
+ registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance))
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(Post);
diff --git a/src/views/Profile.js b/src/views/Profile.js
index 4f7311f..e0f8c67 100644
--- a/src/views/Profile.js
+++ b/src/views/Profile.js
@@ -1,15 +1,15 @@
import * as React from "react";
import * as PropTypes from "prop-types";
import { Link } from "react-router-dom";
-import axios from 'axios'
-import createAuthRefreshInterceptor from 'axios-auth-refresh';
-
+import axios from 'axios';
+import { connect } from "react-redux";
import AppBarButton from "react-uwp/AppBarButton";
import Button from "react-uwp/Button";
import ContentDialog from "react-uwp/ContentDialog";
+import * as actionCreators from '../store/actions/actionCreators';
-export default class Profile extends React.Component {
+class Profile extends React.Component {
constructor(props) {
super(props);
@@ -35,31 +35,8 @@ export default class Profile extends React.Component {
this.getPostList = this.getPostList.bind(this);
this.handleDeleteDialog = this.handleDeleteDialog.bind(this);
this.handleDeletePost = this.handleDeletePost.bind(this);
- this.handleLogOut = this.handleLogOut.bind(this);
- this.refreshToken = this.refreshToken.bind(this);
- }
-
- refreshToken() {
- const refreshOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`,
- 'headers': {
- 'Authorization': localStorage.getItem("refresh_token")
- }
- }
-
- const refreshAuthLogic = failedRequest => axios(refreshOptions)
- .then(tokenRefreshResponse => {
- localStorage.setItem('access_token', tokenRefreshResponse.data.access_token);
- localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token);
- failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token;
- return Promise.resolve();
- });
-
- return refreshAuthLogic;
}
-
getData() {
let username = localStorage.getItem("username");
let url = `${process.env.REACT_APP_DB_HOST}/user/` + username;
@@ -192,32 +169,6 @@ export default class Profile extends React.Component {
.catch(error => { /* console.log(error) */ })
}
- handleLogOut() {
- const axiosOptions = {
- 'method': 'POST',
- 'url': `${process.env.REACT_APP_DB_HOST}/auth/logout`,
- headers: {
- 'Authorization': localStorage.getItem("access_token")
- }
- }
-
- const refreshAuthLogic = this.refreshToken();
-
- createAuthRefreshInterceptor(axios, refreshAuthLogic);
-
- axios(axiosOptions)
- .then(response => {
- //console.log(response.data);
- localStorage.removeItem("username");
- localStorage.removeItem("userID");
- localStorage.removeItem("access_token");
- localStorage.removeItem("refresh_token");
- localStorage.clear();
- window.location.pathname = "/";
- })
- .catch(error => { /* console.log(error) */ })
- }
-
componentDidMount() {
this.getData();
this.getSeenData();
@@ -267,7 +218,7 @@ export default class Profile extends React.Component {
icon={}
label="Sign Out"
labelPosition="right"
- onClick={this.handleLogOut}
+ onClick={() => this.props.logout()}
/>
@@ -373,4 +324,18 @@ export default class Profile extends React.Component {
);
}
-}
\ No newline at end of file
+}
+
+const mapStateToProps = null/*state => {
+ return {
+
+ }
+}*/
+
+const mapDispatchToProps = dispatch => {
+ return {
+ logout: () => dispatch(actionCreators.logout())
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(Profile);
From b7fe6b381eb786bfad25215af65a28bb006b8725 Mon Sep 17 00:00:00 2001
From: Ravi Sri Ram Chowdary
Date: Wed, 30 Dec 2020 14:27:39 +0530
Subject: [PATCH 5/5] Removed unnecessary parantheses
---
src/store/actions/auth.js | 2 +-
src/views/CreatePost.js | 2 +-
src/views/Movie.js | 2 +-
src/views/Post.js | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/store/actions/auth.js b/src/store/actions/auth.js
index aed27ec..b532033 100644
--- a/src/store/actions/auth.js
+++ b/src/store/actions/auth.js
@@ -186,7 +186,7 @@ export const resendEmail = email => {
}
// Asynchronous action creator for registering to refresh auth-token
-export const registerRefreshToken = (axiosInstance) => {
+export const registerRefreshToken = axiosInstance => {
const refreshOptions = {
'method': 'POST',
diff --git a/src/views/CreatePost.js b/src/views/CreatePost.js
index fb0a43f..206dc34 100644
--- a/src/views/CreatePost.js
+++ b/src/views/CreatePost.js
@@ -248,7 +248,7 @@ const mapStateToProps = null/*state => {
const mapDispatchToProps = dispatch => {
return {
- registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance))
+ registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance))
}
}
diff --git a/src/views/Movie.js b/src/views/Movie.js
index 8f1bfb0..a978fe0 100644
--- a/src/views/Movie.js
+++ b/src/views/Movie.js
@@ -253,7 +253,7 @@ const mapStateToProps = null/*state => {
const mapDispatchToProps = dispatch => {
return {
- registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance))
+ registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance))
}
}
diff --git a/src/views/Post.js b/src/views/Post.js
index 695ed6d..e234ed3 100644
--- a/src/views/Post.js
+++ b/src/views/Post.js
@@ -379,7 +379,7 @@ const mapStateToProps = null/*state => {
const mapDispatchToProps = dispatch => {
return {
- registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance))
+ registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance))
}
}