diff --git a/src/api/authorApi.js b/src/api/authorApi.js
deleted file mode 100644
index 2689db1..0000000
--- a/src/api/authorApi.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { get } from "./api";
-const baseUrl = process.env.API_URL + "/authors/";
-
-export function getAuthors() {
- return get(baseUrl);
-}
diff --git a/src/api/courseApi.js b/src/api/courseApi.js
deleted file mode 100644
index 366accb..0000000
--- a/src/api/courseApi.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { get, del, post, put } from "./api";
-const baseUrl = process.env.API_URL + "/courses/";
-
-export function getCourses() {
- return get(baseUrl);
-}
-
-export function saveCourse(course) {
- const url = baseUrl + (course.id || "");
- return course.id ? put(url, course) : post(url, course); // POST for create, PUT to update when id already exists.
-}
-
-export function deleteCourse(courseId) {
- return del(baseUrl + courseId);
-}
diff --git a/src/components/App.js b/src/components/App.js
index 2c9b68c..5cf5ab7 100644
--- a/src/components/App.js
+++ b/src/components/App.js
@@ -4,8 +4,6 @@ import HomePage from "./home/HomePage";
import AboutPage from "./about/AboutPage";
import Header from "./common/Header";
import PageNotFound from "./PageNotFound";
-import CoursesPage from "./courses/CoursesPage";
-import ManageCoursePage from "./courses/ManageCoursePage";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import SessionContainer from "../features/session/components/SessionContainer";
@@ -17,9 +15,6 @@ function App() {
-
-
-
diff --git a/src/components/courses/CourseForm.js b/src/components/courses/CourseForm.js
deleted file mode 100644
index f0ab750..0000000
--- a/src/components/courses/CourseForm.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import React from "react";
-import PropTypes from "prop-types";
-import TextInput from "../common/TextInput";
-import SelectInput from "../common/SelectInput";
-
-const CourseForm = ({
- course,
- authors,
- onSave,
- onChange,
- saving = false,
- errors = {}
-}) => {
- return (
-
- );
-};
-
-CourseForm.propTypes = {
- authors: PropTypes.array.isRequired,
- course: PropTypes.object.isRequired,
- errors: PropTypes.object,
- onSave: PropTypes.func.isRequired,
- onChange: PropTypes.func.isRequired,
- saving: PropTypes.bool
-};
-
-export default CourseForm;
diff --git a/src/components/courses/CourseList.js b/src/components/courses/CourseList.js
deleted file mode 100644
index 7ae652b..0000000
--- a/src/components/courses/CourseList.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import React from "react";
-import PropTypes from "prop-types";
-import { Link } from "react-router-dom";
-
-const CourseList = ({ courses, onDeleteClick }) => (
-
-
-
- |
- Title |
- Author |
- Category |
- |
-
-
-
- {courses.map((course) => {
- return (
-
-
-
- Watch
-
- |
-
- {course.title}
- |
- {course.authorName} |
- {course.category} |
-
-
- |
-
- );
- })}
-
-
-);
-
-CourseList.propTypes = {
- courses: PropTypes.array.isRequired,
- onDeleteClick: PropTypes.func.isRequired
-};
-
-export default CourseList;
diff --git a/src/components/courses/CoursesPage.js b/src/components/courses/CoursesPage.js
deleted file mode 100644
index 973cfd2..0000000
--- a/src/components/courses/CoursesPage.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import React from "react";
-import { connect } from "react-redux";
-import * as courseActions from "../../redux/actions/courseActions";
-import * as authorActions from "../../redux/actions/authorActions";
-import PropTypes from "prop-types";
-import { bindActionCreators } from "redux";
-import CourseList from "./CourseList";
-import { Redirect } from "react-router-dom";
-import Spinner from "../common/Spinner";
-import { toast } from "react-toastify";
-
-class CoursesPage extends React.Component {
- state = {
- redirectToAddCoursePage: false
- };
-
- componentDidMount() {
- const { courses, authors, actions } = this.props;
-
- if (courses.length === 0) {
- actions.loadCourses().catch((error) => {
- alert("Loading courses failed. " + error);
- });
- }
-
- if (authors.length === 0) {
- actions.loadAuthors().catch((error) => {
- alert("Loading authors failed. " + error);
- });
- }
- }
-
- handleDeleteCourse = async (course) => {
- toast.success("Course deleted");
- try {
- await this.props.actions.deleteCourse(course);
- } catch (error) {
- toast.error("Delete failed. " + error.message, { autoClose: false });
- }
- };
-
- render() {
- return (
- <>
- {this.state.redirectToAddCoursePage && }
- Courses
- {this.props.loading ? (
-
- ) : (
- <>
-
-
-
- >
- )}
- >
- );
- }
-}
-
-CoursesPage.propTypes = {
- courses: PropTypes.array.isRequired,
- authors: PropTypes.array.isRequired,
- actions: PropTypes.object.isRequired,
- loading: PropTypes.bool.isRequired
-};
-
-function mapStateToProps(state) {
- return {
- courses:
- state.authors.length === 0
- ? []
- : state.courses.map((course) => {
- const author = state.authors.find((a) => a.id === course.authorId);
- return {
- ...course,
- authorName: author.name
- };
- }),
- authors: state.authors,
- loading: state.ajaxCallsInProgress > 0
- };
-}
-
-function mapDispatchToProps(dispatch) {
- return {
- actions: bindActionCreators(
- {
- loadCourses: courseActions.loadCourses,
- loadAuthors: authorActions.loadAuthors,
- deleteCourse: courseActions.deleteCourse
- },
- dispatch
- )
- };
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(CoursesPage);
diff --git a/src/components/courses/ManageCoursePage.js b/src/components/courses/ManageCoursePage.js
deleted file mode 100644
index 3141097..0000000
--- a/src/components/courses/ManageCoursePage.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import React, { useEffect, useState } from "react";
-import { connect } from "react-redux";
-import { loadCourses, saveCourse } from "../../redux/actions/courseActions";
-import { loadAuthors } from "../../redux/actions/authorActions";
-import PropTypes from "prop-types";
-import { bindActionCreators } from "redux";
-import CourseForm from "./CourseForm";
-import { newCourse } from "../../../tools/mockData";
-import Spinner from "../common/Spinner";
-import { toast } from "react-toastify";
-
-function ManageCoursePage({ courses, authors, actions, history, ...props }) {
- const [course, setCourse] = useState({ ...props.course });
- const [errors, setErrors] = useState({});
- const [saving, setSaving] = useState(false);
-
- useEffect(() => {
- if (courses.length === 0) {
- actions.loadCourses().catch((error) => {
- alert("Loading courses failed. " + error);
- });
- } else {
- setCourse({ ...props.course });
- }
-
- if (authors.length === 0) {
- actions.loadAuthors().catch((error) => {
- alert("Loading authors failed. " + error);
- });
- }
- }, [props.course]);
-
- function handleChange(event) {
- const { name, value } = event.target;
- setCourse((prevCourse) => ({
- ...prevCourse,
- [name]: name === "authorId" ? parseInt(value, 10) : value
- }));
- }
-
- function formIsValid() {
- const { title, authorId, category } = course;
- const errors = {};
-
- if (!title) errors.title = "Title is required.";
- if (!authorId) errors.author = "Author is required";
- if (!category) errors.category = "Category is required";
-
- setErrors(errors);
- // Form is valid if the errors object still has no properties
- return Object.keys(errors).length === 0;
- }
-
- function handleSave(event) {
- event.preventDefault();
- if (!formIsValid()) return;
- setSaving(true);
- actions
- .saveCourse(course)
- .then(() => {
- toast.success("Course saved.");
- history.push("/courses");
- })
- .catch((error) => {
- setSaving(false);
- setErrors({ onSave: error.message });
- });
- }
-
- return authors.length === 0 || course.length === 0 ? (
-
- ) : (
-
- );
-}
-
-ManageCoursePage.propTypes = {
- course: PropTypes.object.isRequired,
- courses: PropTypes.array.isRequired,
- authors: PropTypes.array.isRequired,
- actions: PropTypes.object.isRequired,
- history: PropTypes.object.isRequired
-};
-
-function mapStateToProps(state, ownProps) {
- const slug = ownProps.match.params.slug;
- const course =
- slug && state.courses.length > 0
- ? getCourseBySlug(state.courses, slug)
- : newCourse;
- return {
- course,
- courses: state.courses,
- authors: state.authors
- };
-}
-
-function getCourseBySlug(courses, slug) {
- return courses.find((course) => course.slug === slug) || null;
-}
-
-function mapDispatchToProps(dispatch) {
- return {
- actions: bindActionCreators(
- {
- loadCourses,
- loadAuthors,
- saveCourse
- },
- dispatch
- )
- };
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(ManageCoursePage);
diff --git a/src/features/session/components/SessionListComponent.js b/src/features/session/components/SessionListComponent.js
index da9857c..e751a62 100644
--- a/src/features/session/components/SessionListComponent.js
+++ b/src/features/session/components/SessionListComponent.js
@@ -7,6 +7,7 @@ import Typography from "@material-ui/core/Typography";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import PropTypes from "prop-types";
import SessionSummary from "./SessionSummary";
+import Spinner from "../../../components/common/Spinner";
const useStyles = makeStyles((theme) => ({
root: {
@@ -24,7 +25,10 @@ const SessionListComponent = ({ sessions }) => {
return (
Sessions
- {sessions.loaded &&
+ {sessions.loading ? (
+
+ ) : (
+ sessions.loaded &&
sessions.map((session) => {
return (
@@ -44,7 +48,8 @@ const SessionListComponent = ({ sessions }) => {
);
- })}
+ })
+ )}
);
};
diff --git a/src/redux/actions/actionTypes.js b/src/redux/actions/actionTypes.js
index dde65a7..09963a6 100644
--- a/src/redux/actions/actionTypes.js
+++ b/src/redux/actions/actionTypes.js
@@ -1,16 +1,3 @@
-export const CREATE_COURSE = "CREATE_COURSE";
-export const LOAD_COURSES_SUCCESS = "LOAD_COURSES_SUCCESS";
-export const LOAD_AUTHORS_SUCCESS = "LOAD_AUTHORS_SUCCESS";
-export const CREATE_COURSE_SUCCESS = "CREATE_COURSE_SUCCESS";
-export const UPDATE_COURSE_SUCCESS = "UPDATE_COURSE_SUCCESS";
-
-// By convention, actions that end in "_SUCCESS" are assumed to have been the result of a completed
-// API call. But since we're doing an optimistic delete, we're hiding loading state.
-// So this action name deliberately omits the "_SUCCESS" suffix.
-// If it had one, our apiCallsInProgress counter would be decremented below zero
-// because we're not incrementing the number of apiCallInProgress when the delete request begins.
-export const DELETE_COURSE_OPTIMISTIC = "DELETE_COURSE_OPTIMISTIC";
-
export const BEGIN_AJAX_CALL = "BEGIN_AJAX_CALL";
export const AJAX_CALL_ERROR = "AJAX_CALL_ERROR";
export const END_AJAX_CALL = "END_AJAX_CALL";
diff --git a/src/redux/actions/authorActions.js b/src/redux/actions/authorActions.js
deleted file mode 100644
index 0e49bfc..0000000
--- a/src/redux/actions/authorActions.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import * as types from "./actionTypes";
-import * as authorApi from "../../api/authorApi";
-import { sendHttpRequest } from "../actions/httpActions";
-
-function loadAuthorsSuccess(authors) {
- return { type: types.LOAD_AUTHORS_SUCCESS, authors };
-}
-
-export function loadAuthors() {
- return async function (dispatch) {
- try {
- const authors = await dispatch(sendHttpRequest(authorApi.getAuthors()));
- dispatch(loadAuthorsSuccess(authors));
- } catch (error) {
- throw error;
- }
- };
-}
diff --git a/src/redux/actions/courseActions.js b/src/redux/actions/courseActions.js
deleted file mode 100644
index 59278c9..0000000
--- a/src/redux/actions/courseActions.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import * as types from "./actionTypes";
-import * as courseApi from "../../api/courseApi";
-import { sendHttpRequest } from "../actions/httpActions";
-
-function loadCoursesSuccess(courses) {
- return { type: types.LOAD_COURSES_SUCCESS, courses };
-}
-
-export function createCourseSuccess(course) {
- return { type: types.CREATE_COURSE_SUCCESS, course };
-}
-
-export function updateCourseSuccess(course) {
- return { type: types.UPDATE_COURSE_SUCCESS, course };
-}
-
-export function deleteCourseOptimistic(course) {
- return { type: types.DELETE_COURSE_OPTIMISTIC, course };
-}
-
-export function loadCourses() {
- return function (dispatch) {
- return dispatch(sendHttpRequest(courseApi.getCourses()))
- .then((courses) => {
- dispatch(loadCoursesSuccess(courses));
- })
- .catch((error) => {
- throw error;
- });
- };
-}
-
-export function saveCourse(course) {
- //eslint-disable-next-line no-unused-vars
- return function (dispatch, getState) {
- return dispatch(sendHttpRequest(courseApi.saveCourse(course)))
- .then((savedCourse) => {
- course.id
- ? dispatch(updateCourseSuccess(savedCourse))
- : dispatch(createCourseSuccess(savedCourse));
- })
- .catch((error) => {
- throw error;
- });
- };
-}
-
-export function deleteCourse(course) {
- return function (dispatch) {
- // Doing optimistic delete, so not dispatching begin/end api call
- // actions, or apiCallError action since we're not showing the loading status for this.
- dispatch(deleteCourseOptimistic(course));
- return courseApi.deleteCourse(course.id);
- };
-}
diff --git a/src/redux/reducers/authorReducer.js b/src/redux/reducers/authorReducer.js
deleted file mode 100644
index 6fc82c7..0000000
--- a/src/redux/reducers/authorReducer.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import * as types from "../actions/actionTypes";
-import initialState from "./initialState";
-
-export default function authorReducer(state = initialState.authors, action) {
- switch (action.type) {
- case types.LOAD_AUTHORS_SUCCESS:
- return action.authors;
-
- default:
- return state;
- }
-}
diff --git a/src/redux/reducers/courseReducer.js b/src/redux/reducers/courseReducer.js
deleted file mode 100644
index dcdbae5..0000000
--- a/src/redux/reducers/courseReducer.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import * as types from "../actions/actionTypes";
-import initialState from "./initialState";
-
-export default function courseReducer(state = initialState.courses, action) {
- switch (action.type) {
- case types.LOAD_COURSES_SUCCESS:
- return action.courses;
-
- case types.CREATE_COURSE_SUCCESS:
- return [...state, { ...action.course }];
-
- case types.UPDATE_COURSE_SUCCESS:
- return state.map((course) =>
- course.id === action.course.id ? action.course : course
- );
-
- case types.DELETE_COURSE_OPTIMISTIC:
- return state.filter((course) => course.id !== action.course.id);
-
- default:
- return state;
- }
-}
diff --git a/src/redux/reducers/index.js b/src/redux/reducers/index.js
index f2ae5ce..b3d37d0 100644
--- a/src/redux/reducers/index.js
+++ b/src/redux/reducers/index.js
@@ -1,6 +1,4 @@
import { combineReducers } from "redux";
-import courseReducer from "./courseReducer";
-import authorReducer from "./authorReducer";
import ajaxStatusReducer from "./ajaxStatusReducer";
import systemReducer from "../../features/system/reducer";
import sessionsReducer from "../../features/session/reducer";
@@ -8,8 +6,6 @@ import sessionsReducer from "../../features/session/reducer";
const rootReducer = combineReducers({
system: systemReducer,
sessions: sessionsReducer,
- courses: courseReducer,
- authors: authorReducer,
ajaxCallsInProgress: ajaxStatusReducer
});
diff --git a/src/redux/reducers/initialState.js b/src/redux/reducers/initialState.js
index 0bf616a..218f346 100644
--- a/src/redux/reducers/initialState.js
+++ b/src/redux/reducers/initialState.js
@@ -1,7 +1,5 @@
export default {
system: {},
sessions: Object.assign([], { loading: false, loaded: false }),
- courses: [],
- authors: [],
ajaxCallsInProgress: 0
};