diff --git a/.gitignore b/.gitignore
index 028e2a6..9c301b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ public/bundle.js
package-lock.json
*hot-update.js
*hot-update.json
+env.sh
diff --git a/backend/routes.js b/backend/routes.js
index 9dd2215..5fc13a7 100644
--- a/backend/routes.js
+++ b/backend/routes.js
@@ -1,11 +1,148 @@
const express = require('express');
const router = express.Router();
+const { User, Post } = require('../models');
+const bcrypt = require('bcrypt');
+let hashedPassword;
-// YOUR API ROUTES HERE
+module.exports = (passport) => {
+ // YOUR API ROUTES HERE
+ router.post('/register', (req, res) => {
+ User.findAll({where: {username: req.body.username}})
+ .then(users => {
+ if(req.body.password === req.body.repeatPassword && !users[0]) {
+ bcrypt.hash(req.body.password, 10, (err, hash) => {
+ hashedPassword = hash;
+ User.create({
+ username: req.body.username,
+ password: hashedPassword
+ })
+ .then(() => {
+ res.json({success: true});
+ });
+ });
+ } else {
+ res.json({success: false});
+ }
+ })
+ .catch((err)=>console.log(err));
+ });
-// SAMPLE ROUTE
-router.use('/users', (req, res) => {
- res.json({ success: true });
-});
+ router.post('/login', (req, res, next) => {
+ passport.authenticate('local', (err, user) => {
+ console.log('HERE');
+ user ? req.login(user, error => {
+ if(err) {return next(error);}
+ return res.json({success: true, user: req.user});
+ }) : res.json({success: false});
+ })(req, res, next);
+ });
-module.exports = router;
+ router.get('/posts/all', (req, res) => {
+ Post.findAll({
+ where: {fk_post_id: null}
+ })
+ .then((posts) => {
+ var newPosts = posts.map(post => post.dataValues);
+ console.log(newPosts);
+ res.json({success: true, posts: newPosts});
+ });
+ });
+
+ router.use((req, res, next) => {
+ console.log(req.user, "MIddleware req.user is this");
+ if (!req.user) {
+ res.status(401).json({success: 'failed'});
+ } else {
+ next();
+ }
+ });
+
+ router.get('/logout', (req, res) => {
+ req.logout();
+ res.status(200).json({success: true});
+ });
+
+
+ router.get('/:username', (req, res) => {
+ User.findOne({where: {username: req.params.username}})
+ .then((user) => {
+ if(user) {
+ console.log(user.dataValues, "USer data values");
+ res.json({success: true, user: Object.assign({}, user.dataValues, {password: null})});
+ } else {
+ res.json({success: false, user: null});
+ }
+ });
+ });
+
+ router.get('/user', (req, res) => {
+ User.findOne({where: {username: req.user.username}})
+ .then((user) => {
+ res.json({success: true, user: user.dataValues});
+ });
+ });
+
+ router.post('/post/new', (req, res) => {
+ Post.create({
+ fk_post_id: req.body.postId,
+ img: req.body.img,
+ description: req.body.description,
+ fk_user_id: req.user.id,
+ title: req.body.title
+ })
+ .then(() => {
+ console.log('then inside');
+ res.json({success: true});
+ })
+ .catch((error)=>{
+ console.log('inside catch', error);
+ res.json({success: false, error: error});
+ });
+ });
+
+ async function recurse(post) {
+ try {
+ var comments = await Post.findAll({where: {fk_post_id: post.id}});
+ if (!comments) {
+ return Object.assign({}, post);
+ }
+ return Object.assign({}, post, {children: comments.map((comment) => recurse(comment))
+ });
+ } catch (err) {
+ return false;
+ }
+ }
+
+ router.get('/post/:id', (req, res) => {
+ Post.findOne({where: {id: req.params.id}})
+ .then(async (post) => {
+ var comments = await recurse(post.dataValues);
+ if(!comments) {
+ res.json({
+ success: false,
+ comments: null
+ });
+ }
+ console.log(comments, 'COMMENTS AFTER RECURSE');
+ res.json({
+ success: true,
+ postContents: comments
+ });
+ })
+ .catch((err) => {
+ console.log('Inside catch for findOne');
+ res.json({
+ success: false,
+ error: err
+ });
+ });
+ });
+
+
+ // SAMPLE ROUTE
+ router.use('/users', (req, res) => {
+ res.json({ success: true });
+ });
+
+ return router;
+};
diff --git a/frontend/actions/index.js b/frontend/actions/index.js
index 2bba168..28433d5 100644
--- a/frontend/actions/index.js
+++ b/frontend/actions/index.js
@@ -1,3 +1,8 @@
// Action Creators
// import * as types from './types';
+export function toggleLoginModal() {
+ return {
+ type: 'TOGGLE_LOGIN_MODAL'
+ };
+}
diff --git a/frontend/assets/stylesheets/base.scss b/frontend/assets/stylesheets/base.scss
index 1ddbba3..190630b 100644
--- a/frontend/assets/stylesheets/base.scss
+++ b/frontend/assets/stylesheets/base.scss
@@ -1,4 +1,42 @@
h1 {
font-family: helvetica;
font-weight: 200;
-}
\ No newline at end of file
+}
+
+.headerContent {
+ background-image: url("http://pic.templetons.com/brad/pano/sfba/best-treas.jpg");
+ height: 100px;
+ background-size: cover;
+ background-repeat: no-repeat;
+ border: 5px solid orange;
+}
+
+.postContent {
+ display: flex;
+ border-radius: 5px;
+ border: 5px solid black;
+ padding-top: 100px;
+ width: 500px;
+}
+
+.commentHolder {
+ position: relative;
+ left: 100px;
+}
+
+.comment {
+ display: flex;
+}
+
+.postHeader {
+ display: flex;
+ padding: 10px;
+ padding-bottom: 20px;
+ border-bottom: 2px solid grey;
+}
+
+.postBody {
+ display: flex;
+ justify-content: space-between;
+ padding: 20px
+}
diff --git a/frontend/components/Comment.js b/frontend/components/Comment.js
new file mode 100644
index 0000000..cb43804
--- /dev/null
+++ b/frontend/components/Comment.js
@@ -0,0 +1,59 @@
+var React = require('react');
+import PropTypes from 'prop-types';
+// var { Navbar, FormGroup, FormControl, Button, Checkbox, Col, Form, ControlLabel, HelpBlock} = require('react-bootstrap');
+// var axios = require('axios');
+
+// This assumes we are passing in posts
+// Each post has: img (string url) and description
+
+
+class Comment extends React.Component {
+ constructor() {
+ super();
+ this.state = {
+ hideChildren: true
+ }
+ }
+
+
+ clickHandler() {
+ this.setState({
+ hideChildren: false
+ })
+ }
+
+ render() {
+ return (
+
+
+
+
+ {this.props.comment.content.description}
+
+
this.clickHandler()}>
+ {this.state.children.length} comments
+
+ {this.state.hideChildren ? null :
+ this.props.comment.children.map((comment) => {
+ return (
+
+
+
+ )
+ })
+ })
+
+ );
+ }
+};
+
+Comment.propTypes = {
+ comment: PropTypes.object,
+};
+
+
+export default Comment;
diff --git a/frontend/components/Description.js b/frontend/components/Description.js
new file mode 100644
index 0000000..06db410
--- /dev/null
+++ b/frontend/components/Description.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const Description = ( { description } ) => {
+ return (
+
+ );
+};
+
+Description.propTypes = {
+ description: PropTypes.string,
+};
+
+
+export default Description;
diff --git a/frontend/components/Feed.js b/frontend/components/Feed.js
new file mode 100644
index 0000000..9b1805b
--- /dev/null
+++ b/frontend/components/Feed.js
@@ -0,0 +1,92 @@
+var React = require('react');
+var { Navbar, FormGroup, FormControl, Button, Checkbox, Col, Form, ControlLabel, HelpBlock} = require('react-bootstrap');
+var axios = require('axios');
+var { Redirect } = require('react-router');
+// This assumes we are passing in posts
+// Each post has: img (string url) and description
+let posts = [{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://media.licdn.com/mpr/mpr/AAEAAQAAAAAAAALwAAAAJDliZTVkOTcyLWQ0NzUtNDNlZC1hZmEwLTY1NTQ0ZDBjNTE5ZA.jpg',
+title: "This is what humans call a 'moose' "},{img: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Moose_superior.jpg/1200px-Moose_superior.jpg',
+title: "This is what humans call a 'moose' "},
+{img: 'http://i.telegraph.co.uk/multimedia/archive/02622/geese_2622145b.jpg',
+title: "This is what humans call 'geese'. The singular term is 'goose'. They are notorious for pooping in groups over the skies."}]
+
+class Feed extends React.Component {
+ constructor(){
+ super();
+ this.state = {
+ posts: posts,
+ redirect: false,
+ post_id: null
+ }
+ }
+
+ componentDidMount() {
+ axios.get('http://localhost:3000/api/posts/all', {
+ withCredentials: true
+ })
+ .then((resp) => {
+ this.setState({
+ posts: [...this.state.posts, ...resp.data.posts]
+ })
+ })
+ .catch(e => {
+ console.log(e);
+ })
+ }
+ postClick(i) {
+ console.log('clicked!');
+ this.setState({
+ redirect: true,
+ post_id: this.state.posts[i].id
+ });
+ }
+ render() {
+ return (
+ this.state.redirect ? :
+
+ {
+ this.state.posts.map((post, i) => {
+ return (
+
+ );
+ })
+ }
+
+ );
+ }
+ }
+
+
+export default Feed;
diff --git a/frontend/components/Header.js b/frontend/components/Header.js
new file mode 100644
index 0000000..76ca778
--- /dev/null
+++ b/frontend/components/Header.js
@@ -0,0 +1,49 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Navbar, Nav, NavDropdown, MenuItem } from 'react-bootstrap';
+
+const Header = ( { name } ) => {
+ return (
+
+ {/*
+ */}
+
+
+
+

+
+
+
+ R/ HORIZONS
+
+
+ {/* */}
+
+
+
+ {/*
+ */}
+
+
+ );
+ };
+
+ Header.propTypes = {
+ name: PropTypes.string,
+ };
+
+
+ export default Header;
diff --git a/frontend/components/Login.js b/frontend/components/Login.js
new file mode 100644
index 0000000..f682276
--- /dev/null
+++ b/frontend/components/Login.js
@@ -0,0 +1,110 @@
+import React from 'react';
+import { Button, Modal, Glyphicon } from 'react-bootstrap';
+import axios from 'axios';
+
+class Login extends React.Component {
+ constructor(props) {
+ super(props);
+ this.username = this.refs.username;
+ this.password = this.refs.password;
+ this.rPassword = this.refs.rPassword;
+ this.state = {
+ modalOpen: false,
+ signUp: false
+ };
+ }
+ modalOpen() {
+ this.setState({
+ modalOpen: !this.state.modalOpen
+ });
+ }
+ onSignUp() {
+ this.setState({
+ signUp: true
+ });
+ }
+ login() {
+ axios.post('http://localhost:3000/api/login', {
+ username: this.refs.username.value,
+ password: this.refs.password.value
+ }, {
+ withCredentials: true
+ })
+ .then((resp) => {
+ console.log(resp.data);
+ this.setState({
+ modalOpen: false
+ }, () => this.props.onLogin());
+ })
+ .catch(err => {
+ console.log(err);
+ });
+ }
+ register() {
+ axios.post('http://localhost:3000/api/register', {
+ username: this.refs.username.value,
+ password: this.refs.password.value,
+ repeatPassword: this.refs.rPassword.value
+ })
+ .then((resp) => {
+ this.setState({
+ modalOpen: false,
+ signUp: true
+ }, this.onSignUp());
+ })
+ .catch(err => {
+ console.log(err);
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+
+export default Login;
diff --git a/frontend/components/NewPost.js b/frontend/components/NewPost.js
new file mode 100644
index 0000000..e5a7650
--- /dev/null
+++ b/frontend/components/NewPost.js
@@ -0,0 +1,120 @@
+var React = require('react');
+var {Redirect} = require('react-router');
+var {FormGroup, FormControl, Col, Form, ControlLabel, HelpBlock} = require('react-bootstrap');
+var axios = require('axios');
+
+class NewPost extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ redirect: false,
+ title: '',
+ description: '',
+ link: '',
+ image: ''
+ };
+ }
+
+ postNewPost() {
+ axios.post('http://localhost:3000/api/post/new', {
+ postId: null,
+ img: this.state.link,
+ description: this.state.description,
+ title: this.state.title
+ }, {
+ withCredentials: true
+ })
+ .catch(e => {
+ console.log("Posting new post failed", e);
+ });
+ }
+ onSubmitPost() {
+ this.setState({
+ redirect: true
+ }, () => this.postNewPost());
+ }
+ onTitleChange(e) {
+ this.setState({
+ title: e.target.value
+ });
+ }
+ onDescriptionChange(e) {
+ this.setState({
+ description: e.target.value
+ });
+ }
+ onLinkChange(e) {
+ this.setState({
+ link: e.target.value
+ });
+ }
+ onImgSelect(e) {
+ this.setState({
+ image: e.target.value
+ });
+ }
+ render() {
+ function FieldGroup({ id, type, label, help }) {
+ return (
+
+ {label}
+
+ {help && {help}}
+
+ );
+ }
+ return (
+ (this.state.redirect) ? () : (
+
+ )
+ );
+ }
+}
+
+export default NewPost;
diff --git a/frontend/components/SideBar.js b/frontend/components/SideBar.js
new file mode 100644
index 0000000..abbf373
--- /dev/null
+++ b/frontend/components/SideBar.js
@@ -0,0 +1,49 @@
+import React from 'react';
+import { Panel, Button } from 'react-bootstrap';
+import SubmitPost from './SubmitPost';
+import Login from './Login';
+import Description from './Description';
+import axios from 'axios';
+
+class SideBar extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ loggedIn: false,
+ description: "I don't know what you need here."
+ };
+ }
+ onLogin() {
+ this.setState({
+ loggedIn: true
+ });
+ }
+ logout() {
+ axios.get('http://localhost:3000/api/logout', {
+ withCredentials: true
+ })
+ .then((resp) => {
+ console.log(resp.data);
+ this.setState({
+ loggedIn: false
+ });
+ })
+ .catch(err => {
+ console.log(err);
+ });
+ }
+ render() {
+ return (
+
+
+ {(this.state.loggedIn) ? (
)
+ : (
this.onLogin()} />)}
+
+
+
+
+ );
+ }
+}
+
+export default SideBar;
diff --git a/frontend/components/SubmitPost.js b/frontend/components/SubmitPost.js
new file mode 100644
index 0000000..c3098fd
--- /dev/null
+++ b/frontend/components/SubmitPost.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import { Button } from 'react-bootstrap';
+import { Redirect } from 'react-router';
+
+class SubmitPost extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ redirect: false
+ };
+ }
+ newPostPage() {
+ this.setState({
+ redirect: true
+ });
+ }
+ render() {
+ return (
+
+ {
+ (this.state.redirect) ? ()
+ : ()
+ }
+
+ );
+ }
+}
+
+
+export default SubmitPost;
diff --git a/frontend/containers/AppContainer.js b/frontend/containers/AppContainer.js
index 7c29205..5bbfaab 100644
--- a/frontend/containers/AppContainer.js
+++ b/frontend/containers/AppContainer.js
@@ -1,28 +1,39 @@
import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
-import Title from '../components/Title';
+import Header from '../components/Header';
+import DevTools from './DevTools';
+import SideBar from '../components/SideBar';
+import Feed from '../components/Feed';
+import NewPost from '../components/NewPost';
-const AppContainer = ({ name }) => {
+
+import { toggleLoginModal } from '../actions/index';
+
+const AppContainer = ({ toggleLogin }) => {
return (
-
+
+
+
+
);
};
AppContainer.propTypes = {
- name: PropTypes.string,
+ toggleLogin: PropTypes.func
};
const mapStateToProps = (state) => {
return {
- name: state.name
+ state: state
};
};
-const mapDispatchToProps = (/* dispatch */) => {
+const mapDispatchToProps = (dispatch) => {
return {
+ toggleLogin: () => {dispatch(toggleLoginModal());}
};
};
diff --git a/frontend/containers/PostPage.js b/frontend/containers/PostPage.js
new file mode 100644
index 0000000..e6d9efc
--- /dev/null
+++ b/frontend/containers/PostPage.js
@@ -0,0 +1,72 @@
+var React = require('react');
+// var { Navbar, FormGroup, FormControl, Button, Checkbox, Col, Form, ControlLabel, HelpBlock} = require('react-bootstrap');
+var axios = require('axios');
+import Comment from '../components/Comment';
+import Header from '../components/Header';
+import Sidebar from '../components/SideBar';
+
+
+// This assumes we are passing in posts
+// Each post has: img (string url) and description
+
+
+class PostPage extends React.Component {
+ constructor() {
+ super();
+ this.state = {
+ post: {}
+ };
+ }
+
+ componentDidMount() {
+
+ console.log(this.props.match.params.id, 'ID parameter');
+ axios.get(`http://localhost:3000/api/post/`+ this.props.match.params.id,
+ {
+ withCredentials: true
+ })
+ .then((comments) => {
+ console.log(comments.data);
+ this.setState({
+ post: comments.data.postContents
+ });
+ })
+ .catch(e => {
+ console.log(e);
+ });
+ }
+ render() {
+ return (
+
+
+
+
+
+
+
+
{this.state.post.title}
+
+
+
+
{this.state.post.description}
+ {/*
+ {this.state.post.children.map((comment) => {
+ return(
+
+
+
+ )
+ })}
+
*/}
+
+
+
+ );
+ }
+ }
+
+export default PostPage;
diff --git a/frontend/containers/Root.dev.js b/frontend/containers/Root.dev.js
index c0f8d69..9e3a138 100644
--- a/frontend/containers/Root.dev.js
+++ b/frontend/containers/Root.dev.js
@@ -1,20 +1,31 @@
import PropTypes from 'prop-types';
import React from 'react';
import {Provider} from 'react-redux';
+import Feed from '../components/Feed.js';
+import NewPost from '../components/NewPost.js';
+import Login from '../components/Login';
+import SubmitPost from '../components/SubmitPost';
+import { HashRouter, Route, Switch } from 'react-router-dom';
import AppContainer from './AppContainer.js';
-import DevTools from './DevTools';
+import PostPage from './PostPage.js';
+
export default function Root({ store }) {
return (
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
);
}
-
Root.propTypes = {
store: PropTypes.object.isRequired
};
diff --git a/frontend/index.js b/frontend/index.js
index 411485c..f2fa945 100644
--- a/frontend/index.js
+++ b/frontend/index.js
@@ -1,11 +1,13 @@
import React from 'react';
import { render } from 'react-dom';
-import { configureStore, history } from './store/configureStore';
+import { configureStore } from './store/configureStore';
+import createHistory from 'history/createBrowserHistory';
import Root from './containers/Root';
import './assets/stylesheets/base.scss';
-const store = configureStore();
+export const store = configureStore();
+export const history = createHistory();
render(
,
diff --git a/frontend/reducers/index.js b/frontend/reducers/index.js
index 4d415fd..f7f0bcb 100644
--- a/frontend/reducers/index.js
+++ b/frontend/reducers/index.js
@@ -1,5 +1,12 @@
-function rootReducer(state = {name: 'Horizons'}, action) {
+function rootReducer(state = {
+ isModalOpen: false,
+ signUp: false}, action) {
switch (action.type) {
+ case "TOGGLE_LOGIN_MODAL":
+ console.log(state.isModalOpen);
+ return Object.assign({}, state, {isModalOpen: !state.isModalOpen});
+ case "SIGN_UP":
+ return Object.assign({}, state, {signUp: !state.signUp});
default:
return state;
}
diff --git a/models.js b/models.js
new file mode 100644
index 0000000..79aa118
--- /dev/null
+++ b/models.js
@@ -0,0 +1,68 @@
+"use strict";
+
+var Sequelize = require('sequelize');
+var sequelize = new Sequelize(process.env.DATABASE_NAME, 'postgres', process.env.DATABASE_PASSWORD, {
+ dialect: 'postgres'
+});
+
+sequelize
+.authenticate()
+.then(() => {
+ console.log('Connection has been established successfully.');
+})
+.catch(err => {
+ console.error('Unable to connect to the database:', err);
+});
+
+var User = sequelize.define('user', {
+ id: {
+ type: Sequelize.INTEGER,
+ primaryKey: true,
+ autoIncrement: true
+ },
+ username: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ unique: true
+ },
+ password: {
+ type: Sequelize.STRING,
+ allowNull: false
+ },
+ // ADD MORE ATTRIBUTES HERE
+});
+
+var Post = sequelize.define('posts', {
+ id: {
+ type: Sequelize.INTEGER,
+ primaryKey: true,
+ autoIncrement: true
+ },
+ fk_post_id: {
+ type: Sequelize.INTEGER,
+ allowNull: true
+ },
+ img: {
+ type: Sequelize.STRING,
+ allowNull: true
+ },
+ description: {
+ type: Sequelize.STRING,
+ allowNull: true
+ },
+ title: {
+ type: Sequelize.STRING,
+ allowNull: true
+ },
+ fk_user_id: {
+ type: Sequelize.INTEGER,
+ sllowNull: false
+ }
+});
+
+module.exports = {
+ sequelize,
+ User,
+ Post,
+ // EXPORT models HERE
+};
diff --git a/package.json b/package.json
index 54019e8..ee3524d 100644
--- a/package.json
+++ b/package.json
@@ -14,26 +14,40 @@
"author": "",
"license": "ISC",
"dependencies": {
+ "axios": "^0.17.0",
"babel-core": "^6.24.1",
"babel-loader": "^6.4.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
+ "bcrypt": "^1.0.3",
+ "body-parser": "^1.18.2",
"css-loader": "^0.28.0",
"enzyme": "^2.8.1",
"expect": "^1.20.2",
"express": "^4.15.2",
+ "express-session": "^1.15.6",
+ "history": "^4.7.2",
"mocha": "^3.2.0",
"node-sass": "^4.5.2",
+ "passport": "^0.4.0",
+ "passport-local": "^1.0.0",
+ "pg": "^7.4.0",
+ "pg-hstore": "^2.3.2",
"prop-types": "^15.5.8",
"react": "^15.5.4",
+ "react-bootstrap": "^0.31.5",
"react-dom": "^15.5.4",
"react-redux": "^5.0.5",
+ "react-router": "^4.2.0",
+ "react-router-dom": "^4.2.2",
"redux": "^3.7.2",
"redux-devtools": "^3.4.0",
"redux-devtools-dock-monitor": "^1.1.2",
"redux-devtools-log-monitor": "^1.3.0",
"sass-loader": "^6.0.3",
+ "sequelize": "^4.10.0",
"style-loader": "^0.16.1",
+ "underscore": "^1.8.3",
"webpack": "^2.3.3"
},
"devDependencies": {
diff --git a/public/index.html b/public/index.html
index 9604aed..a56a6f3 100644
--- a/public/index.html
+++ b/public/index.html
@@ -3,9 +3,10 @@
Node + React Starter
+
-