├── .babelrc ├── .gitignore ├── src ├── index.js ├── book.js ├── page.js └── app.js ├── public ├── login-page │ ├── style.css │ └── index.html └── diary │ ├── index.html │ └── style.css ├── README.md ├── webpack.config.js ├── server ├── database.js ├── server.js └── entriesController.js ├── package.json └── LICENSE /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build/*.js 3 | npm-debug.log 4 | .DS_Store 5 | bundle.js 6 | bundle.js.map 7 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './app'; 4 | 5 | ReactDOM.render( 6 | , 7 | document.getElementById('root') 8 | ); -------------------------------------------------------------------------------- /public/login-page/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | background-image: url('http://wallzoa.com/wp-content/uploads/2013/06/twilight-backgrounds-woods.jpeg'); 5 | height: auto; 6 | color: white; 7 | } -------------------------------------------------------------------------------- /public/diary/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Solo Project by Alex 6 | 7 | 8 | 9 |
react didn't load
10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dear-Diary 2 | 3 | Dear-Diary is an application that can store your daily journal entry and retrieve it later on. 4 | 5 | First page is the login page. You can choose to create a new user, or you can login with previously created account. 6 | After logging in, simply type your journal entry and click the journal log button! 7 | 8 | Created by Kangseon Cho 9 | -------------------------------------------------------------------------------- /src/book.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Page from './page.js'; 3 | import axios from 'axios'; 4 | 5 | class Book extends Component { 6 | render() { 7 | // should be able to access a particular entry with a get request. 8 | return ( 9 |
10 | 12 |
13 | ); 14 | } 15 | } 16 | 17 | export default Book; -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | //do webpack stuff here 6 | entry: path.join(__dirname, 'src', 'index.js'), 7 | output: { 8 | path: path.resolve('public/diary'), //determines where the file is going (?) 9 | // publicPath: 'http://localhost:3000/public/diary', 10 | filename: 'bundle.js', 11 | }, 12 | // devtool: 'source-map', 13 | //can put plug in here if we want 14 | module: { 15 | loaders: [ 16 | { 17 | test: /\.js?$/, 18 | loader: 'babel-loader', 19 | exclude: /node_modules/, 20 | query: { 21 | presets: ["es2015", "react"] 22 | } 23 | } 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /server/database.js: -------------------------------------------------------------------------------- 1 | const Sequelize = require('sequelize'); 2 | const pg = require('pg'); 3 | 4 | //set DB connection 5 | //first argument is the database name (should be same as postgres CLI DB name, second parameter is fixed, password doesnt matter) 6 | const connection = new Sequelize('kangseoncho', 'kangseoncho', 'kangseoncho', { 7 | host: 'localhost', 8 | dialect: 'postgres', 9 | 10 | pool: { 11 | max: 5, 12 | min: 0, 13 | idle: 10000 14 | }, 15 | }); 16 | 17 | //create DB Model 18 | const Entries = connection.define('entries',{ 19 | user: {type: Sequelize.STRING, allowNull: false}, 20 | password: {type: Sequelize.STRING, allowNull: false}, 21 | title: Sequelize.STRING, 22 | logTime: Sequelize.STRING, 23 | entry: Sequelize.TEXT 24 | }); 25 | 26 | //create DB if one does not exist already 27 | connection.sync(); 28 | 29 | module.exports = Entries; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solo-project", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon ./server/server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.15.3", 14 | "body-parser": "^1.17.1", 15 | "express": "^4.15.2", 16 | "moment": "^2.18.1", 17 | "pg": "^6.1.5", 18 | "pg-hstore": "^2.3.2", 19 | "react": "^15.4.2", 20 | "react-dom": "^15.4.2", 21 | "sequelize": "^3.30.4" 22 | }, 23 | "devDependencies": { 24 | "babel-core": "^6.24.0", 25 | "babel-loader": "^6.4.1", 26 | "babel-preset-es2015": "^6.24.0", 27 | "babel-preset-react": "^6.23.0", 28 | "nodemon": "^1.11.0", 29 | "webpack": "^2.3.2", 30 | "webpack-dev-server": "^2.4.2" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Kangseon Cho 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /public/diary/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | background-image: url('http://wallzoa.com/wp-content/uploads/2013/06/twilight-backgrounds-woods.jpeg'); 5 | height: auto; 6 | } 7 | 8 | .Welcome { 9 | /*border: 1px black solid;*/ 10 | text-align: center; 11 | /*margin-left: 10%;*/ 12 | margin-top: -2%; 13 | height: auto; 14 | color: white; 15 | } 16 | 17 | .currTitle { 18 | width: 20%; 19 | background-color: transparent; 20 | height: 30px; 21 | color: white; 22 | font-size: 25px; 23 | } 24 | 25 | 26 | .Entry { 27 | padding: 20px; 28 | border: 1px white solid; 29 | border-radius: 5px; 30 | text-align: center; 31 | font-size: 16px; 32 | width: 70%; 33 | position: relative; 34 | background-color: transparent; 35 | color: white; 36 | font-size: 20px; 37 | } 38 | 39 | .log { 40 | padding: 10px; 41 | } 42 | 43 | .button { 44 | position: relative; 45 | padding: 10px; 46 | margin-left: 2%; 47 | width: 20%; 48 | height: 10%; 49 | -moz-appearance: none; 50 | border-radius: 5px; 51 | -webkit-appearance: none; 52 | background-color: white; 53 | } 54 | 55 | #searchField { 56 | font-size: 20px; 57 | width: 30%; 58 | height: 30px; 59 | position: relative; 60 | background-color: transparent; 61 | color: white; 62 | } -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | const EntriesController = require('./entriesController'); 2 | 3 | const express = require('express'); 4 | const app = express(); 5 | const bodyParser = require('body-parser'); 6 | const path = require('path'); 7 | const port = 3000; 8 | 9 | app.use('/', express.static(path.join(__dirname, "./../public/login-page"))); 10 | app.use('/welcome', express.static(path.join(__dirname, './../public/diary'))) 11 | app.use(bodyParser.urlencoded({ extended: false })) 12 | app.use(bodyParser.json()); 13 | 14 | //set a user & password for the duration of the app. 15 | let currentUser = app.locals.user; 16 | let currentPassword = app.locals.password; 17 | 18 | //two below are served statically via app.use. Only here to make redirect work. 19 | app.get('/', (req, res) => { return }) 20 | app.get('/welcome', (req, res) => { return }) 21 | 22 | //post info for verification 23 | app.post('/verification', EntriesController.verification); 24 | 25 | //post for new user 26 | app.post('/newuser', EntriesController.newUser); 27 | 28 | //post should be able to put entry into DB 29 | app.post('/entries', EntriesController.updateEntries); 30 | 31 | //should make a get req to get the entry based on the title 32 | app.get('/findEntries', EntriesController.getAllEntries); 33 | 34 | 35 | app.listen(3000, () => { 36 | console.log("direectory name: ",__dirname); 37 | console.log(`listening on port ${port}!`) 38 | }); -------------------------------------------------------------------------------- /src/page.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class Page extends Component { 4 | render() { 5 | //console.log(this.props.entry) // logs the current state and the text entry 6 | //console.log(this.props.updateEntry) //logs the function itself 7 | 8 | return ( 9 |
10 |
11 |

