tutorial status is stored in user account if exists or in local storage
This commit is contained in:
parent
5430e783cc
commit
1821ac4e40
@ -1,4 +1,4 @@
|
||||
import { MYBADGES_CONNECT, MYBADGES_DISCONNECT, USER_LOADED, USER_LOADING, AUTH_ERROR, LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT_SUCCESS, LOGOUT_FAIL, REFRESH_TOKEN_SUCCESS } from '../actions/types';
|
||||
import { MYBADGES_CONNECT, MYBADGES_DISCONNECT, GET_STATUS, USER_LOADED, USER_LOADING, AUTH_ERROR, LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT_SUCCESS, LOGOUT_FAIL, REFRESH_TOKEN_SUCCESS } from '../actions/types';
|
||||
|
||||
import axios from 'axios';
|
||||
import { returnErrors, returnSuccess } from './messageActions'
|
||||
@ -12,6 +12,10 @@ export const loadUser = () => (dispatch) => {
|
||||
});
|
||||
const config = {
|
||||
success: res => {
|
||||
dispatch({
|
||||
type: GET_STATUS,
|
||||
payload: res.data.user.status
|
||||
});
|
||||
dispatch({
|
||||
type: USER_LOADED,
|
||||
payload: res.data.user
|
||||
@ -21,6 +25,15 @@ export const loadUser = () => (dispatch) => {
|
||||
if(err.response){
|
||||
dispatch(returnErrors(err.response.data.message, err.response.status));
|
||||
}
|
||||
console.log('auth failed');
|
||||
var status = [];
|
||||
if (window.localStorage.getItem('status')) {
|
||||
status = JSON.parse(window.localStorage.getItem('status'));
|
||||
}
|
||||
dispatch({
|
||||
type: GET_STATUS,
|
||||
payload: status
|
||||
});
|
||||
dispatch({
|
||||
type: AUTH_ERROR
|
||||
});
|
||||
@ -31,6 +44,7 @@ export const loadUser = () => (dispatch) => {
|
||||
res.config.success(res);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
err.config.error(err);
|
||||
});
|
||||
};
|
||||
@ -61,13 +75,26 @@ export const login = ({ email, password }) => (dispatch) => {
|
||||
type: LOGIN_SUCCESS,
|
||||
payload: res.data
|
||||
});
|
||||
dispatch({
|
||||
type: GET_STATUS,
|
||||
payload: res.data.user.status
|
||||
});
|
||||
dispatch(returnSuccess(res.data.message, res.status, 'LOGIN_SUCCESS'));
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
dispatch(returnErrors(err.response.data.message, err.response.status, 'LOGIN_FAIL'));
|
||||
dispatch({
|
||||
type: LOGIN_FAIL
|
||||
});
|
||||
var status = [];
|
||||
if (window.localStorage.getItem('status')) {
|
||||
status = JSON.parse(window.localStorage.getItem('status'));
|
||||
}
|
||||
dispatch({
|
||||
type: GET_STATUS,
|
||||
payload: status
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -130,6 +157,14 @@ export const logout = () => (dispatch) => {
|
||||
dispatch({
|
||||
type: LOGOUT_SUCCESS
|
||||
});
|
||||
var status = [];
|
||||
if (window.localStorage.getItem('status')) {
|
||||
status = JSON.parse(window.localStorage.getItem('status'));
|
||||
}
|
||||
dispatch({
|
||||
type: GET_STATUS,
|
||||
payload: status
|
||||
});
|
||||
dispatch(returnSuccess(res.data.message, res.status, 'LOGOUT_SUCCESS'));
|
||||
clearTimeout(logoutTimerId);
|
||||
},
|
||||
@ -138,6 +173,14 @@ export const logout = () => (dispatch) => {
|
||||
dispatch({
|
||||
type: LOGOUT_FAIL
|
||||
});
|
||||
var status = [];
|
||||
if (window.localStorage.getItem('status')) {
|
||||
status = JSON.parse(window.localStorage.getItem('status'));
|
||||
}
|
||||
dispatch({
|
||||
type: GET_STATUS,
|
||||
payload: status
|
||||
});
|
||||
clearTimeout(logoutTimerId);
|
||||
}
|
||||
};
|
||||
@ -146,6 +189,7 @@ export const logout = () => (dispatch) => {
|
||||
res.config.success(res);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
if(err.response.status !== 401){
|
||||
err.config.error(err);
|
||||
}
|
||||
|
@ -3,21 +3,28 @@ import { MYBADGES_DISCONNECT, TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TU
|
||||
import axios from 'axios';
|
||||
import { returnErrors, returnSuccess } from './messageActions';
|
||||
|
||||
export const getTutorial = (id) => (dispatch, getState) => {
|
||||
export const tutorialProgress = () => (dispatch) => {
|
||||
dispatch({type: TUTORIAL_PROGRESS});
|
||||
};
|
||||
|
||||
|
||||
export const getTutorial = (id) => (dispatch, getState) => {
|
||||
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`)
|
||||
.then(res => {
|
||||
var tutorial = res.data.tutorial;
|
||||
existingTutorial(tutorial, getState().tutorial.status).then(status => {
|
||||
console.log('progress',getState().auth.progress);
|
||||
console.log('status');
|
||||
dispatch({
|
||||
type: TUTORIAL_SUCCESS,
|
||||
payload: status
|
||||
});
|
||||
dispatch({type: TUTORIAL_PROGRESS});
|
||||
dispatch(updateStatus(status));
|
||||
dispatch({
|
||||
type: GET_TUTORIAL,
|
||||
payload: tutorial
|
||||
});
|
||||
dispatch({type: TUTORIAL_PROGRESS});
|
||||
dispatch(returnSuccess(res.data.message, res.status));
|
||||
});
|
||||
})
|
||||
@ -30,7 +37,6 @@ export const getTutorial = (id) => (dispatch, getState) => {
|
||||
};
|
||||
|
||||
export const getTutorials = () => (dispatch, getState) => {
|
||||
dispatch({type: TUTORIAL_PROGRESS});
|
||||
axios.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial`)
|
||||
.then(res => {
|
||||
var tutorials = res.data.tutorials;
|
||||
@ -40,6 +46,7 @@ export const getTutorials = () => (dispatch, getState) => {
|
||||
type: TUTORIAL_SUCCESS,
|
||||
payload: status
|
||||
});
|
||||
dispatch(updateStatus(status));
|
||||
dispatch({
|
||||
type: GET_TUTORIALS,
|
||||
payload: tutorials
|
||||
@ -75,6 +82,24 @@ export const assigneBadge = (id) => (dispatch, getState) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const updateStatus = (status) => (dispatch, getState) => {
|
||||
if(getState().auth.isAuthenticated){
|
||||
// update user account in database - sync with redux store
|
||||
axios.put(`${process.env.REACT_APP_BLOCKLY_API}/user/status`, {status: status})
|
||||
.then(res => {
|
||||
// dispatch(returnSuccess(badge, res.status, 'UPDATE_STATUS_SUCCESS'));
|
||||
})
|
||||
.catch(err => {
|
||||
if(err.response){
|
||||
// dispatch(returnErrors(err.response.data.message, err.response.status, 'UPDATE_STATUS_FAIL'));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// update locale storage - sync with redux store
|
||||
window.localStorage.setItem('status', JSON.stringify(status));
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteTutorial = (id) => (dispatch, getState) => {
|
||||
var tutorial = getState().tutorial;
|
||||
var id = getState().builder.id;
|
||||
@ -127,6 +152,7 @@ export const tutorialCheck = (status, step) => (dispatch, getState) => {
|
||||
type: status === 'success' ? TUTORIAL_SUCCESS : TUTORIAL_ERROR,
|
||||
payload: tutorialsStatus
|
||||
});
|
||||
dispatch(updateStatus(tutorialsStatus));
|
||||
dispatch(tutorialChange());
|
||||
dispatch(returnSuccess('','','TUTORIAL_CHECK_SUCCESS'));
|
||||
};
|
||||
@ -149,6 +175,7 @@ export const storeTutorialXml = (code) => (dispatch, getState) => {
|
||||
type: TUTORIAL_XML,
|
||||
payload: tutorialsStatus
|
||||
});
|
||||
dispatch(updateStatus(tutorialsStatus));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -23,6 +23,7 @@ export const NAME = 'NAME';
|
||||
export const TUTORIAL_PROGRESS = 'TUTORIAL_PROGRESS';
|
||||
export const GET_TUTORIAL = 'GET_TUTORIAL';
|
||||
export const GET_TUTORIALS = 'GET_TUTORIALS';
|
||||
export const GET_STATUS = 'GET_STATUS';
|
||||
export const TUTORIAL_SUCCESS = 'TUTORIAL_SUCCESS';
|
||||
export const TUTORIAL_ERROR = 'TUTORIAL_ERROR';
|
||||
export const TUTORIAL_CHANGE = 'TUTORIAL_CHANGE';
|
||||
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { workspaceName } from '../../actions/workspaceActions';
|
||||
import { clearMessages } from '../../actions/messageActions';
|
||||
import { getTutorial, resetTutorial, tutorialStep } from '../../actions/tutorialActions';
|
||||
import { getTutorial, resetTutorial, tutorialStep,tutorialProgress } from '../../actions/tutorialActions';
|
||||
|
||||
import Breadcrumbs from '../Breadcrumbs';
|
||||
import StepperHorizontal from './StepperHorizontal';
|
||||
@ -22,11 +22,20 @@ import Button from '@material-ui/core/Button';
|
||||
class Tutorial extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.getTutorial(this.props.match.params.tutorialId);
|
||||
this.props.tutorialProgress();
|
||||
// retrieve tutorials only if a potential user is loaded - authentication
|
||||
// is finished (success or failed)
|
||||
if(!this.props.progress){
|
||||
this.props.getTutorial(this.props.match.params.tutorialId);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(props, state) {
|
||||
if(this.props.tutorial && !this.props.isLoading && this.props.tutorial._id != this.props.match.params.tutorialId) {
|
||||
if(props.progress !== this.props.progress && !this.props.progress){
|
||||
// authentication is completed
|
||||
this.props.getTutorial(this.props.match.params.tutorialId);
|
||||
}
|
||||
else if(this.props.tutorial && !this.props.isLoading && this.props.tutorial._id != this.props.match.params.tutorialId) {
|
||||
this.props.getTutorial(this.props.match.params.tutorialId);
|
||||
}
|
||||
if(this.props.message.id === 'GET_TUTORIAL_FAIL'){
|
||||
@ -89,13 +98,15 @@ Tutorial.propTypes = {
|
||||
resetTutorial: PropTypes.func.isRequired,
|
||||
clearMessages: PropTypes.func.isRequired,
|
||||
tutorialStep: PropTypes.func.isRequired,
|
||||
tutorialProgress: PropTypes.func.isRequired,
|
||||
workspaceName: PropTypes.func.isRequired,
|
||||
status: PropTypes.array.isRequired,
|
||||
change: PropTypes.number.isRequired,
|
||||
activeStep: PropTypes.number.isRequired,
|
||||
tutorial: PropTypes.object.isRequired,
|
||||
isLoading: PropTypes.bool.isRequired,
|
||||
message: PropTypes.object.isRequired
|
||||
message: PropTypes.object.isRequired,
|
||||
progress: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
@ -104,7 +115,8 @@ const mapStateToProps = state => ({
|
||||
activeStep: state.tutorial.activeStep,
|
||||
tutorial: state.tutorial.tutorials[0],
|
||||
isLoading: state.tutorial.progress,
|
||||
message: state.message
|
||||
message: state.message,
|
||||
progress: state.auth.progress
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, { getTutorial, resetTutorial, tutorialStep, clearMessages, workspaceName })(Tutorial);
|
||||
export default connect(mapStateToProps, { getTutorial, resetTutorial, tutorialStep, tutorialProgress, clearMessages, workspaceName })(Tutorial);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { getTutorials, resetTutorial } from '../../actions/tutorialActions';
|
||||
import { getTutorials, resetTutorial, tutorialProgress } from '../../actions/tutorialActions';
|
||||
import { clearMessages } from '../../actions/messageActions';
|
||||
|
||||
import clsx from 'clsx';
|
||||
@ -52,10 +52,19 @@ const styles = (theme) => ({
|
||||
class TutorialHome extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.getTutorials();
|
||||
this.props.tutorialProgress();
|
||||
// retrieve tutorials only if a potential user is loaded - authentication
|
||||
// is finished (success or failed)
|
||||
if(!this.props.progress){
|
||||
this.props.getTutorials();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(props, state) {
|
||||
if(props.progress !== this.props.progress && !this.props.progress){
|
||||
// authentication is completed
|
||||
this.props.getTutorials();
|
||||
}
|
||||
if(this.props.message.id === 'GET_TUTORIALS_FAIL'){
|
||||
alert(this.props.message.msg);
|
||||
}
|
||||
@ -120,12 +129,14 @@ class TutorialHome extends Component {
|
||||
TutorialHome.propTypes = {
|
||||
getTutorials: PropTypes.func.isRequired,
|
||||
resetTutorial: PropTypes.func.isRequired,
|
||||
tutorialProgress: PropTypes.func.isRequired,
|
||||
clearMessages: PropTypes.func.isRequired,
|
||||
status: PropTypes.array.isRequired,
|
||||
change: PropTypes.number.isRequired,
|
||||
tutorials: PropTypes.array.isRequired,
|
||||
isLoading: PropTypes.bool.isRequired,
|
||||
message: PropTypes.object.isRequired
|
||||
message: PropTypes.object.isRequired,
|
||||
progress: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
@ -133,7 +144,8 @@ const mapStateToProps = state => ({
|
||||
status: state.tutorial.status,
|
||||
tutorials: state.tutorial.tutorials,
|
||||
isLoading: state.tutorial.progress,
|
||||
message: state.message
|
||||
message: state.message,
|
||||
progress: state.auth.progress
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, { getTutorials, resetTutorial, clearMessages })(withStyles(styles, { withTheme: true })(TutorialHome));
|
||||
export default connect(mapStateToProps, { getTutorials, resetTutorial, clearMessages, tutorialProgress })(withStyles(styles, { withTheme: true })(TutorialHome));
|
||||
|
@ -5,7 +5,7 @@ const initialState = {
|
||||
token: localStorage.getItem('token'),
|
||||
refreshToken: localStorage.getItem('refreshToken'),
|
||||
isAuthenticated: null,
|
||||
progress: false,
|
||||
progress: true,
|
||||
user: null
|
||||
};
|
||||
|
||||
|
@ -1,18 +1,20 @@
|
||||
import { TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_ID, TUTORIAL_STEP } from '../actions/types';
|
||||
import { TUTORIAL_PROGRESS, GET_TUTORIAL, GET_TUTORIALS, GET_STATUS, TUTORIAL_SUCCESS, TUTORIAL_ERROR, TUTORIAL_CHANGE, TUTORIAL_XML, TUTORIAL_ID, TUTORIAL_STEP } from '../actions/types';
|
||||
|
||||
|
||||
const initialStatus = () => {
|
||||
if (window.localStorage.getItem('status')) {
|
||||
var status = JSON.parse(window.localStorage.getItem('status'));
|
||||
return status;
|
||||
}
|
||||
return [];
|
||||
// // window.localStorage.getItem('status') does not exist
|
||||
// return tutorials.map(tutorial => { return { id: tutorial.id, tasks: tutorial.steps.filter(step => step.type === 'task').map(task => { return { id: task.id }; }) }; });
|
||||
};
|
||||
//
|
||||
// const initialStatus = () => {
|
||||
// if(store.getState().auth.user){
|
||||
// return store.getState().auth.user.status || []
|
||||
// }
|
||||
// else if (window.localStorage.getItem('status')) {
|
||||
// var status = JSON.parse(window.localStorage.getItem('status'));
|
||||
// return status;
|
||||
// }
|
||||
// return [];
|
||||
// };
|
||||
|
||||
const initialState = {
|
||||
status: initialStatus(),
|
||||
status: [],
|
||||
activeStep: 0,
|
||||
change: 0,
|
||||
tutorials: [],
|
||||
@ -39,8 +41,14 @@ export default function (state = initialState, action) {
|
||||
case TUTORIAL_SUCCESS:
|
||||
case TUTORIAL_ERROR:
|
||||
case TUTORIAL_XML:
|
||||
// update locale storage - sync with redux store
|
||||
window.localStorage.setItem('status', JSON.stringify(action.payload));
|
||||
// update store - sync with redux store is implemented outside reducer
|
||||
// in every dispatch action with the types 'TUTORIAL_SUCCESS','TUTORIAL_ERROR'
|
||||
// and 'TUTORIAL_XML' the function 'updateStatus' is called
|
||||
return {
|
||||
...state,
|
||||
status: action.payload
|
||||
};
|
||||
case GET_STATUS:
|
||||
return {
|
||||
...state,
|
||||
status: action.payload
|
||||
|
Loading…
x
Reference in New Issue
Block a user