├── .nvmrc ├── .gitattributes ├── .travis.yml ├── test ├── mocks │ ├── store.js │ ├── fakeSession.js │ ├── fakeStorage.js │ ├── reducers.js │ └── i18n.js ├── setup.js └── helpers │ └── store.js ├── .stylelintrc ├── app ├── stylesheets │ ├── base.css │ ├── layout.css │ ├── application.css │ └── vars.css ├── locales │ └── en │ │ ├── modal.json │ │ ├── common.json │ │ ├── profile.json │ │ ├── header.json │ │ ├── about.json │ │ ├── session.json │ │ ├── todo.json │ │ ├── home.json │ │ └── article.json ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── services │ ├── history.js │ ├── sessionStorage.js │ ├── currentUser.js │ ├── i18n.js │ └── api.js ├── components │ ├── application │ │ ├── styles.css │ │ ├── tests │ │ │ ├── __snapshots__ │ │ │ │ └── index.snapshot.test.jsx.snap │ │ │ └── index.snapshot.test.jsx │ │ └── index.jsx │ ├── navigation │ │ ├── styles.css │ │ ├── navItemLink.jsx │ │ ├── tests │ │ │ ├── index.snapshot.test.jsx │ │ │ ├── index.test.jsx │ │ │ └── __snapshots__ │ │ │ │ └── index.snapshot.test.jsx.snap │ │ └── index.jsx │ ├── footer │ │ ├── tests │ │ │ ├── __snapshots__ │ │ │ │ └── index.snapshot.test.jsx.snap │ │ │ └── index.snapshot.test.jsx │ │ ├── styles.css │ │ └── index.jsx │ ├── todo │ │ ├── styles.css │ │ ├── tests │ │ │ ├── __snapshots__ │ │ │ │ ├── item.snapshot.test.jsx.snap │ │ │ │ ├── list.snapshot.test.jsx.snap │ │ │ │ ├── index.snapshot.test.jsx.snap │ │ │ │ └── modal.snapshot.test.jsx.snap │ │ │ ├── index.snapshot.test.jsx │ │ │ ├── item.snapshot.test.jsx │ │ │ ├── list.snapshot.test.jsx │ │ │ ├── modal.snapshot.test.jsx │ │ │ └── item.test.jsx │ │ ├── list.jsx │ │ ├── item.jsx │ │ ├── index.jsx │ │ └── modal.jsx │ ├── home │ │ ├── tests │ │ │ ├── index.snapshot.test.jsx │ │ │ └── __snapshots__ │ │ │ │ └── index.snapshot.test.jsx.snap │ │ └── index.jsx │ ├── main │ │ ├── index.jsx │ │ └── tests │ │ │ └── index.test.jsx │ ├── profile │ │ ├── tests │ │ │ ├── __snapshots__ │ │ │ │ └── index.snapshot.test.jsx.snap │ │ │ └── index.snapshot.test.jsx │ │ └── index.jsx │ ├── about │ │ ├── tests │ │ │ ├── index.snapshot.test.jsx │ │ │ └── __snapshots__ │ │ │ │ └── index.snapshot.test.jsx.snap │ │ └── index.jsx │ ├── article │ │ ├── index.jsx │ │ └── tests │ │ │ ├── index.snapshot.test.jsx │ │ │ └── __snapshots__ │ │ │ └── index.snapshot.test.jsx.snap │ ├── modal │ │ ├── tests │ │ │ ├── index.snapshot.test.jsx │ │ │ └── __snapshots__ │ │ │ │ └── index.snapshot.test.jsx.snap │ │ └── index.jsx │ ├── form │ │ ├── tests │ │ │ └── index.test.jsx │ │ └── index.jsx │ ├── applicationRoutes │ │ └── index.jsx │ ├── signin │ │ ├── tests │ │ │ ├── modal.snapshot.test.jsx │ │ │ └── __snapshots__ │ │ │ │ └── modal.snapshot.test.jsx.snap │ │ └── modal.jsx │ └── signup │ │ ├── tests │ │ ├── modal.snapshot.test.jsx │ │ └── __snapshots__ │ │ │ └── modal.snapshot.test.jsx.snap │ │ └── modal.jsx ├── containers │ ├── profile │ │ └── index.jsx │ ├── main │ │ ├── index.jsx │ │ └── tests │ │ │ └── index.test.js │ ├── todoModal │ │ ├── index.jsx │ │ └── tests │ │ │ └── index.test.js │ ├── signinModal │ │ ├── index.jsx │ │ └── tests │ │ │ └── index.test.js │ ├── signupModal │ │ ├── index.jsx │ │ └── tests │ │ │ └── index.test.js │ ├── navigation │ │ ├── index.jsx │ │ └── tests │ │ │ └── index.test.jsx │ ├── todo │ │ ├── tests │ │ │ ├── index.test.js │ │ │ └── list.test.js │ │ ├── index.jsx │ │ └── list.jsx │ └── modal │ │ ├── index.jsx │ │ └── tests │ │ └── index.test.js ├── sources │ ├── users.js │ ├── session.js │ └── todos.js ├── actions │ ├── modal.js │ ├── todos.js │ └── session.js ├── config │ └── env │ │ ├── test.js │ │ ├── production.js │ │ └── development.js ├── index.html ├── helpers │ └── routes.js ├── reducers │ ├── index.js │ ├── modal │ │ ├── index.js │ │ └── index.test.js │ ├── session │ │ ├── index.js │ │ └── index.test.js │ └── todos │ │ ├── index.js │ │ └── index.test.js ├── stores │ └── application.js ├── lib │ └── storage.js ├── hoc │ └── withAuth │ │ ├── index.jsx │ │ └── tests │ │ └── index.test.jsx └── index.jsx ├── .env.example ├── .gitignore ├── bin └── setup ├── .babelrc ├── postcss.config.js ├── json-server ├── db │ └── db.json.example └── index.js ├── .eslintrc ├── .editorconfig ├── CONTRIBUTING.md ├── LICENSE ├── server.js ├── webpack.config.js ├── README.md ├── package.json └── CHANGELOG.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | CHANGELOG merge=union 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "9" 4 | -------------------------------------------------------------------------------- /test/mocks/store.js: -------------------------------------------------------------------------------- 1 | jest.mock('stores/application'); 2 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-fs" 3 | } 4 | -------------------------------------------------------------------------------- /app/stylesheets/base.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-size: 16px; 3 | } 4 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | PORT=8000 3 | NPM_CONFIG_PRODUCTION=false 4 | -------------------------------------------------------------------------------- /app/stylesheets/layout.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | .app { 4 | height: 100%; 5 | margin: 0; 6 | padding: 0; 7 | } 8 | -------------------------------------------------------------------------------- /app/locales/en/modal.json: -------------------------------------------------------------------------------- 1 | { 2 | "signin": "Sign In", 3 | "signup": "Sign Up", 4 | "newTask": "New Task" 5 | } 6 | -------------------------------------------------------------------------------- /app/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fs/react-base/HEAD/app/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /app/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fs/react-base/HEAD/app/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | node_modules 4 | coverage 5 | access_logs.db 6 | npm-debug.log 7 | dist 8 | json-server/db/db.json 9 | -------------------------------------------------------------------------------- /app/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fs/react-base/HEAD/app/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /app/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fs/react-base/HEAD/app/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /app/services/history.js: -------------------------------------------------------------------------------- 1 | import createBrowserHistory from 'history/createBrowserHistory'; 2 | 3 | export default createBrowserHistory(); 4 | -------------------------------------------------------------------------------- /app/components/application/styles.css: -------------------------------------------------------------------------------- 1 | .layout { 2 | height: 100%; 3 | } 4 | 5 | .wrapper { 6 | min-height: 100%; 7 | padding-bottom: 100px; 8 | } 9 | -------------------------------------------------------------------------------- /app/locales/en/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "React-base", 3 | "errorNetwork": "Network error has occured. Please check internet connection" 4 | } 5 | -------------------------------------------------------------------------------- /app/containers/profile/index.jsx: -------------------------------------------------------------------------------- 1 | import Profile from 'components/profile'; 2 | import withAuth from 'hoc/withAuth'; 3 | 4 | export default withAuth(Profile); 5 | -------------------------------------------------------------------------------- /app/locales/en/profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "text": "This page created to demonstrate ability to protect route. This page available only for authenticated users." 3 | } -------------------------------------------------------------------------------- /app/locales/en/header.json: -------------------------------------------------------------------------------- 1 | { 2 | "home": "Home", 3 | "about": "About", 4 | "signIn": "Sign in", 5 | "signUp": "Sign up", 6 | "signOut": "Sign out" 7 | } 8 | -------------------------------------------------------------------------------- /app/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | @import "bootstrap"; 2 | @import "react-s-alert/dist/s-alert-default"; 3 | @import "vars"; 4 | @import "base"; 5 | @import "layout"; 6 | -------------------------------------------------------------------------------- /app/stylesheets/vars.css: -------------------------------------------------------------------------------- 1 | $screen-xs: 480px; 2 | $screen-sm: 768px; 3 | $screen-md: 992px; 4 | $screen-lg: 1200px; 5 | $blue: #337ab7; 6 | $white: #fff; 7 | $grey-e7: #e7e7e7; 8 | -------------------------------------------------------------------------------- /app/components/navigation/styles.css: -------------------------------------------------------------------------------- 1 | @import "../../stylesheets/vars"; 2 | 3 | .panel { 4 | border: none; 5 | border-bottom: 1px solid $grey-e7; 6 | border-radius: 0; 7 | } 8 | -------------------------------------------------------------------------------- /app/locales/en/about.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "About", 3 | "text": "Kick-start your new web application based on React and Redux technologies.", 4 | "details": "show details..." 5 | } 6 | -------------------------------------------------------------------------------- /app/locales/en/session.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Name", 3 | "email": "Email", 4 | "password": "Password", 5 | "passwordConfirmation": "Password Confirmation", 6 | "submit": "Submit" 7 | } 8 | -------------------------------------------------------------------------------- /app/locales/en/todo.json: -------------------------------------------------------------------------------- 1 | { 2 | "taskName": "Task name", 3 | "save": "Save", 4 | "list": "Todo List", 5 | "newTask": "New Task", 6 | "incomplete": "Incomplete", 7 | "complete": "Complete" 8 | } 9 | -------------------------------------------------------------------------------- /app/locales/en/home.json: -------------------------------------------------------------------------------- 1 | { 2 | "text": "Kick-start your new web application based on React and Redux technologies.
It also includes Webpack, React hot loader, PostCSS, JSON-server tools for even more rapid development." 3 | } 4 | -------------------------------------------------------------------------------- /app/containers/main/index.jsx: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux'; 2 | import Main from 'components/main'; 3 | 4 | const mapStateToProps = state => ({ 5 | loggedIn: state.session.loggedIn, 6 | }); 7 | 8 | export default connect(mapStateToProps)(Main); 9 | -------------------------------------------------------------------------------- /app/sources/users.js: -------------------------------------------------------------------------------- 1 | import api from 'services/api'; 2 | 3 | export default { 4 | urlRoot: '/users', 5 | async create(user) { 6 | return ( 7 | await api.post(this.urlRoot, user, { withoutAuth: true }) 8 | ).data; 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /app/actions/modal.js: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions'; 2 | 3 | export const OPEN_MODAL = 'OPEN_MODAL'; 4 | export const CLOSE_MODAL = 'CLOSE_MODAL'; 5 | 6 | export const openModal = createAction(OPEN_MODAL); 7 | export const closeModal = createAction(CLOSE_MODAL); 8 | -------------------------------------------------------------------------------- /app/containers/todoModal/index.jsx: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux'; 2 | import { createTodo } from 'actions/todos'; 3 | import TodoModal from 'components/todo/modal'; 4 | 5 | const mapDispatchToProps = { 6 | createTodo, 7 | }; 8 | 9 | export default connect(null, mapDispatchToProps)(TodoModal); 10 | -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | import 'jest-enzyme'; 2 | 3 | import Enzyme from 'enzyme'; 4 | import Adapter from 'enzyme-adapter-react-16'; 5 | 6 | import './mocks/i18n'; 7 | import './mocks/store'; 8 | import './mocks/reducers'; 9 | 10 | Enzyme.configure({ adapter: new Adapter() }); 11 | 12 | global.context = describe; 13 | -------------------------------------------------------------------------------- /app/components/footer/tests/__snapshots__/index.snapshot.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Footer renders correctly 1`] = ` 4 | 13 | `; 14 | -------------------------------------------------------------------------------- /app/components/footer/styles.css: -------------------------------------------------------------------------------- 1 | @import "../../stylesheets/vars"; 2 | 3 | .footer { 4 | position: relative; 5 | height: 60px; 6 | margin-top: -60px; 7 | clear: both; 8 | border-top: 1px solid $grey-e7; 9 | line-height: 60px; 10 | 11 | p { 12 | margin: 0; 13 | text-align: center; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install all dependencies 4 | yarn install 5 | 6 | # Setup configurable environment variables 7 | if [ ! -f .env ]; then 8 | cp .env.example .env 9 | fi 10 | 11 | # Setup db.json 12 | if [ ! -f json-server/db/db.json ]; then 13 | cp json-server/db/db.json.example json-server/db/db.json 14 | fi 15 | -------------------------------------------------------------------------------- /app/components/footer/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import i18n from 'services/i18n'; 3 | import styles from './styles.css'; 4 | 5 | const Footer = () => ( 6 | 9 | ); 10 | 11 | export default Footer; 12 | -------------------------------------------------------------------------------- /app/components/todo/styles.css: -------------------------------------------------------------------------------- 1 | .spacingTop { 2 | margin-top: 20px; 3 | } 4 | 5 | .iconTrash { 6 | margin-top: 2px; 7 | float: right; 8 | z-index: 10; 9 | } 10 | 11 | .todo { 12 | animation: fadeIn .5s; 13 | } 14 | 15 | @keyframes fadeIn { 16 | from { 17 | opacity: 0; 18 | } 19 | 20 | to { 21 | opacity: 1; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/config/env/test.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: process.env.NODE_ENV, 3 | target: 'http://localhost:8000', 4 | apiTarget: 'http://localhost:8000/v1', 5 | storage: { 6 | sessionKey: 'user_session', 7 | localizationKey: 'i18nextLng', 8 | }, 9 | session: { 10 | tokenKey: 'authentication_token', 11 | emailKey: 'email', 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /app/sources/session.js: -------------------------------------------------------------------------------- 1 | import api from 'services/api'; 2 | 3 | export default { 4 | urlRoot: '/session', 5 | async signin(user) { 6 | return ( 7 | await api.post(this.urlRoot, user, { withoutAuth: true }) 8 | ).data; 9 | }, 10 | async logout({ id }) { 11 | return api.delete(`${this.urlRoot}/${id}`, { withoutAuth: true }); 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /app/components/home/tests/index.snapshot.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | import Home from '../'; 4 | 5 | describe('Home', () => { 6 | const renderComponent = () => renderer.create(); 7 | 8 | it('renders correctly', () => { 9 | expect(renderComponent().toJSON()).toMatchSnapshot(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/mocks/fakeSession.js: -------------------------------------------------------------------------------- 1 | export const fakeSession = { 2 | isLoading: false, 3 | loggedIn: true, 4 | currentUser: { 5 | email: 'test@test.com', 6 | password: 'password', 7 | id: 1, 8 | }, 9 | }; 10 | 11 | export const fakeEmptySession = { 12 | isLoading: false, 13 | loggedIn: false, 14 | currentUser: {}, 15 | }; 16 | 17 | export default fakeSession; 18 | -------------------------------------------------------------------------------- /app/components/footer/tests/index.snapshot.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | import Footer from '../'; 4 | 5 | describe('Footer', () => { 6 | const renderComponent = () => renderer.create(