12 |

Welcome to Dear Diary, {this.props.user}

13 |

Entry for the Date: {this.props.logTime}

14 |

Title:

15 | 16 |
17 | 20 |
21 | 22 |
23 |
24 |
25 |
26 | 27 | 28 |
29 |
30 |
31 | ); 32 | } 33 | } 34 | 35 | export default Page; -------------------------------------------------------------------------------- /public/login-page/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Login 7 | 8 | 9 | 10 | 11 | 12 |
13 |
Welcome to Dear Diary
14 |
15 | 16 |
17 | Please log-in 18 |
19 |
20 | Username:

21 | Password:

22 | 23 |
24 |
25 |


26 | 27 |
28 | New User? Sign Up! 29 |
30 |
31 | Username:

32 | Password:

33 | 34 |
35 |
36 |
37 | 38 | 49 | 50 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Book from './book.js'; 3 | import axios from 'axios'; 4 | import moment from 'moment'; 5 | 6 | class App extends Component { 7 | constructor() { 8 | super(); 9 | this.state = { 10 | title: "", 11 | user: document.cookie.slice(5), 12 | entry: "", 13 | date: "" 14 | }; 15 | this.updateTitle = this.updateTitle.bind(this); 16 | this.updateEntry = this.updateEntry.bind(this); 17 | this.postToDB = this.postToDB.bind(this); 18 | this.logTime = this.logTime.bind(this); 19 | this.getFromDB = this.getFromDB.bind(this); 20 | } 21 | 22 | //will get the time and date of the diary entry 23 | logTime() { 24 | return moment().format('MMMM Do, YYYY'); //typeof === string 25 | } 26 | 27 | //custom function to update state based on entry entries 28 | updateEntry(event) { 29 | this.setState({ entry: event.target.value }); 30 | } 31 | updateTitle(event) { 32 | this.setState({ title: event.target.value }) 33 | } 34 | 35 | //function that will grab current state and make post request 36 | postToDB() { 37 | axios.post('http://localhost:3000/entries', { 38 | user: this.state.user, 39 | title: this.state.title, 40 | entry: this.state.entry, 41 | logTime: this.logTime() 42 | }).then((response) => { 43 | alert("logged new blog entry"); 44 | console.log("I am from Axios post request: ", response) 45 | }) 46 | } 47 | 48 | //get entries from DB 49 | getFromDB() { 50 | axios.get('http://localhost:3000/findEntries') 51 | .then((response) => { 52 | //will fild the object with the title in the seachbox 53 | let searchItem = document.getElementById('searchField').value; 54 | let result = response.data.filter((element, index) => searchItem === element.title) 55 | 56 | //populate fields with past information 57 | this.setState({ 58 | user: result[0].user, 59 | title: result[0].title, 60 | entry: result[0].entry 61 | }) 62 | }) 63 | .catch((err) => console.log(err)) 64 | } 65 | 66 | render() { 67 | return ( 68 |
69 | 71 |
72 | ); 73 | } 74 | } 75 | 76 | export default App; -------------------------------------------------------------------------------- /server/entriesController.js: -------------------------------------------------------------------------------- 1 | const Entries = require('./database'); 2 | 3 | const entriesController = { 4 | verification(req, res) { 5 | console.log("i am res.body from verification", req.body); 6 | Entries.findOne({ where: { user: req.body.user, password: req.body.password } }).then(entry => { 7 | if (entry === null) { 8 | // console.log("i am null entry: ", entry); 9 | return res.redirect('/'); 10 | } else { 11 | // console.log("i am entry: ", entry); 12 | currentUser = req.body.user; 13 | currentPassword = req.body.password; 14 | return res.redirect('/welcome'); 15 | } 16 | }) 17 | return 18 | }, 19 | 20 | newUser(req, res) { 21 | console.log("i am res.body from newuser", req.body) 22 | //find if user already exist, if so, do not make new DB entry 23 | Entries.findOne({ where: { user: req.body.user } }).then(entry => { 24 | if (entry) { 25 | // console.log("i am entry and i found stuff: ", entry); 26 | return res.redirect('/'); 27 | } else { 28 | // console.log("i am entry and didnt find stuff: ", entry) 29 | //new user, therefore make new entry 30 | Entries.create({ 31 | user: req.body.user, 32 | password: req.body.password 33 | }) 34 | //app wide declaration of user 35 | currentUser = req.body.user; 36 | currentPassword = req.body.password; 37 | return res.redirect('/welcome'); 38 | } 39 | }) 40 | return; 41 | }, 42 | 43 | updateEntries(req, res) { 44 | Entries.findOne({ where: { user: req.body.user, logTime: req.body.logTime } }).then(entry => { 45 | if (entry === null) { 46 | Entries.create({ 47 | user: req.body.user, 48 | password: currentPassword, 49 | title: req.body.title, 50 | logTime: req.body.logTime, 51 | entry: req.body.entry 52 | }).then(result => { 53 | res.json(req.body); 54 | }) 55 | return 56 | } else { 57 | Entries.update({ 58 | title: req.body.title, 59 | logTime: req.body.logTime, 60 | entry: req.body.entry 61 | }, { where: { user: req.body.user, logTime: req.body.logTime }}).then(result => { 62 | res.json(req.body); 63 | }) 64 | return 65 | } 66 | }) 67 | res.json(req.body); 68 | return; 69 | }, 70 | 71 | getAllEntries(req, res) { 72 | Entries.findAll().then((entries) => { 73 | //console.log("i am findAll: ", entries) 74 | res.json(entries) 75 | }); 76 | } 77 | } 78 | 79 | module.exports = entriesController; --------------------------------------------------------------------------------