From 6ccb41587ca061d0b15ac09959deddb17b29ad39 Mon Sep 17 00:00:00 2001 From: Benny Ogidan Date: Sun, 17 Dec 2017 08:47:51 +0100 Subject: [PATCH] chore (changing filenames): Implementing correct naming conventions - Fix for loading of userList on heroku - Shortened Google Auth for usernames --- client/src/app/actions/actionType.js | 108 +++++++++ client/src/app/actions/admin/addCategory.js | 2 +- client/src/app/actions/admin/books.js | 2 +- .../src/app/actions/admin/changeUserLevel.js | 2 +- .../src/app/actions/admin/deleteCategory.js | 2 +- client/src/app/actions/admin/editCategory.js | 2 +- .../actions/admin/getAdminNotifications.js | 10 +- .../src/app/actions/admin/getSelectedUser.js | 2 +- .../src/app/actions/admin/getUserLevelList.js | 2 +- client/src/app/actions/admin/getUserList.js | 2 +- client/src/app/actions/api.js | 4 +- client/src/app/actions/authenticate.js | 7 +- client/src/app/actions/borrowBooks.js | 43 ++++ client/src/app/actions/borrowbooks.js | 2 +- client/src/app/actions/changePassword.js | 2 +- client/src/app/actions/fetchBooks.js | 137 +++++++++++ client/src/app/actions/fetchCategories.js | 77 ++++++ client/src/app/actions/fetchbooks.js | 2 +- client/src/app/actions/fetchcategories.js | 2 +- client/src/app/actions/loanHistory.js | 36 +++ client/src/app/actions/loanhistory.js | 14 +- client/src/app/actions/returnBooks.js | 34 +++ client/src/app/actions/returnbooks.js | 2 +- client/src/app/actions/searchBooks.js | 40 ++++ client/src/app/actions/searchbooks.js | 2 +- client/src/app/actions/uploadImage.js | 2 +- .../container/booklist/DisplayAllBooks.jsx | 21 +- .../booklist/DisplayBorrowedBooks.jsx | 8 +- .../booklist/DisplayOverdueBooks.jsx | 14 +- .../container/booklist/DisplayRecentBooks.jsx | 25 +- .../categories/CategoriesCollectionList.jsx | 12 +- .../categories/getCategoriesWrapper.jsx | 5 +- .../container/loanhistory/LoanHistory.jsx | 16 +- .../notification/NotificationTab.jsx | 34 ++- .../container/password/ChangePassword.jsx | 2 +- .../container/userlists/UserListTable.jsx | 1 - .../{UserList.jsx => UserListTab.jsx} | 12 +- .../components/presentation/UserDashboard.jsx | 3 +- .../presentation/admin/AdminDashboard.jsx | 4 +- .../authentication/SignInPage.jsx | 116 +++++---- .../authentication/SignUpPage.jsx | 114 +++++---- .../presentation/common/book/DisplayBook.jsx | 33 ++- .../common/book/DisplayBookModal.jsx | 7 +- .../presentation/common/book/SearchBooks.jsx | 4 +- .../common/modal/AddEditBookModal.jsx | 224 ------------------ .../common/modal/ChangeUserLevelModal.jsx | 39 +-- .../common/modal/EditBookModal.jsx | 16 +- .../presentation/common/modal/UploadModal.jsx | 13 +- client/src/app/reducers/bookReducers.js | 2 +- client/src/app/reducers/categoryReducers.js | 2 +- client/src/app/reducers/imageReducers.js | 2 +- client/src/app/reducers/notifierReducers.js | 4 +- client/src/app/reducers/userReducers.js | 2 +- server/src/controllers/books.js | 6 +- .../controllers/middleware/checkGoogleAuth.js | 2 +- server/src/controllers/notifications.js | 15 +- server/src/controllers/user.js | 41 +++- server/src/test/books.spec.js | 2 +- server/src/test/user.spec.js | 4 +- server/src/test/userbooks.spec.js | 2 +- 60 files changed, 879 insertions(+), 468 deletions(-) create mode 100644 client/src/app/actions/actionType.js create mode 100644 client/src/app/actions/borrowBooks.js create mode 100644 client/src/app/actions/fetchBooks.js create mode 100644 client/src/app/actions/fetchCategories.js create mode 100644 client/src/app/actions/loanHistory.js create mode 100644 client/src/app/actions/returnBooks.js create mode 100644 client/src/app/actions/searchBooks.js rename client/src/app/components/container/userlists/container/{UserList.jsx => UserListTab.jsx} (89%) delete mode 100644 client/src/app/components/presentation/common/modal/AddEditBookModal.jsx diff --git a/client/src/app/actions/actionType.js b/client/src/app/actions/actionType.js new file mode 100644 index 0000000..40d6672 --- /dev/null +++ b/client/src/app/actions/actionType.js @@ -0,0 +1,108 @@ +export const USER_LOGGED_IN = 'USER_LOGGED_IN'; + +export const USER_LOG_IN_FAILURE = 'USER_LOG_IN_FAILURE'; + +export const USER_LOGGED_OUT = 'USER_LOGGED_OUT'; + +export const SIGN_UP_USER_FAILURE = 'SIGN_UP_USER_FAILURE'; + +export const SIGNUP_USER_SUCCESS = 'SIGNUP_USER_SUCCESS'; + +export const FETCH_SELECTED_BOOK_SUCCESS = 'FETCH_SELECTED_BOOK_SUCCESS'; + +export const FETCH_SELECTED_BOOK_FAILURE = 'FETCH_SELECTED_BOOK_FAILURE'; + +export const CREATE_BOOK_SUCCESS = 'CREATE_BOOK_SUCCESS'; + +export const CREATE_BOOK_FAILURE = 'CREATE_BOOK_FAILURE'; + +export const FETCH_ALL_RECENT_BOOKS = 'FETCH_ALL_RECENT_BOOKS '; + +export const FETCH_ALL_BOOKS = 'FETCH_ALL_BOOKS '; + +export const FETCH_BOOKS_BY_USER_ID = 'FETCH_BOOKS_BY_USER_ID'; + +export const FETCH_BOOKS_REJECTED = 'FETCH_BOOKS_REJECTED'; + +export const FETCH_ALL_OVERDUE_BOOKS = 'FETCH_ALL_OVERDUE_BOOKS'; + +export const FETCH_ALL_OVERDUE_REJECTED = 'FETCH_ALL_OVERDUE_REJECTED'; + +export const UPLOAD_TO_CLOUD_IMAGE_SUCCESS = 'UPLOAD_TO_CLOUD_IMAGE_SUCCESS'; + +export const UPLOAD_TO_CLOUD_IMAGE_FAILURE = 'UPLOAD_TO_CLOUD_IMAGE_FAILURE'; + +export const SEARCH_BOOKS_SUCCESS = 'SEARCH_BOOKS_SUCCESS'; + +export const SEARCH_BOOKS_FAILURE = 'SEARCH_BOOKS_FAILURE'; + +export const FETCH_CATEGORIES_SUCCESS = 'FETCH_CATEGORIES_SUCCESS'; + +export const FETCH_CATEGORIES_FAILURE = 'FETCH_CATEGORIES_FAILURE'; + +export const FETCH_BOOKS_FOR_CATEGORIES_SUCCESS = +'FETCH_BOOKS_FOR_CATEGORIES_SUCCESS'; + +export const FETCH_BOOKS_FOR_CATEGORIES_FAILURE = +'FETCH_BOOKS_FOR_CATEGORIES_FAILURE'; + +export const CLOUDINARY_UPLOAD_PRESET = 'yn0wpv0n'; + +export const CLOUDINARY_UPLOAD_URL = +'https://api.cloudinary.com/v1_1/digpnxufx/upload'; + +export const UPDATE_BOOK_SUCCESS = 'UPDATE_BOOK_SUCCESS'; + +export const UPDATE_BOOK_FAILURE = 'UPDATE_BOOK_FAILURE'; + +export const BORROW_BOOKS_SUCCESS = 'BORROW_BOOKS_SUCCESS'; + +export const BORROW_BOOKS_FAIL = 'BORROW_BOOKS_FAIL'; + +export const RETURN_BOOKS_SUCCESS = 'RETURN_BOOKS_SUCCESS'; + +export const RETURN_BOOKS_FAIL = 'RETURN_BOOKS_FAIL'; + +export const LOAN_HISTORY_SUCCESS = 'LOAN_HISTORY_SUCCESS'; + +export const LOAN_HISTORY_FAILURE = 'LOAN_HISTORY_FAILURE'; + +export const DELETE_BOOK_SUCCESS = 'DELETE_BOOK_SUCCESS'; + +export const DELETE_BOOK_FAILURE = 'DELETE_BOOK_FAILURE'; + +export const ADD_CATEGORY_SUCCESS = 'ADD_CATEGORY_SUCCESS'; + +export const ADD_CATEGORY_FAILURE = 'ADD_CATEGORY_FAILURE'; + +export const EDIT_CATEGORY_SUCCESS = 'EDIT_CATEGORY_SUCCESS'; + +export const EDIT_CATEGORY_FAILURE = 'EDIT_CATEGORY_FAILURE'; + +export const DELETE_CATEGORY_SUCCESS = 'DELETE_CATEGORY_SUCCESS'; + +export const DELETE_CATEGORY_FAILURE = 'DELETE_CATEGORY_FAILURE'; + +export const GET_USER_LIST_SUCCESS = 'GET_USER_LIST_SUCCESS'; + +export const GET_USER_LIST_FAILURE = 'GET_USER_LIST_FAILURE'; + +export const GET_USER_LEVEL_LIST_SUCCESS = 'GET_USER_LEVEL_LIST_SUCCESS'; + +export const GET_USER_LEVEL_LIST_FAILURE = 'GET_USER_LEVEL_LIST_FAILURE'; + +export const CHANGE_USER_LEVEL_SUCCESS = 'CHANGE_USER_LEVEL_SUCCESS'; + +export const CHANGE_USER_LEVEL_FAILURE = 'CHANGE_USER_LEVEL_FAILURE'; + +export const GET_USER_SUCCESS = 'GET_USER_SUCCESS'; + +export const GET_USER_FAILURE = 'GET_USER_FAILURE'; + +export const PASSWORD_CHANGED_SUCCESS = 'PASSWORD_CHANGED_SUCCESS'; + +export const PASSWORD_CHANGED_FAILURE = 'PASSWORD_CHANGED_FAILURE'; + +export const GET_NOTIFICATIONS_SUCCESS = 'GET_NOTIFICATIONS_SUCCESS'; + +export const GET_NOTIFICATIONS_FAILURE = 'GET_NOTIFICATIONS_FAILURE'; diff --git a/client/src/app/actions/admin/addCategory.js b/client/src/app/actions/admin/addCategory.js index b9cd131..f3cb624 100644 --- a/client/src/app/actions/admin/addCategory.js +++ b/client/src/app/actions/admin/addCategory.js @@ -5,7 +5,7 @@ import { import { ADD_CATEGORY_FAILURE, ADD_CATEGORY_SUCCESS -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const addCategorySuccess = category => diff --git a/client/src/app/actions/admin/books.js b/client/src/app/actions/admin/books.js index 405505c..2025613 100644 --- a/client/src/app/actions/admin/books.js +++ b/client/src/app/actions/admin/books.js @@ -9,7 +9,7 @@ import { UPDATE_BOOK_FAILURE, DELETE_BOOK_FAILURE, DELETE_BOOK_SUCCESS -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const CreateBookSuccess = book => diff --git a/client/src/app/actions/admin/changeUserLevel.js b/client/src/app/actions/admin/changeUserLevel.js index f192efb..0ae25f4 100644 --- a/client/src/app/actions/admin/changeUserLevel.js +++ b/client/src/app/actions/admin/changeUserLevel.js @@ -5,7 +5,7 @@ import { import { CHANGE_USER_LEVEL_FAILURE, CHANGE_USER_LEVEL_SUCCESS -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const changeUserLevelSuccess = userLevel => ( diff --git a/client/src/app/actions/admin/deleteCategory.js b/client/src/app/actions/admin/deleteCategory.js index 7456037..296c450 100644 --- a/client/src/app/actions/admin/deleteCategory.js +++ b/client/src/app/actions/admin/deleteCategory.js @@ -5,7 +5,7 @@ import { import { DELETE_CATEGORY_SUCCESS, DELETE_CATEGORY_FAILURE -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const deleteCategorySuccess = deletedCategory => ( diff --git a/client/src/app/actions/admin/editCategory.js b/client/src/app/actions/admin/editCategory.js index 04fd590..79bf60a 100644 --- a/client/src/app/actions/admin/editCategory.js +++ b/client/src/app/actions/admin/editCategory.js @@ -4,7 +4,7 @@ import { import { EDIT_CATEGORY_FAILURE, EDIT_CATEGORY_SUCCESS -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const editCategorySuccess = category => diff --git a/client/src/app/actions/admin/getAdminNotifications.js b/client/src/app/actions/admin/getAdminNotifications.js index a868d8d..fe5e4d9 100644 --- a/client/src/app/actions/admin/getAdminNotifications.js +++ b/client/src/app/actions/admin/getAdminNotifications.js @@ -5,7 +5,7 @@ import { import { GET_NOTIFICATIONS_SUCCESS, GET_NOTIFICATIONS_FAILURE -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const getNotificationSuccess = data => ({ @@ -23,11 +23,15 @@ export const getNotificationFailure = error => ({ * * @function getNotification * + * @param {integer} offset + * + * @param {integer} limit + * * @returns {function} asynchronous action */ -export const getAdminNotificationAction = () => dispatch => api +export const getAdminNotificationAction = (offset, limit) => dispatch => api .admin - .getAdminNotifications() + .getAdminNotifications(offset, limit) .then((response) => { dispatch(getNotificationSuccess(response)); return response; diff --git a/client/src/app/actions/admin/getSelectedUser.js b/client/src/app/actions/admin/getSelectedUser.js index ad69c0b..42909b9 100644 --- a/client/src/app/actions/admin/getSelectedUser.js +++ b/client/src/app/actions/admin/getSelectedUser.js @@ -2,7 +2,7 @@ import { showErrorNotification } from '../notifications'; import { GET_USER_SUCCESS, GET_USER_FAILURE -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const getUserSuccess = user => ( diff --git a/client/src/app/actions/admin/getUserLevelList.js b/client/src/app/actions/admin/getUserLevelList.js index bf09c69..6a16f5e 100644 --- a/client/src/app/actions/admin/getUserLevelList.js +++ b/client/src/app/actions/admin/getUserLevelList.js @@ -2,7 +2,7 @@ import { showErrorNotification } from '../notifications'; import { GET_USER_LEVEL_LIST_FAILURE, GET_USER_LEVEL_LIST_SUCCESS -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const getUserLevelListSuccess = userLevelList => ( diff --git a/client/src/app/actions/admin/getUserList.js b/client/src/app/actions/admin/getUserList.js index 18c5ae6..ef694dc 100644 --- a/client/src/app/actions/admin/getUserList.js +++ b/client/src/app/actions/admin/getUserList.js @@ -2,7 +2,7 @@ import { showErrorNotification } from '../notifications'; import { GET_USER_LIST_FAILURE, GET_USER_LIST_SUCCESS -} from '../actiontype'; +} from '../actionType'; import api from '../api'; export const getUserListSuccess = userList => ( diff --git a/client/src/app/actions/api.js b/client/src/app/actions/api.js index 3a51e5a..74ef708 100644 --- a/client/src/app/actions/api.js +++ b/client/src/app/actions/api.js @@ -101,8 +101,8 @@ export default { axios.get(`api/v1/admin/users/${userId}`) .then(res => res.data), - getAdminNotifications: () => - axios.get('api/v1/admin/notifications') + getAdminNotifications: (offset, limit) => + axios.get(`api/v1/admin/notifications/?offset=${offset}&limit=${limit}`) .then(res => res.data) } }; diff --git a/client/src/app/actions/authenticate.js b/client/src/app/actions/authenticate.js index 555b7eb..d9e7b23 100644 --- a/client/src/app/actions/authenticate.js +++ b/client/src/app/actions/authenticate.js @@ -1,11 +1,14 @@ -import { showErrorNotification, showSuccessNotification } from './notifications'; +import +{ showErrorNotification, + showSuccessNotification +} from './notifications'; import { USER_LOGGED_IN, USER_LOG_IN_FAILURE, USER_LOGGED_OUT, SIGNUP_USER_SUCCESS, SIGNUP_USER_FAILURE -} from './actiontype'; +} from './actionType'; import api from './api'; import setAuthorizationToken from '../utils/setAuthorizationToken'; diff --git a/client/src/app/actions/borrowBooks.js b/client/src/app/actions/borrowBooks.js new file mode 100644 index 0000000..abaee0f --- /dev/null +++ b/client/src/app/actions/borrowBooks.js @@ -0,0 +1,43 @@ +import { + showErrorNotification, + showSuccessNotification +} from './notifications'; +import { + BORROW_BOOKS_SUCCESS, + BORROW_BOOKS_FAIL +} from './actionType'; +import api from './api'; + +export const BorrowBooksSuccess = books => + ({ + type: BORROW_BOOKS_SUCCESS, + books + }); +export const BorrowBooksRejected = error => + ({ + type: BORROW_BOOKS_FAIL, + error + }); + +/** + * async helper function: log in user + * + * @function BorrowBooks + * + * @param {object} book + * + * @returns {function} asynchronous action + */ +export const borrowBookAction = book => dispatch => api + .book + .borrowBook(book) + .then((response) => { + dispatch(BorrowBooksSuccess(response)); + dispatch(showSuccessNotification(response)); + return (response); + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(BorrowBooksRejected({ error })); + return ({ error }); + }); diff --git a/client/src/app/actions/borrowbooks.js b/client/src/app/actions/borrowbooks.js index 087c6f5..abaee0f 100644 --- a/client/src/app/actions/borrowbooks.js +++ b/client/src/app/actions/borrowbooks.js @@ -5,7 +5,7 @@ import { import { BORROW_BOOKS_SUCCESS, BORROW_BOOKS_FAIL -} from './actiontype'; +} from './actionType'; import api from './api'; export const BorrowBooksSuccess = books => diff --git a/client/src/app/actions/changePassword.js b/client/src/app/actions/changePassword.js index 83afd13..d2a4649 100644 --- a/client/src/app/actions/changePassword.js +++ b/client/src/app/actions/changePassword.js @@ -5,7 +5,7 @@ import { import { PASSWORD_CHANGED_SUCCESS, PASSWORD_CHANGED_FAILURE -} from './actiontype'; +} from './actionType'; import api from './api'; export const changePasswordSuccess = data => ({ diff --git a/client/src/app/actions/fetchBooks.js b/client/src/app/actions/fetchBooks.js new file mode 100644 index 0000000..708a851 --- /dev/null +++ b/client/src/app/actions/fetchBooks.js @@ -0,0 +1,137 @@ +import { showErrorNotification } from './notifications'; +import { + FETCH_ALL_RECENT_BOOKS, + FETCH_ALL_BOOKS, + FETCH_BOOKS_REJECTED, + FETCH_BOOKS_BY_USER_ID, + FETCH_ALL_OVERDUE_BOOKS, + FETCH_SELECTED_BOOK_FAILURE, + FETCH_SELECTED_BOOK_SUCCESS +} from './actionType'; +import api from './api'; + +export const fetchBooksRejected = error => ({ + type: FETCH_BOOKS_REJECTED, + error +}); +export const fetchRecentBooks = books => ({ + type: FETCH_ALL_RECENT_BOOKS, + books +}); +export const fetchBooks = books => ({ + type: FETCH_ALL_BOOKS, + books +}); +export const fetchBooksByUserId = books => ({ + type: FETCH_BOOKS_BY_USER_ID, + books +}); +export const fetchOverdueBooks = books => ({ + type: FETCH_ALL_OVERDUE_BOOKS, + books +}); +export const fetchSelectedBookSuccess = book => ({ + type: FETCH_SELECTED_BOOK_SUCCESS, + book +}); +export const fetchSelectedBookFailure = error => ({ + type: FETCH_SELECTED_BOOK_FAILURE, + error +}); + +/** + * async helper function: log in user + * + * @function fetchAllBooks + * + * @param {integer} offset + * + * @param {integer} limit + * + * @returns {function} asynchronous action + */ +export const fetchAllBooks = (offset, limit) => dispatch => api + .book + .fetch(offset, limit) + .then((response) => { + dispatch(fetchBooks(response)); + return response; + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(fetchBooksRejected({ error })); + }); + + /** + * async helper function: log in user + * @function fetchOverdueBooks + * @param {integer} offset + * @param {integer} limit + * @returns {function} asynchronous action + */ +export const fetchOverdueBookstoDashboard = (offset, limit) => dispatch => api + .book + .fetchOverdueBooks(offset, limit) + .then((response) => { + dispatch(fetchOverdueBooks(response)); + return response; + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(fetchBooksRejected({ error })); + }); + + +/** + * async helper function: fetch books to go on the dashboard + * @function fetchBooksforDashboard + * @param {integer} offset + * @param {integer} limit + * @returns {function} asynchronous action + */ +export const fetchAllRecentBooks = (offset, limit) => dispatch => api + .book + .fetchRecentBooks(offset, limit) + .then((response) => { + dispatch(fetchRecentBooks(response)); + return response; + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(fetchBooksRejected({ error })); + }); + +/** + * async helper function:fetch books by Id + * @function fetchAllBooksbyId + * @param {object} offset + * @param {object} limit + * @returns {function} asynchronous action + */ +export const fetchAllBorrowedBooks = (offset, limit) => dispatch => api + .book + .fetchBooksByUserId(offset, limit) + .then((response) => { + dispatch(fetchBooksByUserId(response)); + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(fetchBooksRejected({ error })); + }); + /** + * async helper function:fetch selected book + * @function fetchSelectedBook + * @param {number} bookId + * @returns {function} asynchronous action + */ +export const fetchSelectedBook = bookId => dispatch => api + .book + .fetchSelectedBookById(bookId) + .then((response) => { + dispatch(fetchSelectedBookSuccess(response)); + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(fetchSelectedBookFailure({ error })); + }); + diff --git a/client/src/app/actions/fetchCategories.js b/client/src/app/actions/fetchCategories.js new file mode 100644 index 0000000..94bd095 --- /dev/null +++ b/client/src/app/actions/fetchCategories.js @@ -0,0 +1,77 @@ +import { showErrorNotification } from './notifications'; +import { + FETCH_CATEGORIES_SUCCESS, + FETCH_CATEGORIES_FAILURE, + FETCH_BOOKS_FOR_CATEGORIES_SUCCESS, + FETCH_BOOKS_FOR_CATEGORIES_FAILURE +} from './actionType'; +import api from './api'; + + +export const fetchCategoriesFailure = error => + ({ + type: FETCH_CATEGORIES_FAILURE, + error + }); +export const fetchCategoriesSuccess = categories => + ({ + type: FETCH_CATEGORIES_SUCCESS, + categories + }); + +export const fetchBooksCategoriesFailure = error => + ({ + type: FETCH_BOOKS_FOR_CATEGORIES_FAILURE, + error + }); +export const fetchBooksCategoriesSuccess = books => + ({ + type: FETCH_BOOKS_FOR_CATEGORIES_SUCCESS, + books + }); + + +/** + * async helper function: fetch all categories + * + * @function fetchAllCategories + * + * @returns {function} asynchronous action + */ +export const fetchAllCategories = () => dispatch => api + .book + .fetchAllCategories() + .then((response) => { + dispatch(fetchCategoriesSuccess(response)); + return response; + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(fetchCategoriesFailure({ error })); + }); +/** + * @description fetches all books and groups them category + * + * @param {number} categoryId + * + * @param {number} offset + * + * @param {number} limit + * + * @returns {object} asynchronous action + */ +export +const fetchBooksForCategories = (categoryId, offset, limit) => (dispatch) => { + api + .book + .fetchAllBooksByCategories(categoryId, offset, limit) + .then((response) => { + dispatch(fetchBooksCategoriesSuccess(response)); + return response; + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(fetchBooksCategoriesFailure({ error })); + return error; + }); +}; diff --git a/client/src/app/actions/fetchbooks.js b/client/src/app/actions/fetchbooks.js index b0932d0..708a851 100644 --- a/client/src/app/actions/fetchbooks.js +++ b/client/src/app/actions/fetchbooks.js @@ -7,7 +7,7 @@ import { FETCH_ALL_OVERDUE_BOOKS, FETCH_SELECTED_BOOK_FAILURE, FETCH_SELECTED_BOOK_SUCCESS -} from './actiontype'; +} from './actionType'; import api from './api'; export const fetchBooksRejected = error => ({ diff --git a/client/src/app/actions/fetchcategories.js b/client/src/app/actions/fetchcategories.js index ab07bf7..94bd095 100644 --- a/client/src/app/actions/fetchcategories.js +++ b/client/src/app/actions/fetchcategories.js @@ -4,7 +4,7 @@ import { FETCH_CATEGORIES_FAILURE, FETCH_BOOKS_FOR_CATEGORIES_SUCCESS, FETCH_BOOKS_FOR_CATEGORIES_FAILURE -} from './actiontype'; +} from './actionType'; import api from './api'; diff --git a/client/src/app/actions/loanHistory.js b/client/src/app/actions/loanHistory.js new file mode 100644 index 0000000..1ded7e5 --- /dev/null +++ b/client/src/app/actions/loanHistory.js @@ -0,0 +1,36 @@ +import { showErrorNotification } from './notifications'; +import { + LOAN_HISTORY_FAILURE, + LOAN_HISTORY_SUCCESS } from './actionType'; +import api from './api'; + +export const loanHistorySuccess = bookOperations => ({ + type: LOAN_HISTORY_SUCCESS, + bookOperations +}); +export const loanHistoryFailure = error => ({ + type: LOAN_HISTORY_FAILURE, error +}); + +/** + * async helper function: loan history + * + * @function loanhistory + * + * @param {integer} offset + * + * @param {integer} limit + * + * @returns {function} asynchronous action + */ +export const loanHistoryAction = (offset, limit) => dispatch => api + .book + .loanHistory(offset, limit) + .then((response) => { + dispatch(loanHistorySuccess(response)); + return response; + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(loanHistoryFailure({ error })); + }); diff --git a/client/src/app/actions/loanhistory.js b/client/src/app/actions/loanhistory.js index 9c328b4..1ded7e5 100644 --- a/client/src/app/actions/loanhistory.js +++ b/client/src/app/actions/loanhistory.js @@ -1,12 +1,14 @@ import { showErrorNotification } from './notifications'; -import { LOAN_HISTORY_FAILURE, LOAN_HISTORY_SUCCESS } from './actiontype'; +import { + LOAN_HISTORY_FAILURE, + LOAN_HISTORY_SUCCESS } from './actionType'; import api from './api'; -export const loanhistorySuccess = bookOperations => ({ +export const loanHistorySuccess = bookOperations => ({ type: LOAN_HISTORY_SUCCESS, bookOperations }); -export const loanhistoryFailure = error => ({ +export const loanHistoryFailure = error => ({ type: LOAN_HISTORY_FAILURE, error }); @@ -21,14 +23,14 @@ export const loanhistoryFailure = error => ({ * * @returns {function} asynchronous action */ -export const loanhistory = (offset, limit) => dispatch => api +export const loanHistoryAction = (offset, limit) => dispatch => api .book .loanHistory(offset, limit) .then((response) => { - dispatch(loanhistorySuccess(response)); + dispatch(loanHistorySuccess(response)); return response; }) .catch((error) => { dispatch(showErrorNotification({ error })); - dispatch(loanhistoryFailure({ error })); + dispatch(loanHistoryFailure({ error })); }); diff --git a/client/src/app/actions/returnBooks.js b/client/src/app/actions/returnBooks.js new file mode 100644 index 0000000..2844dd0 --- /dev/null +++ b/client/src/app/actions/returnBooks.js @@ -0,0 +1,34 @@ +import { + showErrorNotification, + showSuccessNotification +} from './notifications'; +import { RETURN_BOOKS_FAIL, + RETURN_BOOKS_SUCCESS +} + from './actionType'; +import api from './api'; + +export const ReturnBookSuccess = returnedBook => + ({ + type: RETURN_BOOKS_SUCCESS, + returnedBook + }); +export const ReturnBookRejected = error => ({ type: RETURN_BOOKS_FAIL, error }); + +/** + * async helper function: Return book + * @function ReturnBooks + * @param {object} book + * @returns {function} asynchronous action + */ +export const returnBookAction = book => dispatch => api + .book + .returnBook(book) + .then((response) => { + dispatch(ReturnBookSuccess(response.returnedBook)); + dispatch(showSuccessNotification(response)); + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(ReturnBookRejected(error)); + }); diff --git a/client/src/app/actions/returnbooks.js b/client/src/app/actions/returnbooks.js index 86f923e..2844dd0 100644 --- a/client/src/app/actions/returnbooks.js +++ b/client/src/app/actions/returnbooks.js @@ -5,7 +5,7 @@ import { import { RETURN_BOOKS_FAIL, RETURN_BOOKS_SUCCESS } - from './actiontype'; + from './actionType'; import api from './api'; export const ReturnBookSuccess = returnedBook => diff --git a/client/src/app/actions/searchBooks.js b/client/src/app/actions/searchBooks.js new file mode 100644 index 0000000..89a5ca3 --- /dev/null +++ b/client/src/app/actions/searchBooks.js @@ -0,0 +1,40 @@ +import { showErrorNotification } from './notifications'; +import { + SEARCH_BOOKS_SUCCESS, + SEARCH_BOOKS_FAILURE +} from './actionType'; +import api from './api'; + +export const SearchBookSuccess = books => + ({ + type: SEARCH_BOOKS_SUCCESS, + books + }); +export const SearchBookFailure = error => + ({ + type: SEARCH_BOOKS_FAILURE, + error + }); + + +/** + * async helper function: search Books + * + * @function SearchBooks + * + * @param {object} value + * + * @returns {function} asynchronous action + */ +export const searchAllBooks = value => dispatch => api + .book + .searchBooks(value) + .then((response) => { + dispatch(SearchBookSuccess(response.booksFound)); + return (response); + }) + .catch((error) => { + dispatch(showErrorNotification({ error })); + dispatch(SearchBookFailure({ error })); + return error; + }); diff --git a/client/src/app/actions/searchbooks.js b/client/src/app/actions/searchbooks.js index 3791c2e..89a5ca3 100644 --- a/client/src/app/actions/searchbooks.js +++ b/client/src/app/actions/searchbooks.js @@ -2,7 +2,7 @@ import { showErrorNotification } from './notifications'; import { SEARCH_BOOKS_SUCCESS, SEARCH_BOOKS_FAILURE -} from './actiontype'; +} from './actionType'; import api from './api'; export const SearchBookSuccess = books => diff --git a/client/src/app/actions/uploadImage.js b/client/src/app/actions/uploadImage.js index 8c4341c..f7e11f2 100644 --- a/client/src/app/actions/uploadImage.js +++ b/client/src/app/actions/uploadImage.js @@ -5,7 +5,7 @@ import { showErrorNotification } from './notifications'; import { UPLOAD_TO_CLOUD_IMAGE_SUCCESS, UPLOAD_TO_CLOUD_IMAGE_FAILURE, CLOUDINARY_UPLOAD_PRESET, - CLOUDINARY_UPLOAD_URL } from './actiontype'; + CLOUDINARY_UPLOAD_URL } from './actionType'; export const UploadImageToCloud = response => ({ diff --git a/client/src/app/components/container/booklist/DisplayAllBooks.jsx b/client/src/app/components/container/booklist/DisplayAllBooks.jsx index aec510d..533d6e1 100644 --- a/client/src/app/components/container/booklist/DisplayAllBooks.jsx +++ b/client/src/app/components/container/booklist/DisplayAllBooks.jsx @@ -4,12 +4,13 @@ import { PropTypes } from 'prop-types'; import { Row, Col, Button, Preloader } from 'react-materialize'; import Book from '../../presentation/common/book/DisplayBook.jsx'; import Loader from './Loader.jsx'; -import { fetchAllBooks } from '../../../actions/fetchbooks'; -import { fetchAllCategories } from '../../../actions/fetchcategories'; +import { fetchAllBooks } from '../../../actions/fetchBooks'; +import { fetchAllCategories } from '../../../actions/fetchCategories'; import PaginationWrapper from '../common/Pagination.jsx'; import SearchBooks from '../../presentation/common/book/SearchBooks.jsx'; import CategoriesDropdownList from '../categories/CategoriesDropdownList.jsx'; -import MessageforNoCatBooks from '../../presentation/messages/dashboardMessages/MessageforNoCatBooks.jsx'; +import MessageforNoCatBooks from + '../../presentation/messages/dashboardMessages/MessageforNoCatBooks.jsx'; import EditBookModal from '../../presentation/common/modal/EditBookModal.jsx'; import AddBookModal from '../../presentation/common/modal/AddBookModal.jsx'; @@ -20,7 +21,8 @@ import AddBookModal from '../../presentation/common/modal/AddBookModal.jsx'; */ class DisplayAllBooks extends React.Component { /** - * @description dispatch actions that help populate the dashboard with all the books + * @description dispatch actions that help + * populate the dashboard with all the books * @method componentDidMount * @memberof DisplayAllBooks * @returns {component} Loader @@ -75,7 +77,13 @@ class DisplayAllBooks extends React.Component { } {this.props.isAdmin ?
-
: null } @@ -134,7 +142,8 @@ DisplayAllBooks.defaultProps = { }; const mapStateToProps = state => ({ - allBooksList: (state.bookReducer.allBooksList) ? state.bookReducer.allBooksList : {}, + allBooksList: (state.bookReducer.allBooksList) + ? state.bookReducer.allBooksList : {}, isAdmin: (state.userReducer.user) ? state.userReducer.user.isAdmin : false, }); diff --git a/client/src/app/components/container/booklist/DisplayBorrowedBooks.jsx b/client/src/app/components/container/booklist/DisplayBorrowedBooks.jsx index ed41640..ce077d2 100644 --- a/client/src/app/components/container/booklist/DisplayBorrowedBooks.jsx +++ b/client/src/app/components/container/booklist/DisplayBorrowedBooks.jsx @@ -5,8 +5,9 @@ import { Row, Col } from 'react-materialize'; import PaginationWrapper from '../common/Pagination.jsx'; import Book from '../../presentation/common/book/DisplayBook.jsx'; import Loader from './Loader.jsx'; -import { fetchAllBorrowedBooks } from '../../../actions/fetchbooks'; -import MessageforNoBooks from '../../presentation/messages/dashboardMessages/MessageforNoBooks.jsx'; +import { fetchAllBorrowedBooks } from '../../../actions/fetchBooks'; +import MessageforNoBooks from + '../../presentation/messages/dashboardMessages/MessageforNoBooks.jsx'; /** * @description Component for Display Books on the Landing page for all users @@ -24,7 +25,8 @@ class DisplayAllBorrowedBooks extends React.Component { componentDidMount() { return (); } /** diff --git a/client/src/app/components/container/booklist/DisplayOverdueBooks.jsx b/client/src/app/components/container/booklist/DisplayOverdueBooks.jsx index 58da351..c88be65 100644 --- a/client/src/app/components/container/booklist/DisplayOverdueBooks.jsx +++ b/client/src/app/components/container/booklist/DisplayOverdueBooks.jsx @@ -5,8 +5,9 @@ import { Row, Col } from 'react-materialize'; import PaginationWrapper from '../common/Pagination.jsx'; import Loader from './Loader.jsx'; import Book from '../../presentation/common/book/DisplayBook.jsx'; -import { fetchOverdueBookstoDashboard } from '../../../actions/fetchbooks'; -import MessageforNoOverdueBooks from '../../presentation/messages/dashboardMessages/MessageforNoOverdueBooks.jsx'; +import { fetchOverdueBookstoDashboard } from '../../../actions/fetchBooks'; +import MessageforNoOverdueBooks from + '../../presentation/messages/dashboardMessages/MessageforNoOverdueBooks.jsx'; /** * @description Component for Display Books on the Landing page for all users @@ -23,7 +24,11 @@ class DisplayOverdueBooks extends React.Component { componentDidMount() { return (); } /** @@ -33,7 +38,8 @@ class DisplayOverdueBooks extends React.Component { * @returns {object} component */ render() { - if (!this.props.overdueBooks || this.props.overdueBooks.books.length === 0) { + if (!this.props.overdueBooks + || this.props.overdueBooks.books.length === 0) { return ; } const getAllBooks = this.props.overdueBooks.books.map(book => ( diff --git a/client/src/app/components/container/booklist/DisplayRecentBooks.jsx b/client/src/app/components/container/booklist/DisplayRecentBooks.jsx index d49eb4b..272b7fc 100644 --- a/client/src/app/components/container/booklist/DisplayRecentBooks.jsx +++ b/client/src/app/components/container/booklist/DisplayRecentBooks.jsx @@ -4,7 +4,7 @@ import { PropTypes } from 'prop-types'; import { Row } from 'react-materialize'; import Loader from './Loader.jsx'; import Book from '../../presentation/common/book/DisplayBook.jsx'; -import { fetchAllRecentBooks } from '../../../actions/fetchbooks'; +import { fetchAllRecentBooks } from '../../../actions/fetchBooks'; /** @@ -17,17 +17,36 @@ class DisplayRecentBooks extends React.Component { /** * @description dispatch actions that help populate the dashboard with books * fetch books for the dashboard + * * @method componentDidMount + * * @memberof DisplayLandingBooks + * * @returns {void} */ componentDidMount() { $('body').css('background-color', 'rgb(204, 204, 204)'); return (); } + + /** + * + * + * @memberof DisplayRecentBooks + * + * @returns {object} void + * + * @memberOf DisplayRecentBooks + * */ + componentWillUnmount() { + $('body').css('background-color', 'rgb(204, 204, 204)'); + } /** * render Display Recent component * @method render @@ -68,7 +87,7 @@ DisplayRecentBooks.propTypes = { books: PropTypes.arrayOf(PropTypes.shape({ title: PropTypes.string.isRequired, author: PropTypes.string.isRequired, - quantity: PropTypes.number.isRequired, + // quantity: PropTypes.number.isRequired, description: PropTypes.string, })) }), diff --git a/client/src/app/components/container/categories/CategoriesCollectionList.jsx b/client/src/app/components/container/categories/CategoriesCollectionList.jsx index 3ff8d2f..6c18775 100644 --- a/client/src/app/components/container/categories/CategoriesCollectionList.jsx +++ b/client/src/app/components/container/categories/CategoriesCollectionList.jsx @@ -130,11 +130,19 @@ class CategoriesCollectionList extends React.Component {
{category.categoryName} - this.deleteCategory(category.id)}> + this.deleteCategory(category.id)} + > delete - this.editCategory(category.id)}> + this.editCategory(category.id)} + > edit diff --git a/client/src/app/components/container/categories/getCategoriesWrapper.jsx b/client/src/app/components/container/categories/getCategoriesWrapper.jsx index e5bc2c1..c0af60e 100644 --- a/client/src/app/components/container/categories/getCategoriesWrapper.jsx +++ b/client/src/app/components/container/categories/getCategoriesWrapper.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Preloader } from 'react-materialize'; -import { fetchBooksForCategories } from '../../../actions/fetchcategories'; +import { fetchBooksForCategories } from '../../../actions/fetchCategories'; const getCategoriesWrapper = (WrappedComponent) => { /** @@ -87,7 +87,8 @@ const getCategoriesWrapper = (WrappedComponent) => { const mapStateToProps = ({ categoryReducer }) => ({ - categoryList: categoryReducer.categoryList + categoryList: (categoryReducer.categoryList) + ? categoryReducer.categoryList : {} }); return connect( diff --git a/client/src/app/components/container/loanhistory/LoanHistory.jsx b/client/src/app/components/container/loanhistory/LoanHistory.jsx index f9f687a..05bfaac 100644 --- a/client/src/app/components/container/loanhistory/LoanHistory.jsx +++ b/client/src/app/components/container/loanhistory/LoanHistory.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { connect } from 'react-redux'; import { Preloader } from 'react-materialize'; import PropTypes from 'prop-types'; -import { loanhistory } from '../../../actions/loanhistory'; +import { loanHistoryAction } from '../../../actions/loanHistory'; import PaginationWrapper from '../common/Pagination.jsx'; import LoanHistoryTable from '../../presentation/loanhistory/LoanHistoryTable.jsx'; @@ -28,7 +28,7 @@ class LoanHistory extends React.Component { */ componentDidMount() { this.props - .loanhistory(this.props.offset, this.props.limit); + .loanHistoryAction(this.props.offset, this.props.limit); } /** * render Loan History component @@ -53,7 +53,7 @@ class LoanHistory extends React.Component {
@@ -70,7 +70,9 @@ LoanHistory.propTypes = { description: PropTypes.string, })) }), - loanhistory: PropTypes.func.isRequired + loanHistoryAction: PropTypes.func.isRequired, + limit: PropTypes.number, + offset: PropTypes.number }; @@ -81,14 +83,10 @@ LoanHistory.defaultProps = { offset: 0 }; -LoanHistory.propTypes = { - limit: PropTypes.number, - offset: PropTypes.number -}; const mapStateToProps = state => ({ bookOperations: state.bookReducer.bookOperations }); -export default connect(mapStateToProps, { loanhistory })(LoanHistory); +export default connect(mapStateToProps, { loanHistoryAction })(LoanHistory); diff --git a/client/src/app/components/container/notification/NotificationTab.jsx b/client/src/app/components/container/notification/NotificationTab.jsx index 185bb26..11060b9 100644 --- a/client/src/app/components/container/notification/NotificationTab.jsx +++ b/client/src/app/components/container/notification/NotificationTab.jsx @@ -4,7 +4,7 @@ import { Preloader } from 'react-materialize'; import PropTypes from 'prop-types'; import { getAdminNotificationAction } from '../../../actions/admin/getAdminNotifications'; -// import PaginationWrapper from '../common/Pagination.jsx'; +import PaginationWrapper from '../common/Pagination.jsx'; import NotificationTable from './NotificationTable.jsx'; /** @@ -25,7 +25,7 @@ class NotificationTab extends React.Component { * @returns {void} */ componentDidMount() { - this.props.getAdminNotificationAction(); + this.props.getAdminNotificationAction(this.props.offset, this.props.limit); } /** * render Notification Tab component @@ -40,14 +40,21 @@ class NotificationTab extends React.Component { if (!this.props.notifications) { return ; } + const { pagination } = this.props.notifications; + const config = { + items: pagination.pageCount, + activePage: pagination.page + }; return (
- - {/* + */} + />
); } @@ -55,24 +62,27 @@ class NotificationTab extends React.Component { NotificationTab.propTypes = { notifications: PropTypes.PropTypes.shape({ - notificationList: PropTypes.arrayOf(PropTypes.shape({ + pagination: PropTypes.object, + notifications: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.number })) }), - getAdminNotificationAction: PropTypes.func.isRequired + getAdminNotificationAction: PropTypes.func.isRequired, + limit: PropTypes.number, + offset: PropTypes.number }; NotificationTab.defaultProps = { notifications: null, - // limit: 5, - // offset: 0 + limit: 5, + offset: 0 }; const mapStateToProps = state => ({ - notifications: - state.notifierReducer.notifications + notifications: (state.notifierReducer.notifications) ? + state.notifierReducer.notifications : {} }); export default diff --git a/client/src/app/components/container/password/ChangePassword.jsx b/client/src/app/components/container/password/ChangePassword.jsx index 0dcc34b..b323cbe 100644 --- a/client/src/app/components/container/password/ChangePassword.jsx +++ b/client/src/app/components/container/password/ChangePassword.jsx @@ -62,7 +62,7 @@ class ChangePassword extends Component { */ onClick() { if (this.isValid()) { - this.setState({ errors: {} }); + this.setState({ errors: {} }); this.props.changePasswordAction({ newPassword: this.state.password, oldPassword: this.state.oldPassword diff --git a/client/src/app/components/container/userlists/UserListTable.jsx b/client/src/app/components/container/userlists/UserListTable.jsx index 32514e7..870f83d 100644 --- a/client/src/app/components/container/userlists/UserListTable.jsx +++ b/client/src/app/components/container/userlists/UserListTable.jsx @@ -60,7 +60,6 @@ class UserListTable extends React.Component { >Edit - )) : null; return (rows ? diff --git a/client/src/app/components/container/userlists/container/UserList.jsx b/client/src/app/components/container/userlists/container/UserListTab.jsx similarity index 89% rename from client/src/app/components/container/userlists/container/UserList.jsx rename to client/src/app/components/container/userlists/container/UserListTab.jsx index ce72c63..aecee9b 100644 --- a/client/src/app/components/container/userlists/container/UserList.jsx +++ b/client/src/app/components/container/userlists/container/UserListTab.jsx @@ -14,7 +14,7 @@ import UserListTable from '../UserListTable.jsx'; * * @extends {React.Component} */ -class UserList extends React.Component { +class UserListTab extends React.Component { /** * @description dispatch actions that * help populate the admin dashboard with userlists @@ -60,7 +60,7 @@ class UserList extends React.Component { } } -UserList.propTypes = { +UserListTab.propTypes = { userList: PropTypes.PropTypes.shape({ id: PropTypes.number, map: PropTypes.object, @@ -74,20 +74,20 @@ UserList.propTypes = { }; -UserList.defaultProps = { +UserListTab.defaultProps = { userList: null, limit: 5, offset: 0 }; -UserList.propTypes = { +UserListTab.propTypes = { limit: PropTypes.number, offset: PropTypes.number }; const mapStateToProps = state => ({ - userList: state.userReducer.userList + userList: (state.userReducer.userList) ? state.userReducer.userList : {} }); -export default connect(mapStateToProps, { getUserListAction })(UserList); +export default connect(mapStateToProps, { getUserListAction })(UserListTab); diff --git a/client/src/app/components/presentation/UserDashboard.jsx b/client/src/app/components/presentation/UserDashboard.jsx index 2ae125f..dc6893a 100644 --- a/client/src/app/components/presentation/UserDashboard.jsx +++ b/client/src/app/components/presentation/UserDashboard.jsx @@ -2,7 +2,8 @@ import React from 'react'; import { Row } from 'react-materialize'; import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'; import SideNav from '../presentation/common/SideNav/index.jsx'; -import DisplayAllBorrowedBooks from '../container/booklist/DisplayBorrowedBooks.jsx'; +import DisplayAllBorrowedBooks from + '../container/booklist/DisplayBorrowedBooks.jsx'; import DisplayAllBooks from '../container/booklist/DisplayAllBooks.jsx'; import LoanHistoryTable from '../container/loanhistory/LoanHistory.jsx'; import DisplayOverdueBooks from '../container/booklist/DisplayOverdueBooks.jsx'; diff --git a/client/src/app/components/presentation/admin/AdminDashboard.jsx b/client/src/app/components/presentation/admin/AdminDashboard.jsx index 6c035ac..fa49c0b 100644 --- a/client/src/app/components/presentation/admin/AdminDashboard.jsx +++ b/client/src/app/components/presentation/admin/AdminDashboard.jsx @@ -6,7 +6,7 @@ import DisplayAllBooks from '../../container/booklist/DisplayAllBooks.jsx'; import getDashboardWrapper from '../../container/Dashboard.jsx'; import CategoryAdminTab from '../../container/categories/CategoriesAdminTab.jsx'; -import UserList from '../../container/userlists/container/UserList.jsx'; +import UserListTab from '../../container/userlists/container/UserListTab.jsx'; import NotificationTab from '../../container/notification/NotificationTab.jsx'; /** * @@ -43,7 +43,7 @@ class AdminDashboard extends React.PureComponent { - + diff --git a/client/src/app/components/presentation/authentication/SignInPage.jsx b/client/src/app/components/presentation/authentication/SignInPage.jsx index 883f8fc..ec6910f 100644 --- a/client/src/app/components/presentation/authentication/SignInPage.jsx +++ b/client/src/app/components/presentation/authentication/SignInPage.jsx @@ -5,15 +5,23 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { GoogleLogin } from 'react-google-login'; import { login } from '../../../actions/authenticate'; -import Bottom from '../../../components/presentation/common/Footer.jsx' +import Bottom from '../../../components/presentation/common/Footer.jsx'; /** * SignIn component + * * @class SignIn - * @param {object} + * * @extends React.Component */ class SignInPage extends Component { + /** + * Creates an instance of SignInPage. + * + * @param {object} props + * + * @memberOf SignInPage + */ constructor(props) { super(props); this.state = { @@ -36,53 +44,47 @@ class SignInPage extends Component { * Handle onChange events on form inputs * @method onChange * @memberof SignIn - * @param {object} event + * @param {object} e * @returns {function} a function that handles change event on inputs */ - onChange = e => { + onChange = (e) => { e.preventDefault(); this.setState({ ...this.state, [e.target.name]: e.target.value - }) + }); } /** * Submit state - * This is called when the submit button is clicked + * @description This is called when the submit button is clicked + * * @method submit + * + * @param {object} e + * * @memberof SignIn - * @returns {function} + * + * @returns {function} response */ onSubmit = (e) => { e.preventDefault(); this - .props - .login(this.state) - .then((response) => { - console.log(response,'>>>>>>>>>>>??????>>>') - if(response.success && response.isAdmin) - - { - console.log(response,'ADMIIIIN') - return - this - .props - .history - .push('/admin') - - } - console.log(response,'>>>>>>>>>>>>>>') - this - .props - .history - .push('/dashboard') - }) - .catch(()=>{ - - }) + .props + .login(this.state) + .then((response) => { + if (response.success && response.isAdmin) { + return this.props.history.push('/admin'); + } + this + .props + .history + .push('/dashboard'); + }) + .catch(() => { + }); } /** @@ -91,11 +93,9 @@ class SignInPage extends Component { * @memberof Login */ handleGoogleLogin(response) { - this + this .props - .login( - response.profileObj - ) + .login(response.profileObj) .then((res) => { if (res) { this @@ -104,9 +104,6 @@ class SignInPage extends Component { .push('/dashboard'); } }); - // if (response.error) { - // Materialize.toast('Please resume google login', 4000, ''); - // } } /** * render login component @@ -117,31 +114,33 @@ class SignInPage extends Component { render() { return (
-
-
+
+
-
+
LOGIN
-
+
+ onChange={this.onChange} + > account_circle + onChange={this.onChange} + > lock @@ -149,24 +148,25 @@ class SignInPage extends Component { {/*

Forgotten Password

*/} - +

Sign Up

- -
- + +
+
- -
+ +
- + - + onFailure={this.handleGoogleLogin} + > + Sign in with Google @@ -177,12 +177,10 @@ class SignInPage extends Component {
- +
- ); } - } -export default connect(null, {login})(SignInPage); +export default connect(null, { login })(SignInPage); diff --git a/client/src/app/components/presentation/authentication/SignUpPage.jsx b/client/src/app/components/presentation/authentication/SignUpPage.jsx index feaabff..f6e0bec 100644 --- a/client/src/app/components/presentation/authentication/SignUpPage.jsx +++ b/client/src/app/components/presentation/authentication/SignUpPage.jsx @@ -1,23 +1,29 @@ -import React, {Component} from 'react'; -import {NavLink} from 'react-router-dom'; -import {Input, Col, Row, Icon, Button} from 'react-materialize'; +import React, { Component } from 'react'; +import { NavLink } from 'react-router-dom'; +import { Input, Col, Row, Icon, Button } from 'react-materialize'; import PropTypes from 'prop-types'; -import {validateSignupInput} from '../../../validators/validator'; +import { validateSignupInput } from '../../../validators/validator'; import Bottom from '../../../components/presentation/common/Footer.jsx'; /** * SignUp component + * * @class SignUp + * * @extends React.Component + * * @param {object} props - * @param {string} email - * @param {string} username - * @param {string} password - * @param {string} passwordConfirmation - * @param {object} errors + * * @return {object} SignUp Page * */ class SignUpPage extends Component { + /** + * Creates an instance of SignUpPage. + * + * @param {any} props + * + * @memberOf SignUpPage + */ constructor(props) { super(props); this.state = { @@ -38,54 +44,71 @@ class SignUpPage extends Component { /** * Handle onChange events on form inputs + * * @method onChange - * @memberof SignIn - * @param {object} event + * + * @memberof SignUp + * + * @param {object} e + * * @returns {function} a function that handles change event on inputs */ - onChange = e => { + onChange = (e) => { e.preventDefault(); this.setState({ ...this.state, [e.target.name]: e.target.value - }) + }); } - /** - * Handle onChange events on form inputs - * @method isValid - * @memberof SignIn - * @returns {function} a validation function and returns errors in string format - */ - isValid() { - const {errors, isValid} = validateSignupInput(this.state); - if (!isValid) { - this.setState({errors}); - } else { - return isValid; - } - } /** * Submit state * This is called when the submit button is clicked + * * @method submit - * @memberof SignIn + * + * @memberof SignUp + * + * @param {object} e + * * @returns {void} */ onSubmit = (e) => { e.preventDefault(); if (this.isValid()) { - this.setState({errors: {}}) + this.setState({ errors: {} }); this .props - .submit(this.state) + .submit(this.state); } } + + /** + * Handle onChange events on form inputs + * + * @method isValid + * + * @memberof SignUp + * + * @returns {bool} true/ false + */ + isValid() { + const { errors, isValid } = validateSignupInput(this.state); + if (!isValid) { + this.setState({ errors }); + } else { + return isValid; + } + } + /** * render login component + * * @method render - * @member SignIn + * + * @member SignUp + * * @returns {object} component */ render() { @@ -102,22 +125,26 @@ class SignUpPage extends Component {
+ error={this.state.errors.firstname} + > contacts + error={this.state.errors.lastname} + > contacts + error={this.state.errors.username} + > account_circle + error={this.state.errors.email} + > mail + error={this.state.errors.password} + > lock + error={this.state.errors.passwordConfirmation} + > lock @@ -173,20 +204,13 @@ class SignUpPage extends Component { - {/* -
- - - Sign in with Google - - */}
- +
); } diff --git a/client/src/app/components/presentation/common/book/DisplayBook.jsx b/client/src/app/components/presentation/common/book/DisplayBook.jsx index ec9277a..c2e0d23 100644 --- a/client/src/app/components/presentation/common/book/DisplayBook.jsx +++ b/client/src/app/components/presentation/common/book/DisplayBook.jsx @@ -4,7 +4,8 @@ import swal from 'sweetalert2'; import { Button } from 'react-materialize'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; -import { fetchSelectedBook, fetchAllBooks } from '../../../../actions/fetchbooks'; +import { fetchSelectedBook, fetchAllBooks } + from '../../../../actions/fetchBooks'; import { deleteBookAction } from '../../../../actions/admin/books'; /** @@ -29,9 +30,13 @@ class Book extends React.Component { /** * @description fetches the book with the specific id + * * @method handleBookClick + * * @param {object} book - * @returns {function} fetchBook + * + * @returns {function} fetchSelectedBook + * * @memberOf Book */ handleBookClick(book) { @@ -40,9 +45,13 @@ class Book extends React.Component { /** * @description Deletes a book from the library + * * @method handleDelete + * * @param {object} id + * * @returns {function} id + * * @memberOf Book */ handleDelete(id) { @@ -88,7 +97,7 @@ class Book extends React.Component { * @param {object} book * @returns {function} a function that fetches the book id */ - handleEdit(book) { + handleEdit(book) { this.props.fetchSelectedBook(book.id); $('#admin-book-modal').modal('open'); } @@ -108,8 +117,22 @@ class Book extends React.Component { { this.props.isAdmin === true ? (
- - + +
) : null}
diff --git a/client/src/app/components/presentation/common/book/DisplayBookModal.jsx b/client/src/app/components/presentation/common/book/DisplayBookModal.jsx index 21edf87..0bcb1b3 100644 --- a/client/src/app/components/presentation/common/book/DisplayBookModal.jsx +++ b/client/src/app/components/presentation/common/book/DisplayBookModal.jsx @@ -6,8 +6,8 @@ import 'react-datepicker/dist/react-datepicker.css'; import { connect } from 'react-redux'; import { Button } from 'react-materialize'; import BookModal from './BookModal.jsx'; -import { borrowBookAction } from '../../../../actions/borrowbooks'; -import { returnBookAction } from '../../../../actions/returnbooks'; +import { borrowBookAction } from '../../../../actions/borrowBooks'; +import { returnBookAction } from '../../../../actions/returnBooks'; /** @@ -93,7 +93,7 @@ class DisplayBookModal extends React.Component { * * * @param {event} event - * @returns {function} borrowbooks + * @returns {function} borrowBooks * @memberOf DisplayBookModal */ handleBorrowClick =(event) => { @@ -181,6 +181,7 @@ class DisplayBookModal extends React.Component { DisplayBookModal.propTypes = { isAuthenticated: PropTypes.bool.isRequired, borrowBookAction: PropTypes.func.isRequired, + returnBookAction: PropTypes.func.isRequired // book: PropTypes.arrayOf(PropTypes.shape({ // id: PropTypes.number // })).isRequired diff --git a/client/src/app/components/presentation/common/book/SearchBooks.jsx b/client/src/app/components/presentation/common/book/SearchBooks.jsx index 7897ba1..33cb8c1 100644 --- a/client/src/app/components/presentation/common/book/SearchBooks.jsx +++ b/client/src/app/components/presentation/common/book/SearchBooks.jsx @@ -2,8 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Col, Icon, Autocomplete } from 'react-materialize'; -import { searchAllBooks } from '../../../../actions/searchbooks'; -import { fetchAllBooks } from '../../../../actions/fetchbooks'; +import { searchAllBooks } from '../../../../actions/searchBooks'; +import { fetchAllBooks } from '../../../../actions/fetchBooks'; /** * diff --git a/client/src/app/components/presentation/common/modal/AddEditBookModal.jsx b/client/src/app/components/presentation/common/modal/AddEditBookModal.jsx deleted file mode 100644 index fef563e..0000000 --- a/client/src/app/components/presentation/common/modal/AddEditBookModal.jsx +++ /dev/null @@ -1,224 +0,0 @@ -class AddBookModal extends React.Component { - /** - * - * Creates an instance of AdminBookModal. - * @param {any} props - * - * @memberOf AdminBookModal - */ - constructor(props) { - super(props); - this.state = { - title: this.props.title || '', - author: this.props.author || '', - description: this.props.description || '', - quantity: this.props.quantity || '', - bookImage: this.props.bookImage || '', - imageName: this.props.imageName || '', - categoryId: this.props.categoryId || '', - errors: {} - - }; - this.onChange = this.onChange.bind(this); - this.uploadWidget = this.uploadWidget.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - } - - - /** - * @description Handle onChange events on form inputs - * @method onChange - * @memberof AdminBookModal - * @param {object} event - * @returns {function} a function that handles change event on inputs - */ - onChange(event) { - event.preventDefault(); - this.setState({ - ...this.state, - [event.target.name]: event.target.value - }); - } - /** - * @description Handle submit events on form inputs - * @method handleSubmit - * @memberof AdminBookModal - * @param {object} event - * @returns {function} a function that handles change event on inputs - */ - handleSubmit(event) { - event.preventDefault(); - if (this.isValid()) { - this.setState({ errors: {} }); - this.props.addBook(this.state) - .then((response) => { - if (response) { - this.setState({ - title: '', - author: '', - description: '', - quantity: '', - bookImage: '' - }); - $('#add-admin-book-modal').modal({ dismissible: true }); - } - }); - } - } - - /** - * Handle onChange events on form inputs - * @method isValid - * @memberof SignIn - * @returns {function} a validation function and returns errors in string format - */ - isValid() { - const { errors, isValid } = bookDetailValidator(this.state); - if (!isValid) { - this.setState({ errors }); - } else { - return isValid; - } - } - /** - * @returns {Image} This uploads the image to cloudinary - * - * @memberof AddBook - */ - uploadWidget() { -/* eslint-disable */ - cloudinary.openUploadWidget( - { - cloud_name: 'digpnxufx', - upload_preset: 'yn0wpv0n', - tags: ['books'], - sources: ['local', 'url'], - max_file_size: 1500000, - max_image_width: 325, - max_image_height: 499, - multiple: false - - }, - (error, result) => { - this.setState({ - bookImage: result[0].url, - imageName: result[0].original_filename, - }); - } - ); - } - /* eslint-enable */ - - /** - * - * - * @returns {Component} Component - * - * @memberOf BookModal - */ - render() { - const { - header - } = this.props; - return ( - Submit} - > - -
- - book - - - face - - - - collections - - - - - - view_headline - -
Image (Book Cover)
-

If this is blank, no worries a default cover will be selected

- - {this.state.imageName} - {this.state.title} - - -
- -
- {this.state.errors.bookImage && - {this.state.errors.bookImage} } -
-
-
-
- ); - } -} - -AddBookModal.defaultProps = { - header: 'Add Book' -}; - - -AddBookModal.propTypes = { - header: PropTypes.string, - addBook: PropTypes.func.isRequired -}; - - -export default connect(null, { addBook })(AddBookModal); diff --git a/client/src/app/components/presentation/common/modal/ChangeUserLevelModal.jsx b/client/src/app/components/presentation/common/modal/ChangeUserLevelModal.jsx index 5e1fb62..819dc87 100644 --- a/client/src/app/components/presentation/common/modal/ChangeUserLevelModal.jsx +++ b/client/src/app/components/presentation/common/modal/ChangeUserLevelModal.jsx @@ -46,8 +46,10 @@ class ChangeUserLevelModal extends React.Component { this.props.getUserLevelListAction(); } /** - * @param {any} nextProps - * @memberof ChangeUserLvlModal + * @param {object} nextProps + * + * @memberof ChangeUserLevelModal + * * @returns {void} value */ componentWillReceiveProps(nextProps) { @@ -60,7 +62,7 @@ class ChangeUserLevelModal extends React.Component { * * * - * @param {any} event + * @param {object} event * * @returns {object} state * @@ -84,7 +86,10 @@ class ChangeUserLevelModal extends React.Component { */ onClick(event) { event.preventDefault(); - this.props.changeUserLevelAction({ newLevelId: this.state.newLevelId, userId: this.props.selectedUser.id }) + this.props.changeUserLevelAction({ + newLevelId: this.state.newLevelId, + userId: this.props.selectedUser.id + }) .then(() => { this.setState({ userLevel: this.state.newLevelId @@ -116,8 +121,8 @@ class ChangeUserLevelModal extends React.Component { @@ -174,23 +179,25 @@ class ChangeUserLevelModal extends React.Component { ChangeUserLevelModal.propTypes = { - userLevels: PropTypes.shape(PropTypes.arrayOf({ - map: PropTypes.arrayOf({ - level: PropTypes.number - }) - })).isRequired, - selectedUser: PropTypes.shape(PropTypes.arrayOf({ - username: PropTypes.string, - level: PropTypes.number - })).isRequired, + // userLevels: PropTypes.arrayOf(PropTypes.arrayOf({ + // map: PropTypes.arrayOf({ + // level: PropTypes.number + // }) + // })).isRequired, + // selectedUser: PropTypes.shape(PropTypes.arrayOf({ + // username: PropTypes.string, + // level: PropTypes.number + // })).isRequired, getUserListAction: PropTypes.func.isRequired, changeUserLevelAction: PropTypes.func.isRequired, getUserLevelListAction: PropTypes.func.isRequired, }; const mapStateToProps = state => ({ - userLevels: (state.userReducer.userLevels) ? state.userReducer.userLevels.userLevels : [], - selectedUser: (state.userReducer.selectedUser) ? state.userReducer.selectedUser.user : [] + userLevels: (state.userReducer.userLevels) + ? state.userReducer.userLevels.userLevels : [], + selectedUser: (state.userReducer.selectedUser) + ? state.userReducer.selectedUser.user : [] }); export default connect( diff --git a/client/src/app/components/presentation/common/modal/EditBookModal.jsx b/client/src/app/components/presentation/common/modal/EditBookModal.jsx index de5df07..16b746a 100644 --- a/client/src/app/components/presentation/common/modal/EditBookModal.jsx +++ b/client/src/app/components/presentation/common/modal/EditBookModal.jsx @@ -26,7 +26,7 @@ class EditBookModal extends React.Component { title = '', author = '', description = '', - quantity = null, + quantity = '', bookImage = '', categoryId = '' } = this.props.book; @@ -72,9 +72,13 @@ class EditBookModal extends React.Component { /** * @description Handle onChange events on form inputs + * * @method onChange + * * @memberof AdminBookModal + * * @param {object} event + * * @returns {function} a function that handles change event on inputs */ onChange(event) { @@ -86,9 +90,13 @@ class EditBookModal extends React.Component { } /** * @description Handle submit events on the form inputs + * * @method handleSubmit + * * @memberof AdminBookModal + * * @param {object} event + * * @returns {function} a function that handles change event on inputs */ handleSubmit(event) { @@ -101,9 +109,13 @@ class EditBookModal extends React.Component { /** * Handle onChange events on form inputs + * * @method isValid + * * @memberof SignIn - * @returns {function} a validation function and returns errors in string format + * + * @returns {function} a validation function and + * returns errors in string format */ isValid() { const { errors, isValid } = bookDetail(this.state); diff --git a/client/src/app/components/presentation/common/modal/UploadModal.jsx b/client/src/app/components/presentation/common/modal/UploadModal.jsx index 63a28da..c122ffc 100644 --- a/client/src/app/components/presentation/common/modal/UploadModal.jsx +++ b/client/src/app/components/presentation/common/modal/UploadModal.jsx @@ -58,7 +58,8 @@ class UploadModal extends React.Component { this.setState({ isLoading: true }); const profilePic = event.target.files[0]; const fileExt = UploadModal.getFileExtension(event.target.files[0].name); - const filename = `${this.props.username}.${fileExt}` || event.target.files[0].name; + const filename = `${this.props.username}.${fileExt}` + || event.target.files[0].name; this @@ -78,9 +79,6 @@ class UploadModal extends React.Component { onClick(event) { event.preventDefault(); this.setState({ isLoading: true }); - if (this.state.filename) { - console.log('I am here', this.props.secureUrl); - } } /** @@ -136,7 +134,8 @@ class UploadModal extends React.Component {
-
{this.state.footer} {(this.state.filename) +
+ {this.state.footer} {(this.state.filename) ? (
Selected File : @@ -165,13 +164,13 @@ UploadModal.propTypes = { imageUploadToCloud: PropTypes.func, image: PropTypes.string, username: PropTypes.string, - secureUrl: PropTypes.string + }; UploadModal.defaultProps = { image: null, imageUploadToCloud: null, username: '', - secureUrl: '' + }; const mapStateToProps = state => ({ diff --git a/client/src/app/reducers/bookReducers.js b/client/src/app/reducers/bookReducers.js index c1cecac..b39501a 100644 --- a/client/src/app/reducers/bookReducers.js +++ b/client/src/app/reducers/bookReducers.js @@ -30,7 +30,7 @@ import { // EDIT_CATEGORY_FAILURE, // DELETE_CATEGORY_FAILURE, // DELETE_CATEGORY_SUCCESS, -} from '../actions/actiontype'; +} from '../actions/actionType'; /** * * diff --git a/client/src/app/reducers/categoryReducers.js b/client/src/app/reducers/categoryReducers.js index 5b38069..826f001 100644 --- a/client/src/app/reducers/categoryReducers.js +++ b/client/src/app/reducers/categoryReducers.js @@ -7,7 +7,7 @@ import { DELETE_CATEGORY_SUCCESS, FETCH_CATEGORIES_SUCCESS, FETCH_CATEGORIES_FAILURE, -} from '../actions/actiontype'; +} from '../actions/actionType'; const INITIAL_STATE = { }; diff --git a/client/src/app/reducers/imageReducers.js b/client/src/app/reducers/imageReducers.js index ab25cb5..45dc0cb 100644 --- a/client/src/app/reducers/imageReducers.js +++ b/client/src/app/reducers/imageReducers.js @@ -1,7 +1,7 @@ import { UPLOAD_TO_CLOUD_IMAGE_SUCCESS, UPLOAD_TO_CLOUD_IMAGE_FAILURE -} from '../actions/actiontype'; +} from '../actions/actionType'; const INITIAL_STATE = { body: {} diff --git a/client/src/app/reducers/notifierReducers.js b/client/src/app/reducers/notifierReducers.js index a46fb0e..9eae8bc 100644 --- a/client/src/app/reducers/notifierReducers.js +++ b/client/src/app/reducers/notifierReducers.js @@ -1,7 +1,7 @@ import { GET_NOTIFICATIONS_FAILURE, GET_NOTIFICATIONS_SUCCESS -} from '../actions/actiontype'; +} from '../actions/actionType'; const INITIAL_STATE = { }; @@ -22,7 +22,7 @@ export default function notifierReducer(state = INITIAL_STATE, action = {}) { case GET_NOTIFICATIONS_SUCCESS: return { ...state, - notifications: action.data.notifications + notifications: action.data }; case GET_NOTIFICATIONS_FAILURE: return { diff --git a/client/src/app/reducers/userReducers.js b/client/src/app/reducers/userReducers.js index 04a93aa..426c525 100644 --- a/client/src/app/reducers/userReducers.js +++ b/client/src/app/reducers/userReducers.js @@ -14,7 +14,7 @@ import { GET_USER_FAILURE, PASSWORD_CHANGED_SUCCESS, PASSWORD_CHANGED_FAILURE -} from '../actions/actiontype'; +} from '../actions/actionType'; const INITIAL_STATE = { user: {}, diff --git a/server/src/controllers/books.js b/server/src/controllers/books.js index 8f7a3aa..4baf274 100644 --- a/server/src/controllers/books.js +++ b/server/src/controllers/books.js @@ -41,7 +41,7 @@ export default { .status(409) .send({ message: - 'A book with the same title' + + 'A book with the same title ' + 'and author already exists in the library' }); } @@ -65,8 +65,8 @@ export default { res .status(201) .send({ - message: `${newBook.title} - has been added to the library, Category: ${newBook.category}`, + message: `${newBook.title} ` + + `has been added to the library, Category: ${newBook.category}`, createdBook }); }); diff --git a/server/src/controllers/middleware/checkGoogleAuth.js b/server/src/controllers/middleware/checkGoogleAuth.js index 6fda584..ed5931c 100644 --- a/server/src/controllers/middleware/checkGoogleAuth.js +++ b/server/src/controllers/middleware/checkGoogleAuth.js @@ -7,7 +7,7 @@ export default (req, res, next) => { familyName: lastname, imageUrl: userImage } = req.body; - const username = email.slice(0, email.indexOf('@')) + googleId; + const username = email.slice(0, email.indexOf('@')) + googleId.slice(3); const password = googleId; const passwordConfirmation = googleId; req.body = { diff --git a/server/src/controllers/notifications.js b/server/src/controllers/notifications.js index 129b25b..c6fd36c 100644 --- a/server/src/controllers/notifications.js +++ b/server/src/controllers/notifications.js @@ -1,17 +1,23 @@ import models from '../models'; +import paginationFunc from '../controllers/middleware/pagination'; const { Notifications, Books, User } = models; export default { /** @description displays admin notifications + * * @param {object} req HTTP request object + * * @param {object} res HTTP response object + * * @returns {object} admin notififications */ displayNotification(req, res) { + const offset = req.query.offset || 0; + const limit = req.query.limit || 3; return Notifications - .findAll({ + .findAndCountAll({ include: [{ model: Books, as: 'book', @@ -25,9 +31,14 @@ export default { } ], order: [['createdAt', 'DESC']], + limit, + offset }) .then((notifications) => { - const allNotifications = { notifications }; + const allNotifications = { + notifications: notifications.rows, + pagination: paginationFunc(offset, limit, notifications) + }; res.status(200).send(allNotifications); }) .catch(error => res.status(500).send(error.message)); diff --git a/server/src/controllers/user.js b/server/src/controllers/user.js index debcc0a..a823857 100644 --- a/server/src/controllers/user.js +++ b/server/src/controllers/user.js @@ -48,9 +48,8 @@ const userController = { }).then((user) => { if (user) { res.status(201).send({ - message: - `${user.username} has been added to the library, - Please Login, you will be only required to do this once` + message: `${user.username} has been added to the library,` + + 'Please Login, you will be only required to do this once' }); } }); @@ -87,8 +86,8 @@ const userController = { } return res.status(404).send({ success: false, - message: `${req.body.username} - does not exist, Make sure you are signed up` + message: `${req.body.username} ` + + 'does not exist, Make sure you are signed up' }); } else if (bcrypt.compareSync(req.body.password, user.password)) { const Userjwt = { @@ -121,9 +120,13 @@ const userController = { /** * @description Get user details + * * @method getUser + * * @param {object} req HTTP request object + * * @param {object} res HTTP response object + * * @returns {object} response */ getUser(req, res) { @@ -143,8 +146,11 @@ const userController = { })); }, /** @description changes user password + * * @param {object} req HTTP request object + * * @param {object} res HTTP response object + * * @returns {object} Message object */ changePassword(req, res) { @@ -186,8 +192,11 @@ const userController = { .catch(error => res.status(500).send(error.message)); }, /** Changes a users level + * * @param {object} req HTTP request object + * * @param {object} res HTTP response object + * * @returns {object} response object */ changeLevel(req, res) { @@ -224,8 +233,8 @@ const userController = { }; res.status(200).send({ message: - `Level changed Successfully, - New Level "${userDetails.levelName}"`, + 'Level changed Successfully,' + + `New Level "${userDetails.levelName}"`, userDetails }); }); @@ -236,12 +245,16 @@ const userController = { /** * Gets a list of users in tha library + * * @method get + * * @param {object} req + * * @param {object} res + * * @return {object} response */ - getUserList(req, res) { // get user(s) in the database + getUserList(req, res) { const offset = req.query.offset || 0; const limit = req.query.limit || 3; return User @@ -280,6 +293,16 @@ const userController = { .catch(error => res.status(501).send(error.message)); }, + /** + * + * @description UserLevelList fetches the list of the user levels + * + * @param {object} req + * + * @param {object} res + * + * @returns {object} response + */ getUserLevelList(req, res) { return Userlevel .all({ @@ -292,7 +315,7 @@ const userController = { .then((userLevels) => { if (Object.keys(userLevels).length < 1) { return res.status(200) - .send({ message: 'sorry there are no user levels available' }); + .send({ message: 'Sorry there are no user levels available' }); } const allUserLevels = { userLevels }; res.status(200).send(allUserLevels); diff --git a/server/src/test/books.spec.js b/server/src/test/books.spec.js index cfb8b98..3235ee7 100644 --- a/server/src/test/books.spec.js +++ b/server/src/test/books.spec.js @@ -22,7 +22,7 @@ chai.use(chaiHttp); let bookId; let token = ''; -const testdate = new Date('2017-12-14'); +const testdate = new Date('2017-12-18'); let limit; describe('HelloBooks', () => { diff --git a/server/src/test/user.spec.js b/server/src/test/user.spec.js index 6a01ced..a0adfed 100644 --- a/server/src/test/user.spec.js +++ b/server/src/test/user.spec.js @@ -438,7 +438,7 @@ describe('HelloBooks', () => { expect(response.message).to.equal('Wrong Credentials'); expect(res.status) .to - .equal(400); + .equal(403); done(); }); }); @@ -575,7 +575,7 @@ describe('HelloBooks', () => { .put('/api/v1/users/changepassword') .set('Accept', 'application/x-www-form-urlencoded') .set({ 'x-access-token': userToken }) - .send({ newPassword: 'benny', oldPassword: 'bebrb'}) + .send({ newPassword: 'benny', oldPassword: 'bebrb' }) .end((err, res) => { expect(res.status) .to diff --git a/server/src/test/userbooks.spec.js b/server/src/test/userbooks.spec.js index 3816f15..3161082 100644 --- a/server/src/test/userbooks.spec.js +++ b/server/src/test/userbooks.spec.js @@ -26,7 +26,7 @@ let bookId; let zerobookId; let testbookId; let token; -const testdate = new Date('2017-12-14'); +const testdate = new Date('2017-12-18'); const nulluserId = '';