diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/models/todo.js b/models/todo.js new file mode 100644 index 0000000..0d755a3 --- /dev/null +++ b/models/todo.js @@ -0,0 +1,12 @@ +var mongoose = require("mongoose"), + Schema = mongoose.Schema; + +var TodoSchema = new Schema ({ + task: String, + description: String +}); + +var Todo = mongoose.model("Todo", TodoSchema); + //this should match variable name + +module.exports = Todo; diff --git a/package.json b/package.json new file mode 100644 index 0000000..e712687 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "express-todo-app", + "version": "1.0.0", + "description": "**Objective:** Use Express to make a RESTful API for a to do list. Build a client for your app that uses AJAX and Handlebars templating to `CREATE`, `READ`, `UPDATE`, and `DELETE` todos.", + "main": "server.js", + "scripts": { + "test": "mocha" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/tkhuynh/express-todo-app.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/tkhuynh/express-todo-app/issues" + }, + "homepage": "https://github.com/tkhuynh/express-todo-app#readme", + "dependencies": { + "body-parser": "^1.14.1", + "express": "^4.13.3", + "hbs": "^4.0.0", + "mongoose": "^4.2.5" + } +} diff --git a/public/script.js b/public/script.js new file mode 100644 index 0000000..fa8568d --- /dev/null +++ b/public/script.js @@ -0,0 +1,81 @@ +$(function() { + var baseUrl = "/api/todos"; + var allTodos = []; + var $toDoList = $("#todos-list"); + var source = $("#todos-template").html(); + var template = Handlebars.compile(source); + var render = function() { + $toDoList.empty(); + var todosHtml = template({ todos: allTodos}); + //use find to target child element in form + $("form").find("input[name='task'], textarea").val(""); + $toDoList.append(todosHtml); + }; + $.get(baseUrl, function(data) { + allTodos = data.todos; + render(); + }); + $("#create-todos").on("submit", function(event) { + event.preventDefault(); + var newTodo = $(this).serialize(); + $.post(baseUrl, newTodo, function(data) { + allTodos.push(data); + render(); + }); + }); + + $("#todos-list").on("click", ".edit-button", function() { + var ID = $(this).attr("id"); + console.log(ID); + var todoToBeEdited = allTodos.filter(function(todo) { + return todo._id == ID; + })[0]; + var todoToBeEditedIndex = allTodos.indexOf(todoToBeEdited); + var $editForm = $("#form" + ID); + $editForm.toggle(); + $("#todos-list").on("submit", $editForm, function(event) { + event.preventDefault(); + var editedTodo = $editForm.serialize(); + console.log(editedTodo); + $.ajax({ + type: "PUT", + url: baseUrl + "/" + ID, + data: editedTodo, + success: function(data) { + allTodos.splice(todoToBeEditedIndex, 1, data); + render(); + console.log(allTodos); + } + }); + }); + }); + + $("#todos-list").on("click", ".delete-button", function () { + //if was del{{_id}} >> need to remove first 3 letters + var ID = $(this).attr("id").slice(3); + var todoToBeDeleted = allTodos.filter(function(todo) { + return todo._id == ID; + })[0]; + var todoToBeDeletedIndex = allTodos.indexOf(todoToBeDeleted); + $.ajax({ + type: "DELETE", + url: baseUrl + "/" + ID, + data: todoToBeDeleted, + success: function (data) { + allTodos.splice(todoToBeDeletedIndex, 1); + render(); + } + }); + }); + $("#todos-list").on("change", ".check", function (event) { + var ID = $(this).attr("id").slice(7); + var doneTodo = "#row" + ID + " h4," + "#row" + ID + " .task-name"; + var done = allTodos.filter(function(todo) { + return todo._id == ID; + })[0]; + var editButton = "#row" + ID + " .edit-button"; + $(doneTodo).toggleClass("done"); + $(editButton).toggleClass("disabled"); + console.log(done); + }); +}); \ No newline at end of file diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..6b882ba --- /dev/null +++ b/public/style.css @@ -0,0 +1,45 @@ +body { + background-color: #F7DCB4; +} +h1 { + color: #663333; + font-size: 60px; + font-family: 'Noto Serif', serif; + margin-bottom: 15px; + clear: :both; +} +img { + float: left; + width: 60px; +} +.task-column { + border-right: 1px solid #EEEEEE +} +.done { + text-decoration: line-through; +} +h4, .task-name { + padding: 0px 5px 0px 5px; + font-size: 25px; + font-family: 'Indie Flower', cursive; +} +.edit-form { + display: none; +} +.button-holder { + margin-bottom: 30px; + display: inline; + float: right; +} + +@media (max-width: 500px) { + h1 { + font-size: 45px; + } + img { + width: 45px; + } + h4 { + font-size: 15px:; + } +} \ No newline at end of file diff --git a/server.js b/server.js new file mode 100644 index 0000000..17ea202 --- /dev/null +++ b/server.js @@ -0,0 +1,102 @@ +var express = require("express"); +var bodyParser = require("body-parser"); +var hbs = require("hbs"); +var mongoose = require("mongoose"); + +var app = express(); + +app.set("view engine", "hbs"); + +app.use(express.static("public")); // app.use(express.static(__dirname + "/public")); + +//set up body-parser +app.use(bodyParser.urlencoded({ + extended: true +})); +//connect to mongodb +mongoose.connect('mongodb://localhost/todo-app'); + +var Todo = require("./models/todo"); //it's ok without .js + + +//setup routes + +app.get("/", function(req, res) { + res.render("index"); +}); + +//set up todos api +app.get("/api/todos", function(req, res) { + //Mongo + //find all todos in db + Todo.find(function(err, allTodos) { + res.json({ + todos: allTodos + }); + }); +}); + +//get a todo by its Id +app.get("/api/todos/:id", function(req, res) { + //Mongo + //get id from url + var todoId = req.params.id; + + // find todo in db by id + Todo.findOne({ + _id: todoId + }, function(err, foundTodo) { + res.json(foundTodo); + }); +}); + +//create new one +app.post("/api/todos", function(req, res) { + //Mongo + // create new todo with form data (`req.body`) + var newTodo = new Todo(req.body); + + // save new todo in db + newTodo.save(function(err, savedTodo) { + res.json(savedTodo); + }); +}); + +/// update todo +// update todo +app.put('/api/todos/:id', function(req, res) { + // get todo id from url params (`req.params`) + var todoId = req.params.id; + + // find todo in db by id + Todo.findOne({ + _id: todoId + }, function(err, foundTodo) { + // update the todos's attributes + foundTodo.task = req.body.task; + foundTodo.description = req.body.description; + + // save updated todo in db + foundTodo.save(function(err, savedTodo) { + res.json(savedTodo); + }); + }); +}); + +// delete todo +app.delete('/api/todos/:id', function(req, res) { + // get todo id from url params (`req.params`) + var todoId = req.params.id; + + // find todo in db by id and remove + Todo.findOneAndRemove({ + _id: todoId + }, function(err, deletedTodo) { + res.json(deletedTodo); + }); +}); + +//listen to port 3000 +var server = app.listen(process.env.PORT || 3000, function() { + console.log("I'm listening"); +}); \ No newline at end of file diff --git a/views/index.hbs b/views/index.hbs new file mode 100644 index 0000000..3813995 --- /dev/null +++ b/views/index.hbs @@ -0,0 +1,99 @@ + + + + + + + + + + + + Document + + +
+
+
+
+ +

To Do List

+
+
+
+
+
+ +
+
+ +
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + \ No newline at end of file