├── . eslintignore ├── .babelrc ├── client ├── __tests__ │ ├── __mocks__ │ │ ├── styleMocks.js │ │ ├── fileMock.js │ │ └── mockConfig.js │ ├── components │ │ ├── utils │ │ │ ├── setAuthorizationToken.spec.js │ │ │ └── Pagination.spec.jsx │ │ ├── presentation │ │ │ ├── common │ │ │ │ ├── Footer.spec.jsx │ │ │ │ ├── modal │ │ │ │ │ ├── BookDetailForm.spec.jsx │ │ │ │ │ └── TextInput.spec.jsx │ │ │ │ └── book │ │ │ │ │ └── DisplayBook.spec.jsx │ │ │ ├── messages │ │ │ │ ├── MessageforNoBooks.spec.jsx │ │ │ │ ├── MessageforNoBooksHistory.spec.jsx │ │ │ │ └── MessageforNoCatBooks.spec.jsx │ │ │ └── authentication │ │ │ │ ├── SignIn.spec.jsx │ │ │ │ └── SignUp.spec.jsx │ │ └── container │ │ │ ├── booklists │ │ │ ├── Loader.spec.jsx │ │ │ ├── SearchBooks.spec.jsx │ │ │ ├── DisplayRecentBooks.spec.jsx │ │ │ ├── DisplayAllBooks.spec.jsx │ │ │ └── DisplayBorrowedBooks.spec.jsx │ │ │ ├── categories │ │ │ ├── CategoriesDropdownList.spec.jsx │ │ │ ├── CategoriesSideBar.spec.jsx │ │ │ ├── CategoriesOptionList.spec.jsx │ │ │ └── CategoriesWrapper.spec.jsx │ │ │ ├── common │ │ │ └── Dashboard.spec.jsx │ │ │ └── modal │ │ │ └── AddBookModal.spec.jsx │ ├── shim.js │ ├── __config__ │ │ └── setup.js │ ├── actions │ │ ├── users │ │ │ ├── uploadImage.spec.js │ │ │ ├── loanHistory.spec.js │ │ │ ├── searchBooks.spec.js │ │ │ ├── returnBooks.spec.js │ │ │ ├── borrowBooks.spec.js │ │ │ ├── changePassword.spec.js │ │ │ └── authenticate.spec.js │ │ └── admin │ │ │ ├── getUserList.spec.js │ │ │ ├── getSelectedUser.spec.js │ │ │ ├── getUserLevelList.spec.js │ │ │ ├── getAdminNotifications.spec.js │ │ │ └── changeLevel.spec.js │ └── reducers │ │ └── notifierReducer.spec.js └── src │ ├── app │ ├── img │ │ ├── bg.jpg │ │ └── 404.jpg │ ├── store │ │ ├── configStore.js │ │ ├── configStore.prod.js │ │ └── configStore.dev.js │ ├── components │ │ ├── container │ │ │ ├── header │ │ │ │ └── Header.jsx │ │ │ ├── LandingPage.jsx │ │ │ ├── booklist │ │ │ │ ├── Loader.jsx │ │ │ │ └── DisplayRecentBooks.jsx │ │ │ ├── categories │ │ │ │ ├── CategoriesAdminTab.jsx │ │ │ │ ├── CategoriesDropdownList.jsx │ │ │ │ ├── CategoriesSideBarList.jsx │ │ │ │ └── CategoriesOptionsList.jsx │ │ │ ├── common │ │ │ │ ├── Dashboard.jsx │ │ │ │ └── Pagination.jsx │ │ │ ├── authentication │ │ │ │ └── Logout.jsx │ │ │ ├── notification │ │ │ │ ├── NotificationTable.jsx │ │ │ │ └── NotificationTab.jsx │ │ │ ├── userlists │ │ │ │ └── container │ │ │ │ │ └── UserListTab.jsx │ │ │ └── loanhistory │ │ │ │ └── LoanHistory.jsx │ │ ├── presentation │ │ │ ├── messages │ │ │ │ ├── WelcomeMessage.jsx │ │ │ │ └── dashboardMessages │ │ │ │ │ ├── MessageforNoOverdueBooks.jsx │ │ │ │ │ ├── MessageforNoBooks.jsx │ │ │ │ │ ├── NoNotifications.jsx │ │ │ │ │ ├── MessageforNoCatBooks.jsx │ │ │ │ │ └── MessageforNoBooksHistory.jsx │ │ │ ├── common │ │ │ │ ├── Preloader │ │ │ │ │ └── ShowProgressBar.jsx │ │ │ │ ├── Footer.jsx │ │ │ │ ├── SideNav │ │ │ │ │ ├── UserView.jsx │ │ │ │ │ └── index.jsx │ │ │ │ ├── header │ │ │ │ │ ├── NavigationBar.jsx │ │ │ │ │ └── Header.jsx │ │ │ │ ├── book │ │ │ │ │ ├── BaseBookModal.jsx │ │ │ │ │ └── SearchBooks.jsx │ │ │ │ └── modal │ │ │ │ │ └── form │ │ │ │ │ └── TextInput.jsx │ │ │ ├── LandingPage.jsx │ │ │ ├── UserDashboard.jsx │ │ │ ├── admin │ │ │ │ └── AdminDashboard.jsx │ │ │ └── loanhistory │ │ │ │ └── LoanHistoryTable.jsx │ │ ├── Root.jsx │ │ └── hoc │ │ │ ├── UserRoutes.jsx │ │ │ ├── GuestRoutes.jsx │ │ │ └── AdminRoutes.jsx │ ├── utils │ │ ├── setAuthorizationToken.js │ │ └── localSave.js │ ├── reducers │ │ ├── rootReducers.js │ │ ├── notifierReducers.js │ │ ├── imageReducers.js │ │ ├── categoryReducers.js │ │ └── userReducers.js │ ├── actions │ │ ├── borrowBooks.js │ │ ├── index.js │ │ ├── changePassword.js │ │ ├── admin │ │ │ ├── getSelectedUser.js │ │ │ ├── getUserLevelList.js │ │ │ ├── addCategory.js │ │ │ ├── changeUserLevel.js │ │ │ ├── deleteCategory.js │ │ │ ├── getAdminNotifications.js │ │ │ ├── getUserList.js │ │ │ ├── editCategory.js │ │ │ └── books.js │ │ ├── searchBooks.js │ │ ├── returnBooks.js │ │ ├── loanHistory.js │ │ ├── uploadImage.js │ │ ├── notifications.js │ │ └── fetchCategories.js │ ├── index.jsx │ └── MainRoot.jsx │ └── index.html ├── Procfile ├── templates ├── img │ ├── bg.jpg │ ├── book1.png │ ├── book2.jpg │ ├── Schema.png │ ├── profile.jpg │ └── evolution-2-e1427283314331.jpg ├── js │ └── data-toggle.js └── stylesheets │ ├── bootstrap-imageupload.min.css │ └── styles.css ├── .hound.yml ├── apidocs ├── fonts │ ├── slate.eot │ ├── slate.ttf │ ├── slate.woff │ ├── slate.woff2 │ └── slate.svg └── images │ ├── logo.png │ └── navbar.png ├── .editorconfig ├── screenshots └── hellobooks-screenshot.png ├── server └── src │ ├── test │ ├── index.spec.js │ ├── notifications.spec.js │ ├── helpers │ │ └── usrToken.js │ └── model.spec.js │ ├── controllers │ ├── index.js │ ├── helpers │ │ └── pagination.js │ ├── middleware │ │ ├── checkAdmin.js │ │ ├── validators │ │ │ ├── fieldValidations.js │ │ │ ├── nullValidation.js │ │ │ └── validators.js │ │ └── checkGoogleAuth.js │ └── notifications.js │ ├── mailer │ └── mailer.js │ ├── cron │ ├── index.js │ └── sendSurcharge.js │ ├── models │ ├── categories.js │ ├── notifications.js │ ├── userLevel.js │ ├── index.js │ ├── userBooks.js │ └── books.js │ ├── config │ └── config.js │ ├── migrations │ ├── 20171125192622-create-categories.js │ ├── 20171125194210-create-notifications.js │ ├── 20171125184821-create-userlevel.js │ ├── 20170818172848-create-user-books.js │ ├── 20170818172635-create-books.js │ └── 20170818172333-create-user.js │ ├── seeders │ ├── seedLevels.js │ ├── seedUsers.js │ └── seedCategories.js │ ├── app.js │ └── bin │ └── www.js ├── .coverage.yml ├── .sequelizerc ├── .gitignore ├── .env.sample ├── nightwatch.config.js ├── .codeclimate.yml ├── e2e-tests ├── landing.spec.js ├── selectors.js ├── dashboard.spec.js ├── login.spec.js ├── signup.spec.js └── library.spec.js ├── LICENSE.md ├── nightwatch.json ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .travis.yml ├── .eslintrc └── .sass-lint.yml /. eslintignore: -------------------------------------------------------------------------------- 1 | /server/test 2 | /dist 3 | server/dist -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { "presets": ["es2015", "react", "stage-2"] 2 | } 3 | -------------------------------------------------------------------------------- /client/__tests__/__mocks__/styleMocks.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: npm run start 2 | clock: node server/dist/cron/index.js 3 | -------------------------------------------------------------------------------- /client/__tests__/__mocks__/fileMock.js: -------------------------------------------------------------------------------- 1 | module.exports = 'image-file'; 2 | -------------------------------------------------------------------------------- /templates/img/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/templates/img/bg.jpg -------------------------------------------------------------------------------- /.hound.yml: -------------------------------------------------------------------------------- 1 | eslint: 2 | enabled: true 3 | config_file: .eslintrc 4 | ignore_file: .eslintignore -------------------------------------------------------------------------------- /apidocs/fonts/slate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/apidocs/fonts/slate.eot -------------------------------------------------------------------------------- /apidocs/fonts/slate.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/apidocs/fonts/slate.ttf -------------------------------------------------------------------------------- /apidocs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/apidocs/images/logo.png -------------------------------------------------------------------------------- /templates/img/book1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/templates/img/book1.png -------------------------------------------------------------------------------- /templates/img/book2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/templates/img/book2.jpg -------------------------------------------------------------------------------- /apidocs/fonts/slate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/apidocs/fonts/slate.woff -------------------------------------------------------------------------------- /apidocs/fonts/slate.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/apidocs/fonts/slate.woff2 -------------------------------------------------------------------------------- /apidocs/images/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/apidocs/images/navbar.png -------------------------------------------------------------------------------- /client/src/app/img/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/client/src/app/img/bg.jpg -------------------------------------------------------------------------------- /templates/img/Schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/templates/img/Schema.png -------------------------------------------------------------------------------- /templates/img/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/templates/img/profile.jpg -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [{package.json,.travis.yml}] 4 | indent_style = space 5 | indent_size = 2 6 | -------------------------------------------------------------------------------- /client/src/app/img/404.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/client/src/app/img/404.jpg -------------------------------------------------------------------------------- /screenshots/hellobooks-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/screenshots/hellobooks-screenshot.png -------------------------------------------------------------------------------- /templates/img/evolution-2-e1427283314331.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfluleck/HelloBooks/HEAD/templates/img/evolution-2-e1427283314331.jpg -------------------------------------------------------------------------------- /server/src/test/index.spec.js: -------------------------------------------------------------------------------- 1 | require('./books.spec'); 2 | require('./userBooks.spec'); 3 | require('./model.spec'); 4 | require('./categories.spec'); 5 | require('./authenticate.spec'); 6 | require('./notifications.spec'); 7 | require('./user.spec'); 8 | -------------------------------------------------------------------------------- /client/src/app/store/configStore.js: -------------------------------------------------------------------------------- 1 | import configDev from './configStore.dev'; 2 | import configProd from './configStore.prod'; 3 | 4 | if (process.env.NODE_ENV === 'production') { 5 | module.exports = configProd; 6 | } else { 7 | module.exports = configDev; 8 | } 9 | -------------------------------------------------------------------------------- /.coverage.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | duplication: 3 | enabled: false 4 | config: 5 | languages: 6 | javascript: 7 | mass_threshold: 20 8 | ratings: 9 | paths: 10 | - "**.js" 11 | exclude_paths: 12 | - "dist/" 13 | - "node_modules/" 14 | - "api-docs/" -------------------------------------------------------------------------------- /.sequelizerc: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | "config": path.resolve('./server/dist/config', 'config.js'), 5 | "models-path": path.resolve('./server/dist/models'), 6 | "seeders-path": path.resolve('./server/dist/seeders'), 7 | "migrations-path": path.resolve('./server/dist/migrations') 8 | }; 9 | -------------------------------------------------------------------------------- /server/src/controllers/index.js: -------------------------------------------------------------------------------- 1 | import User from './user'; 2 | import Books from './books'; 3 | import UserBooks from './userBooks'; 4 | import Category from './category'; 5 | import Notifications from './notifications'; 6 | 7 | export default { 8 | User, 9 | Books, 10 | UserBooks, 11 | Category, 12 | Notifications 13 | }; 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */node_modules/* 2 | node_modules/* 3 | node_modules/ 4 | server/config/* 5 | package-lock.json 6 | */coverage/* 7 | */nyc_output/* 8 | coverage 9 | */.nyc_output/* 10 | .coveralls.yml 11 | .env 12 | .nyc_output 13 | npm-debug.log 14 | coverage/ 15 | client/dist 16 | server/dist 17 | .vscode 18 | .DS_Store 19 | reports 20 | logs 21 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | JWT_SECRET=sampleJWT 2 | DBUSERNAME=sampledb 3 | DBPASSWORD=password 4 | DB=sampledb 5 | DBADDRESS=SampleIpaddress 6 | DBDIALECT=Sampledialect 7 | TESTDB=sampletestdb 8 | ISBNRANDOM_MIN_ID =test_random_id 9 | ISBNRANDOM_MAX_ID=test_random_id 10 | DATABASE_URL=databaseurl 11 | NODE_ENV=environment 12 | DEFAULT_BOOK_COVER=bookimage 13 | PROFILE_PIC=userimage 14 | -------------------------------------------------------------------------------- /nightwatch.config.js: -------------------------------------------------------------------------------- 1 | require('babel-core/register'); 2 | const fs = require('fs'); 3 | 4 | module.exports = ((settings) => { 5 | const seleniumServerFileName = 6 | fs.readdirSync('node_modules/selenium-standalone/.selenium/selenium-server/'); 7 | settings.selenium.server_path += seleniumServerFileName; 8 | return settings; 9 | })(require('./nightwatch.json')); 10 | -------------------------------------------------------------------------------- /client/__tests__/components/utils/setAuthorizationToken.spec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import setAuthorizationToken from 3 | '../../../src/../src/app/utils/setAuthorizationToken'; 4 | 5 | describe('# Set Authorization Token', () => { 6 | it('should set axios header when token is passed', () => { 7 | setAuthorizationToken('token-is-here'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /client/__tests__/__mocks__/mockConfig.js: -------------------------------------------------------------------------------- 1 | 2 | import axios from 'axios'; 3 | import configureMockStore from 'redux-mock-store'; 4 | import thunk from 'redux-thunk'; 5 | import MockAdapter from 'axios-mock-adapter'; 6 | 7 | 8 | export const middlewares = [thunk]; 9 | export const mockStore = configureMockStore(middlewares); 10 | 11 | export const mock = new MockAdapter(axios); 12 | 13 | -------------------------------------------------------------------------------- /client/src/app/components/container/header/Header.jsx: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux'; 2 | import Header from '../../presentation/common/header/Header'; 3 | 4 | 5 | const mapStateToProps = state => ({ 6 | 7 | isAuthenticated: !!state.userReducer.isAuthenticated, 8 | tokenExists: !!localStorage.getItem('token') 9 | 10 | }); 11 | 12 | export default connect(mapStateToProps)(Header); 13 | -------------------------------------------------------------------------------- /templates/js/data-toggle.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $('[data-toggle="tooltip"]').tooltip() 3 | }) 4 | 5 | // Initialize popover component 6 | $(function() { 7 | $('[data-toggle="popover"]').popover() 8 | }) 9 | 10 | $('.img-upload').imgupload({ 11 | 12 | allowedFormats: ["jpg", "jpeg", "png", "gif"], 13 | 14 | previewWidth: 250, 15 | 16 | previewHeight: 250, 17 | 18 | maxFileSizeKb: 2048 19 | 20 | }); -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | duplication: 3 | enabled: true 4 | config: 5 | languages: 6 | javascript: 7 | mass_threshold: 500 8 | checks: 9 | method-lines: 10 | config: 11 | threshold: 60 12 | complex-logic: 13 | config: 14 | threshold: 8 15 | method-complexity: 16 | config: 17 | threshold: 8 18 | return-statements: 19 | config: 20 | threshold: 12 21 | -------------------------------------------------------------------------------- /client/src/app/components/presentation/messages/WelcomeMessage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { NavLink } from 'react-router-dom'; 3 | 4 | /** 5 | * @description Component for Welcome Mesage 6 | * 7 | * @class WelcomeMessage 8 | */ 9 | const WelcomeMessage = () => ( 10 |