removed old components
parent
828ab3883a
commit
28ab66ac09
|
@ -1,6 +0,0 @@
|
||||||
import { get } from "./api";
|
|
||||||
const baseUrl = process.env.API_URL + "/authors/";
|
|
||||||
|
|
||||||
export function getAuthors() {
|
|
||||||
return get(baseUrl);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -4,8 +4,6 @@ import HomePage from "./home/HomePage";
|
||||||
import AboutPage from "./about/AboutPage";
|
import AboutPage from "./about/AboutPage";
|
||||||
import Header from "./common/Header";
|
import Header from "./common/Header";
|
||||||
import PageNotFound from "./PageNotFound";
|
import PageNotFound from "./PageNotFound";
|
||||||
import CoursesPage from "./courses/CoursesPage";
|
|
||||||
import ManageCoursePage from "./courses/ManageCoursePage";
|
|
||||||
import { ToastContainer } from "react-toastify";
|
import { ToastContainer } from "react-toastify";
|
||||||
import "react-toastify/dist/ReactToastify.css";
|
import "react-toastify/dist/ReactToastify.css";
|
||||||
import SessionContainer from "../features/session/components/SessionContainer";
|
import SessionContainer from "../features/session/components/SessionContainer";
|
||||||
|
@ -17,9 +15,6 @@ function App() {
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" component={HomePage} />
|
<Route exact path="/" component={HomePage} />
|
||||||
<Route path="/about" component={AboutPage} />
|
<Route path="/about" component={AboutPage} />
|
||||||
<Route path="/courses" component={CoursesPage} />
|
|
||||||
<Route path="/course/:slug" component={ManageCoursePage} />
|
|
||||||
<Route path="/course" component={ManageCoursePage} />
|
|
||||||
<Route path="/sessions" component={SessionContainer} />
|
<Route path="/sessions" component={SessionContainer} />
|
||||||
<Route component={PageNotFound} />
|
<Route component={PageNotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
@ -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 (
|
|
||||||
<form onSubmit={onSave}>
|
|
||||||
<h2>{course.id ? "Edit" : "Add"} Course</h2>
|
|
||||||
{errors.onSave && (
|
|
||||||
<div className="alert alert-danger" role="alert">
|
|
||||||
{errors.onSave}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<TextInput
|
|
||||||
name="title"
|
|
||||||
label="Title"
|
|
||||||
value={course.title}
|
|
||||||
onChange={onChange}
|
|
||||||
error={errors.title}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SelectInput
|
|
||||||
name="authorId"
|
|
||||||
label="Author"
|
|
||||||
value={course.authorId || ""}
|
|
||||||
defaultOption="Select Author"
|
|
||||||
options={authors.map((author) => ({
|
|
||||||
value: author.id,
|
|
||||||
text: author.name
|
|
||||||
}))}
|
|
||||||
onChange={onChange}
|
|
||||||
error={errors.author}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextInput
|
|
||||||
name="category"
|
|
||||||
label="Category"
|
|
||||||
value={course.category}
|
|
||||||
onChange={onChange}
|
|
||||||
error={errors.category}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<button type="submit" disabled={saving} className="btn btn-primary">
|
|
||||||
{saving ? "Saving..." : "Save"}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
|
@ -1,53 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import PropTypes from "prop-types";
|
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
|
|
||||||
const CourseList = ({ courses, onDeleteClick }) => (
|
|
||||||
<table className="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th />
|
|
||||||
<th>Title</th>
|
|
||||||
<th>Author</th>
|
|
||||||
<th>Category</th>
|
|
||||||
<th />
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{courses.map((course) => {
|
|
||||||
return (
|
|
||||||
<tr key={course.id}>
|
|
||||||
<td>
|
|
||||||
<a
|
|
||||||
className="btn btn-light"
|
|
||||||
href={"http://pluralsight.com/courses/" + course.slug}
|
|
||||||
>
|
|
||||||
Watch
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Link to={"/course/" + course.slug}>{course.title}</Link>
|
|
||||||
</td>
|
|
||||||
<td>{course.authorName}</td>
|
|
||||||
<td>{course.category}</td>
|
|
||||||
<td>
|
|
||||||
<button
|
|
||||||
className="btn btn-outline-danger"
|
|
||||||
onClick={() => onDeleteClick(course)}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
);
|
|
||||||
|
|
||||||
CourseList.propTypes = {
|
|
||||||
courses: PropTypes.array.isRequired,
|
|
||||||
onDeleteClick: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CourseList;
|
|
|
@ -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 && <Redirect to="/course" />}
|
|
||||||
<h2>Courses</h2>
|
|
||||||
{this.props.loading ? (
|
|
||||||
<Spinner />
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
style={{ marginBottom: 20 }}
|
|
||||||
className="btn btn-primary add-course"
|
|
||||||
onClick={() => this.setState({ redirectToAddCoursePage: true })}
|
|
||||||
>
|
|
||||||
Add Course
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<CourseList
|
|
||||||
courses={this.props.courses}
|
|
||||||
onDeleteClick={this.handleDeleteCourse}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
|
@ -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 ? (
|
|
||||||
<Spinner />
|
|
||||||
) : (
|
|
||||||
<CourseForm
|
|
||||||
course={course}
|
|
||||||
errors={errors}
|
|
||||||
authors={authors}
|
|
||||||
onChange={handleChange}
|
|
||||||
onSave={handleSave}
|
|
||||||
saving={saving}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
|
@ -7,6 +7,7 @@ import Typography from "@material-ui/core/Typography";
|
||||||
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import SessionSummary from "./SessionSummary";
|
import SessionSummary from "./SessionSummary";
|
||||||
|
import Spinner from "../../../components/common/Spinner";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
root: {
|
root: {
|
||||||
|
@ -24,7 +25,10 @@ const SessionListComponent = ({ sessions }) => {
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<h2>Sessions</h2>
|
<h2>Sessions</h2>
|
||||||
{sessions.loaded &&
|
{sessions.loading ? (
|
||||||
|
<Spinner />
|
||||||
|
) : (
|
||||||
|
sessions.loaded &&
|
||||||
sessions.map((session) => {
|
sessions.map((session) => {
|
||||||
return (
|
return (
|
||||||
<ExpansionPanel key={session.sessionId}>
|
<ExpansionPanel key={session.sessionId}>
|
||||||
|
@ -44,7 +48,8 @@ const SessionListComponent = ({ sessions }) => {
|
||||||
</ExpansionPanelDetails>
|
</ExpansionPanelDetails>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
);
|
);
|
||||||
})}
|
})
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 BEGIN_AJAX_CALL = "BEGIN_AJAX_CALL";
|
||||||
export const AJAX_CALL_ERROR = "AJAX_CALL_ERROR";
|
export const AJAX_CALL_ERROR = "AJAX_CALL_ERROR";
|
||||||
export const END_AJAX_CALL = "END_AJAX_CALL";
|
export const END_AJAX_CALL = "END_AJAX_CALL";
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,4 @@
|
||||||
import { combineReducers } from "redux";
|
import { combineReducers } from "redux";
|
||||||
import courseReducer from "./courseReducer";
|
|
||||||
import authorReducer from "./authorReducer";
|
|
||||||
import ajaxStatusReducer from "./ajaxStatusReducer";
|
import ajaxStatusReducer from "./ajaxStatusReducer";
|
||||||
import systemReducer from "../../features/system/reducer";
|
import systemReducer from "../../features/system/reducer";
|
||||||
import sessionsReducer from "../../features/session/reducer";
|
import sessionsReducer from "../../features/session/reducer";
|
||||||
|
@ -8,8 +6,6 @@ import sessionsReducer from "../../features/session/reducer";
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
system: systemReducer,
|
system: systemReducer,
|
||||||
sessions: sessionsReducer,
|
sessions: sessionsReducer,
|
||||||
courses: courseReducer,
|
|
||||||
authors: authorReducer,
|
|
||||||
ajaxCallsInProgress: ajaxStatusReducer
|
ajaxCallsInProgress: ajaxStatusReducer
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
export default {
|
export default {
|
||||||
system: {},
|
system: {},
|
||||||
sessions: Object.assign([], { loading: false, loaded: false }),
|
sessions: Object.assign([], { loading: false, loaded: false }),
|
||||||
courses: [],
|
|
||||||
authors: [],
|
|
||||||
ajaxCallsInProgress: 0
|
ajaxCallsInProgress: 0
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue