├── models
├── index.js
└── todo.js
├── package.json
├── routes
└── todos.js
├── index.js
├── views
└── index.html
├── helpers
└── todos.js
└── public
├── app.css
└── app.js
/models/index.js:
--------------------------------------------------------------------------------
1 | var mongoose = require('mongoose');
2 | mongoose.set('debug', true);
3 | mongoose.connect('mongodb://localhost/todo-api');
4 |
5 | mongoose.Promise = Promise;
6 |
7 | module.exports.Todo = require("./todo");
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todos_api",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "body-parser": "^1.17.2",
13 | "express": "^4.15.4",
14 | "mongoose": "^4.11.9"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/routes/todos.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var db = require("../models");
4 | var helpers = require("../helpers/todos");
5 |
6 | router.route('/')
7 | .get(helpers.getTodos)
8 | .post(helpers.createTodo)
9 |
10 | router.route('/:todoId')
11 | .get(helpers.getTodo)
12 | .put(helpers.updateTodo)
13 | .delete(helpers.deleteTodo)
14 |
15 | module.exports = router;
--------------------------------------------------------------------------------
/models/todo.js:
--------------------------------------------------------------------------------
1 | var mongoose = require('mongoose');
2 |
3 | var todoSchema = new mongoose.Schema({
4 | name: {
5 | type: String,
6 | required: 'Name cannot be blank!'
7 | },
8 | completed: {
9 | type: Boolean,
10 | default: false
11 | },
12 | created_date: {
13 | type: Date,
14 | default: Date.now
15 | }
16 | });
17 |
18 | var Todo = mongoose.model('Todo', todoSchema);
19 |
20 | module.exports = Todo;
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express'),
2 | app = express(),
3 | port = process.env.PORT || 3000,
4 | bodyParser = require('body-parser');
5 |
6 | var todoRoutes = require("./routes/todos");
7 |
8 | app.use(bodyParser.json());
9 | app.use(bodyParser.urlencoded({extended: true}));
10 | app.use(express.static(__dirname +'/public'));
11 | app.use(express.static(__dirname + '/views'));
12 |
13 | app.get('/', function(req, res){
14 | res.sendFile("index.html");
15 | });
16 |
17 | app.use('/api/todos', todoRoutes);
18 |
19 | app.listen(port, function(){
20 | console.log("APP IS RUNNING ON PORT " + process.env.PORT);
21 | })
22 |
23 |
--------------------------------------------------------------------------------
/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 | todolist
12 | A simple todo list app built with node
13 |
14 |
15 |
18 |
19 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/helpers/todos.js:
--------------------------------------------------------------------------------
1 | var db = require('../models');
2 |
3 | exports.getTodos = function(req, res){
4 | db.Todo.find()
5 | .then(function(todos){
6 | res.json(todos);
7 | })
8 | .catch(function(err){
9 | res.send(err);
10 | })
11 | }
12 |
13 | exports.createTodo = function(req, res){
14 | db.Todo.create(req.body)
15 | .then(function(newTodo){
16 | res.status(201).json(newTodo);
17 | })
18 | .catch(function(err){
19 | res.send(err);
20 | })
21 | }
22 |
23 | exports.getTodo = function(req, res){
24 | db.Todo.findById(req.params.todoId)
25 | .then(function(foundTodo){
26 | res.json(foundTodo);
27 | })
28 | .catch(function(err){
29 | res.send(err);
30 | })
31 | }
32 |
33 | exports.updateTodo = function(req, res){
34 | db.Todo.findOneAndUpdate({_id: req.params.todoId}, req.body, {new: true})
35 | .then(function(todo){
36 | res.json(todo);
37 | })
38 | .catch(function(err){
39 | res.send(err);
40 | })
41 | }
42 |
43 | exports.deleteTodo = function(req, res){
44 | db.Todo.remove({_id: req.params.todoId})
45 | .then(function(){
46 | res.json({message: 'We deleted it!'});
47 | })
48 | .catch(function(err){
49 | res.send(err);
50 | })
51 | }
52 |
53 | module.exports = exports;
--------------------------------------------------------------------------------
/public/app.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Montserrat:300,400,700');
2 |
3 | body {
4 | font-family: 'Montserrat', sans-serif;
5 | background: #ecf0f1;
6 | }
7 |
8 | /*****************************HEADER STYLES*****************************/
9 | header {
10 | text-align: center;
11 | }
12 | header h1 {
13 | font-size: 64px;
14 | font-weight: 300;
15 | margin: 80px 0 25px;
16 | color: #2c3e50;
17 | }
18 | header h1 span {
19 | font-weight: 700;
20 | }
21 | header h2 {
22 | color: #bdc3c7;
23 | font-weight:300;
24 | }
25 | /*****************************FORM STYLES*****************************/
26 |
27 | .form {
28 | width: 800px;
29 | margin: 50px auto 20px;
30 | }
31 |
32 | #todoInput {
33 | width: 100%;
34 | height: 60px;
35 | background: none;
36 | border: none;
37 | border-bottom: 1px solid #34495e;
38 | outline: none;
39 | font: 300 28px 'Ubuntu', sans-serif;
40 | padding: 20px;
41 | color: #34495e;
42 | }
43 |
44 | /*****************************LIST STYLES*****************************/
45 | .list {
46 | width: 800px;
47 | margin: 0 auto;
48 | }
49 | .task {
50 | width: 100%;
51 | height: 60px;
52 | line-height: 60px;
53 | font-size: 20px;
54 | padding: 0 20px;
55 | color: #34495e;
56 | transition: all .3s ease;
57 | }
58 | .task:hover {
59 | background: rgba(0, 0, 0, .02);
60 | cursor: pointer;
61 | }
62 |
63 | .task:hover span{
64 | opacity: 1;
65 | }
66 |
67 | .done {
68 | text-decoration: line-through;
69 | color: #bdc3c7;
70 | }
71 |
72 | li span {
73 | float: right;
74 | color: #c0392b;
75 | transition: all 0.3s;
76 | opacity: 0;
77 | }
78 |
79 | li span:hover {
80 | color: #e74c3c
81 | }
--------------------------------------------------------------------------------
/public/app.js:
--------------------------------------------------------------------------------
1 | /* global $ */
2 | $(document).ready(function(){
3 | $.getJSON("/api/todos")
4 | .then(addTodos)
5 |
6 | $('#todoInput').keypress(function(event){
7 | if(event.which == 13) {
8 | createTodo();
9 | }
10 | });
11 |
12 | $('.list').on('click', 'li', function(){
13 | updateTodo($(this));
14 | })
15 |
16 | $('.list').on('click', 'span', function(e){
17 | e.stopPropagation();
18 | removeTodo($(this).parent());
19 | })
20 | });
21 |
22 | function addTodos(todos) {
23 | //add todos to page here
24 | todos.forEach(function(todo){
25 | addTodo(todo);
26 | });
27 | }
28 |
29 | function addTodo(todo){
30 | var newTodo = $(''+todo.name +' X');
31 | newTodo.data('id', todo._id);
32 | newTodo.data('completed', todo.completed);
33 | if(todo.completed){
34 | newTodo.addClass("done");
35 | }
36 | $('.list').append(newTodo);
37 | }
38 |
39 | function createTodo(){
40 | //send request to create new todo
41 | var usrInput = $('#todoInput').val();
42 | $.post('/api/todos',{name: usrInput})
43 | .then(function(newTodo){
44 | $('#todoInput').val('');
45 | addTodo(newTodo);
46 | })
47 | .catch(function(err){
48 | console.log(err);
49 | })
50 | }
51 |
52 | function removeTodo(todo){
53 | var clickedId = todo.data('id');
54 | var deleteUrl = '/api/todos/' + clickedId;
55 | $.ajax({
56 | method: 'DELETE',
57 | url: deleteUrl
58 | })
59 | .then(function(data){
60 | todo.remove();
61 | })
62 | .catch(function(err){
63 | console.log(err);
64 | })
65 | }
66 |
67 | function updateTodo(todo){
68 | var updateUrl = '/api/todos/' + todo.data('id');
69 | var isDone = !todo.data('completed');
70 | var updateData = {completed: isDone}
71 | $.ajax({
72 | method: 'PUT',
73 | url: updateUrl,
74 | data: updateData
75 | })
76 | .then(function(updatedTodo){
77 | todo.toggleClass("done");
78 | todo.data('completed', isDone);
79 | })
80 | }
--------------------------------------------------------------------------------