- update tutorial modell - add difficulty closes #82 - add review system - make tutorials private by default - add admin overview
346 lines
9.5 KiB
JavaScript
346 lines
9.5 KiB
JavaScript
import {
|
|
TUTORIAL_PROGRESS,
|
|
GET_TUTORIAL,
|
|
GET_TUTORIALS,
|
|
TUTORIAL_SUCCESS,
|
|
TUTORIAL_ERROR,
|
|
TUTORIAL_CHANGE,
|
|
TUTORIAL_XML,
|
|
TUTORIAL_STEP,
|
|
} from "./types";
|
|
|
|
import axios from "axios";
|
|
import { returnErrors, returnSuccess } from "./messageActions";
|
|
|
|
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) => {
|
|
dispatch({
|
|
type: TUTORIAL_SUCCESS,
|
|
payload: status,
|
|
});
|
|
dispatch(updateStatus(status));
|
|
dispatch({
|
|
type: GET_TUTORIAL,
|
|
payload: tutorial,
|
|
});
|
|
dispatch({ type: TUTORIAL_PROGRESS });
|
|
dispatch(returnSuccess(res.data.message, res.status));
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
if (err.response) {
|
|
dispatch(
|
|
returnErrors(
|
|
err.response.data.message,
|
|
err.response.status,
|
|
"GET_TUTORIAL_FAIL"
|
|
)
|
|
);
|
|
}
|
|
dispatch({ type: TUTORIAL_PROGRESS });
|
|
});
|
|
};
|
|
|
|
export const getTutorials = () => (dispatch, getState) => {
|
|
axios
|
|
.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial`)
|
|
.then((res) => {
|
|
var tutorials = res.data.tutorials;
|
|
existingTutorials(tutorials, getState().tutorial.status).then(
|
|
(status) => {
|
|
dispatch({
|
|
type: TUTORIAL_SUCCESS,
|
|
payload: status,
|
|
});
|
|
dispatch(updateStatus(status));
|
|
dispatch({
|
|
type: GET_TUTORIALS,
|
|
payload: tutorials,
|
|
});
|
|
dispatch({ type: TUTORIAL_PROGRESS });
|
|
dispatch(returnSuccess(res.data.message, res.status));
|
|
}
|
|
);
|
|
})
|
|
.catch((err) => {
|
|
if (err.response) {
|
|
dispatch(
|
|
returnErrors(
|
|
err.response.data.message,
|
|
err.response.status,
|
|
"GET_TUTORIALS_FAIL"
|
|
)
|
|
);
|
|
}
|
|
dispatch({ type: TUTORIAL_PROGRESS });
|
|
});
|
|
};
|
|
|
|
export const getAllTutorials = () => (dispatch, getState) => {
|
|
axios
|
|
.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/getAllTutorials`)
|
|
.then((res) => {
|
|
var tutorials = res.data.tutorials;
|
|
existingTutorials(tutorials, getState().tutorial.status).then(
|
|
(status) => {
|
|
dispatch({
|
|
type: TUTORIAL_SUCCESS,
|
|
payload: status,
|
|
});
|
|
dispatch(updateStatus(status));
|
|
dispatch({
|
|
type: GET_TUTORIALS,
|
|
payload: tutorials,
|
|
});
|
|
dispatch({ type: TUTORIAL_PROGRESS });
|
|
dispatch(returnSuccess(res.data.message, res.status));
|
|
}
|
|
);
|
|
})
|
|
.catch((err) => {
|
|
if (err.response) {
|
|
dispatch(
|
|
returnErrors(
|
|
err.response.data.message,
|
|
err.response.status,
|
|
"GET_TUTORIALS_FAIL"
|
|
)
|
|
);
|
|
}
|
|
dispatch({ type: TUTORIAL_PROGRESS });
|
|
});
|
|
};
|
|
|
|
export const getUserTutorials = () => (dispatch, getState) => {
|
|
axios
|
|
.get(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/getUserTutorials`)
|
|
.then((res) => {
|
|
var tutorials = res.data.tutorials;
|
|
existingTutorials(tutorials, getState().tutorial.status).then(
|
|
(status) => {
|
|
dispatch({
|
|
type: TUTORIAL_SUCCESS,
|
|
payload: status,
|
|
});
|
|
dispatch(updateStatus(status));
|
|
dispatch({
|
|
type: GET_TUTORIALS,
|
|
payload: tutorials,
|
|
});
|
|
dispatch({ type: TUTORIAL_PROGRESS });
|
|
dispatch(returnSuccess(res.data.message, res.status));
|
|
}
|
|
);
|
|
})
|
|
.catch((err) => {
|
|
console.log(err);
|
|
if (err.response) {
|
|
dispatch(
|
|
returnErrors(
|
|
err.response.data.message,
|
|
err.response.status,
|
|
"GET_TUTORIALS_FAIL"
|
|
)
|
|
);
|
|
}
|
|
dispatch({ type: TUTORIAL_PROGRESS });
|
|
});
|
|
};
|
|
|
|
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) => {})
|
|
.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;
|
|
const config = {
|
|
success: (res) => {
|
|
var tutorials = tutorial.tutorials;
|
|
var index = tutorials.findIndex((res) => res._id === id);
|
|
tutorials.splice(index, 1);
|
|
dispatch({
|
|
type: GET_TUTORIALS,
|
|
payload: tutorials,
|
|
});
|
|
dispatch(
|
|
returnSuccess(res.data.message, res.status, "TUTORIAL_DELETE_SUCCESS")
|
|
);
|
|
},
|
|
error: (err) => {
|
|
dispatch(
|
|
returnErrors(
|
|
err.response.data.message,
|
|
err.response.status,
|
|
"TUTORIAL_DELETE_FAIL"
|
|
)
|
|
);
|
|
},
|
|
};
|
|
axios
|
|
.delete(`${process.env.REACT_APP_BLOCKLY_API}/tutorial/${id}`, config)
|
|
.then((res) => {
|
|
res.config.success(res);
|
|
})
|
|
.catch((err) => {
|
|
if (err.response && err.response.status !== 401) {
|
|
err.config.error(err);
|
|
}
|
|
});
|
|
};
|
|
|
|
export const resetTutorial = () => (dispatch) => {
|
|
dispatch({
|
|
type: GET_TUTORIALS,
|
|
payload: [],
|
|
});
|
|
dispatch({
|
|
type: TUTORIAL_STEP,
|
|
payload: 0,
|
|
});
|
|
};
|
|
|
|
export const tutorialChange = () => (dispatch) => {
|
|
dispatch({
|
|
type: TUTORIAL_CHANGE,
|
|
});
|
|
};
|
|
|
|
export const tutorialCheck = (status, step) => (dispatch, getState) => {
|
|
var tutorialsStatus = getState().tutorial.status;
|
|
var id = getState().tutorial.tutorials[0]._id;
|
|
var tutorialsStatusIndex = tutorialsStatus.findIndex(
|
|
(tutorialStatus) => tutorialStatus._id === id
|
|
);
|
|
var tasksIndex = tutorialsStatus[tutorialsStatusIndex].tasks.findIndex(
|
|
(task) => task._id === step._id
|
|
);
|
|
tutorialsStatus[tutorialsStatusIndex].tasks[tasksIndex] = {
|
|
...tutorialsStatus[tutorialsStatusIndex].tasks[tasksIndex],
|
|
type: status,
|
|
};
|
|
dispatch({
|
|
type: status === "success" ? TUTORIAL_SUCCESS : TUTORIAL_ERROR,
|
|
payload: tutorialsStatus,
|
|
});
|
|
dispatch(updateStatus(tutorialsStatus));
|
|
dispatch(tutorialChange());
|
|
dispatch(returnSuccess("", "", "TUTORIAL_CHECK_SUCCESS"));
|
|
};
|
|
|
|
export const storeTutorialXml = (code) => (dispatch, getState) => {
|
|
var tutorial = getState().tutorial.tutorials[0];
|
|
if (tutorial) {
|
|
var id = tutorial._id;
|
|
var activeStep = getState().tutorial.activeStep;
|
|
var steps = tutorial.steps;
|
|
if (steps && steps[activeStep].type === "task") {
|
|
var tutorialsStatus = getState().tutorial.status;
|
|
var tutorialsStatusIndex = tutorialsStatus.findIndex(
|
|
(tutorialStatus) => tutorialStatus._id === id
|
|
);
|
|
var tasksIndex = tutorialsStatus[tutorialsStatusIndex].tasks.findIndex(
|
|
(task) => task._id === steps[activeStep]._id
|
|
);
|
|
tutorialsStatus[tutorialsStatusIndex].tasks[tasksIndex] = {
|
|
...tutorialsStatus[tutorialsStatusIndex].tasks[tasksIndex],
|
|
xml: code,
|
|
};
|
|
dispatch({
|
|
type: TUTORIAL_XML,
|
|
payload: tutorialsStatus,
|
|
});
|
|
dispatch(updateStatus(tutorialsStatus));
|
|
}
|
|
}
|
|
};
|
|
|
|
export const tutorialStep = (step) => (dispatch) => {
|
|
dispatch({
|
|
type: TUTORIAL_STEP,
|
|
payload: step,
|
|
});
|
|
};
|
|
|
|
const existingTutorials = (tutorials, status) =>
|
|
new Promise(function (resolve, reject) {
|
|
var newstatus;
|
|
new Promise(function (resolve, reject) {
|
|
var existingTutorialIds = tutorials.map((tutorial, i) => {
|
|
existingTutorial(tutorial, status).then((status) => {
|
|
newstatus = status;
|
|
});
|
|
return tutorial._id;
|
|
});
|
|
resolve(existingTutorialIds);
|
|
}).then((existingTutorialIds) => {
|
|
// deleting old tutorials which do not longer exist
|
|
if (existingTutorialIds.length > 0) {
|
|
status = newstatus.filter(
|
|
(status) => existingTutorialIds.indexOf(status._id) > -1
|
|
);
|
|
}
|
|
resolve(status);
|
|
});
|
|
});
|
|
|
|
const existingTutorial = (tutorial, status) =>
|
|
new Promise(function (resolve, reject) {
|
|
var tutorialsId = tutorial._id;
|
|
var statusIndex = status.findIndex((status) => status._id === tutorialsId);
|
|
if (statusIndex > -1) {
|
|
var tasks = tutorial.steps.filter((step) => step.type === "task");
|
|
var existingTaskIds = tasks.map((task, j) => {
|
|
var tasksId = task._id;
|
|
if (
|
|
status[statusIndex].tasks.findIndex(
|
|
(task) => task._id === tasksId
|
|
) === -1
|
|
) {
|
|
// task does not exist
|
|
status[statusIndex].tasks.push({ _id: tasksId });
|
|
}
|
|
return tasksId;
|
|
});
|
|
// deleting old tasks which do not longer exist
|
|
if (existingTaskIds.length > 0) {
|
|
status[statusIndex].tasks = status[statusIndex].tasks.filter(
|
|
(task) => existingTaskIds.indexOf(task._id) > -1
|
|
);
|
|
}
|
|
} else {
|
|
status.push({
|
|
_id: tutorialsId,
|
|
tasks: tutorial.steps
|
|
.filter((step) => step.type === "task")
|
|
.map((task) => {
|
|
return { _id: task._id };
|
|
}),
|
|
});
|
|
}
|
|
resolve(status);
|
|
});
|