src/actions/courseActions.js
import { render, updateSavedText } from "./editorActions";
import * as types from "../constants/ActionTypes";
import * as sceneActions from "./sceneActions";
const courseRef = "/apiv1/courses/";
const header = { headers: { "content-type": "application/json" } };
const noLessons = {
name: "",
id: -1,
prompt: "There are no lessons in this course",
code: ""
};
const problem = {
name: "Error",
id: -1,
prompt: "There has been an error. Please try reloading the page.",
code: ""
};
/*
* Course Actions
*/
/**
* Fetch all the courses available
*/
export function fetchCourses() {
return (dispatch) => {
fetch(courseRef, header)
.then(response => {
response.json()
.then(json => { dispatch(syncCourses(json)); })
// likely a parsing issue
.catch(err => {
dispatch(loadLesson(problem));
console.error(err);
});
})
// likely an HTTP error
.catch(err => {
dispatch(loadLesson(problem));
console.error(err);
});
};
}
/**
* Sends a signal to the reducer to synchronize the courses
*
* @param {*} payload List of courses retrieved
*
* @returns reducer action object with type: SYNC_COURSE and payload
*/
export function syncCourses(payload) {
return { type: types.SYNC_COURSES, payload: payload };
}
/**
* Fetch specific course
*
* @param {string} courseId id of the course getting
*/
export function fetchCourse(courseId) {
return (dispatch) => {
fetch(courseRef + courseId, header)
.then(response => {
response.json()
.then(json => {
document.title = json.name + " Course | MYR";
dispatch(loadCourse(json));
//Make sure that the course is not empty
if(json.lessons.length <= 0){
noLessons.name = json.name;
dispatch(loadLesson(noLessons));
return;
}
dispatch(loadLesson(json.lessons[0] || ""));
dispatch(sceneActions.loadSettings(json.lessons[0].settings || {}));
dispatch(render(json.lessons[0].code || ""));
dispatch(updateSavedText(json.lessons[0].code || ""));
dispatch(sceneActions.setNameDesc(
{
name: json.lessons[0].name,
desc: "This scene was saved from the course: " + json.name
}));
})
.catch(err => {
console.error(err);
dispatch(loadLesson(problem));
});
})
.catch(err => {
console.error(err);
dispatch(loadLesson(problem));
});
};
}
/**
* Sends signal to the reducer to load the course retrieved
*
* @param {*} course Data of course retrieved
* @returns {object} reducer action obj with type: LOAD_COURSE and payload
*/
export function loadCourse(course) {
return { type: types.LOAD_COURSE, payload: course };
}
/*
* Lesson Actions
*/
/**
* Fetch the lesson that is supplied by the parameter.
* @param {*} json Lesson data
*/
export function fetchLesson(json) {
return (dispatch) => {
dispatch(loadLesson(json));
dispatch(sceneActions.resetSettings());
dispatch(sceneActions.loadSettings(json.settings || {}));
dispatch(render(json.code || ""));
dispatch(updateSavedText(json.code || ""));
dispatch(sceneActions.nameScene(json.name));
};
}
/**
* Sends signal to the reducer to load a new lesson supplied by parameter
*
* @param {object} lesson Lesson data
* @returns reducer action obj with type: LOAD_LESSON and payload: lesson
*/
export function loadLesson(lesson) {
return { type: types.LOAD_LESSON, payload: lesson };
}
/**
* Increment the lesson index and load the next lesson.
* Frontend disables option if out of bounds
*
* @param {number} currentIndex current index of the course
* @param {object} next Object of lesson to be load next
*/
export function nextLesson(currentIndex, next) {
return (dispatch) => {
dispatch(setCurrentIndex(currentIndex + 1));
dispatch(fetchLesson(next));
};
}
/**
* Decrement the lesson index and load the previous lesson.
* Frontend disables option if out of bounds
*
* @param {number} currentIndex current index of the course
* @param {object} prev Object of lesson to be load previous
*/
export function previousLesson(currentIndex, prev) {
return (dispatch) => {
dispatch(setCurrentIndex(currentIndex - 1));
dispatch(fetchLesson(prev));
};
}
/**
* Sends signal to the reducer to update the current index of the Course
*
* @param {number} newIndex New index to be set
* @returns {object} reducer action obj with type: SET_INDEX and payload: newIndex
*/
export function setCurrentIndex(newIndex) {
return { type: types.SET_INDEX, payload: newIndex };
}
export default {
fetchCourses,
syncCourses,
nextLesson,
previousLesson,
fetchCourse,
setCurrentIndex,
loadLesson,
fetchLesson,
loadCourse
};