diff --git a/.vscode/settings.json b/.vscode/settings.json
index c3c81b8b..8347b197 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,4 @@
{
- "editor.fontSize": 42,
- "terminal.integrated.fontSize": 62
-}
\ No newline at end of file
+ "editor.fontSize": 18,
+ "terminal.integrated.fontSize": 20
+}
diff --git a/public/css/style.css b/public/css/style.css
index 0475253a..25275d12 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -1,7 +1,9 @@
-h1{
+/* set the H1 text color to red */
+h1 {
color: red;
}
-.completed{
+/* set the completed items to gray, and strike a line through the text */
+.completed {
color: gray;
text-decoration: line-through;
-}
\ No newline at end of file
+}
diff --git a/public/js/main.js b/public/js/main.js
index ff0eac39..888c542d 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -1,72 +1,111 @@
-const deleteBtn = document.querySelectorAll('.fa-trash')
-const item = document.querySelectorAll('.item span')
-const itemCompleted = document.querySelectorAll('.item span.completed')
+// create a "nodelist" of every item with these classes (trash icon)
+const deleteBtn = document.querySelectorAll(".fa-trash");
+// create a "nodelist" of every item with these classes (item span)
+const item = document.querySelectorAll(".item span");
+// create a "nodelist" of every item with these classes (item, completed)
+const itemCompleted = document.querySelectorAll(".item span.completed");
-Array.from(deleteBtn).forEach((element)=>{
- element.addEventListener('click', deleteItem)
-})
+// create an array from these node lists, and add event listeners to each one
+Array.from(deleteBtn).forEach((element) => {
+ // run the deleteItem function when we click on the item
+ element.addEventListener("click", deleteItem);
+});
-Array.from(item).forEach((element)=>{
- element.addEventListener('click', markComplete)
-})
+Array.from(item).forEach((element) => {
+ // run the markComplete function when we click on the item
+ element.addEventListener("click", markComplete);
+});
-Array.from(itemCompleted).forEach((element)=>{
- element.addEventListener('click', markUnComplete)
-})
+Array.from(itemCompleted).forEach((element) => {
+ // run the markUnComplete function when we click on the item
+ element.addEventListener("click", markUnComplete);
+});
-async function deleteItem(){
- const itemText = this.parentNode.childNodes[1].innerText
- try{
- const response = await fetch('deleteItem', {
- method: 'delete',
- headers: {'Content-Type': 'application/json'},
+// delete item function
+async function deleteItem() {
+ // from the trash icon, go up to the parent node (the
)
+ // then go to the second child node (index 0), and grab the innerText
+ // essentially - save the todo item text in a variable
+ const itemText = this.parentNode.childNodes[1].innerText;
+ try {
+ // make a fetch request to the deleteItem route
+ const response = await fetch("deleteItem", {
+ // DELETE method
+ method: "delete",
+ // set the headers to json
+ headers: { "Content-Type": "application/json" },
+ // in the body of the text
body: JSON.stringify({
- 'itemFromJS': itemText
- })
- })
- const data = await response.json()
- console.log(data)
- location.reload()
-
- }catch(err){
- console.log(err)
+ // send the text of the todo
+ itemFromJS: itemText,
+ }),
+ });
+ // wait for the response
+ const data = await response.json();
+ // log the data
+ console.log(data);
+ // reload the current URL
+ location.reload();
+ } catch (err) {
+ // otherwise log the error
+ console.log(err);
}
}
-async function markComplete(){
- const itemText = this.parentNode.childNodes[1].innerText
- try{
- const response = await fetch('markComplete', {
- method: 'put',
- headers: {'Content-Type': 'application/json'},
+// mark complete function
+async function markComplete() {
+ // grab the text from the todo
+ const itemText = this.parentNode.childNodes[1].innerText;
+ // make a fetch reqeust to the mark complete route
+ try {
+ const response = await fetch("markComplete", {
+ // PUT request
+ method: "put",
+ // json data
+ headers: { "Content-Type": "application/json" },
+ // convert the objects to string
body: JSON.stringify({
- 'itemFromJS': itemText
- })
- })
- const data = await response.json()
- console.log(data)
- location.reload()
-
- }catch(err){
- console.log(err)
+ // send the todo text
+ itemFromJS: itemText,
+ }),
+ });
+ // wait for the response
+ const data = await response.json();
+ // log the data
+ console.log(data);
+ // reload the current route
+ location.reload();
+ } catch (err) {
+ // log the error
+ console.log(err);
}
}
-async function markUnComplete(){
- const itemText = this.parentNode.childNodes[1].innerText
- try{
- const response = await fetch('markUnComplete', {
- method: 'put',
- headers: {'Content-Type': 'application/json'},
+// marking an item as uncomplete
+async function markUnComplete() {
+ // grab the todo text
+ const itemText = this.parentNode.childNodes[1].innerText;
+ try {
+ // fetch request to the mark uncomplete route
+ const response = await fetch("markUnComplete", {
+ // PUT request
+ method: "put",
+ // json data is set
+ headers: { "Content-Type": "application/json" },
+ // stringify the object
body: JSON.stringify({
- 'itemFromJS': itemText
- })
- })
- const data = await response.json()
- console.log(data)
- location.reload()
-
- }catch(err){
- console.log(err)
+ // send the todo text in the body of the request
+ itemFromJS: itemText,
+ }),
+ });
+ // wait for the response
+ const data = await response.json();
+ // log the data
+ console.log(data);
+ // reload the page
+ location.reload();
+ } catch (err) {
+ // log the error if there is one
+ console.log(err);
}
-}
\ No newline at end of file
+}
diff --git a/server.js b/server.js
index 58b53e2f..d7e95f56 100644
--- a/server.js
+++ b/server.js
@@ -1,30 +1,54 @@
-const express = require('express')
-const app = express()
-const MongoClient = require('mongodb').MongoClient
-const PORT = 2121
-require('dotenv').config()
-
+// import express
+const express = require("express");
+// call the express function and store it in the `app` variable
+const app = express();
+// create instance of the Mongo Client which represents a pool of connections to the database
+const MongoClient = require("mongodb").MongoClient;
+// set the port that we'll use for our application
+// this is where our server is listening for requests
+const PORT = 2121;
+// require the dotenv package to keep environment variables secret
+require("dotenv").config();
+// set variables for the database
let db,
+ // store connection string for database in this variable
dbConnectionStr = process.env.DB_STRING,
- dbName = 'todo'
+ // name the database
+ dbName = "todo";
-MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true })
- .then(client => {
- console.log(`Connected to ${dbName} Database`)
- db = client.db(dbName)
- })
-
-app.set('view engine', 'ejs')
-app.use(express.static('public'))
-app.use(express.urlencoded({ extended: true }))
-app.use(express.json())
+// connect to the Mongo DB database, using the connection string
+MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true }).then(
+ (client) => {
+ // print successful database connection to the console
+ console.log(`Connected to ${dbName} Database`);
+ // store the database name in the db variable
+ db = client.db(dbName);
+ }
+);
+// middleware methods used
+// set the view engine to EJS
+app.set("view engine", "ejs");
+// serve files in the public directory as static files
+app.use(express.static("public"));
+// parse incoming requests with urlencoded payloads
+// The “extended” syntax allows for rich objects and arrays to be encoded into the URL-encoded format, allowing for a JSON-like experience with URL-encoded.
+// essentially decode URLS and arrays where the body matches the content type
+app.use(express.urlencoded({ extended: true }));
+// middleware to parse json data from incoming requests, replaces body-parser
+app.use(express.json());
-app.get('/',async (request, response)=>{
- const todoItems = await db.collection('todos').find().toArray()
- const itemsLeft = await db.collection('todos').countDocuments({completed: false})
- response.render('index.ejs', { items: todoItems, left: itemsLeft })
+// for GET requests on the root route
+app.get("/", async (request, response) => {
+ // asynchronous request to go to the todos collection, find everything, and turn it into an array, store the result in todoitems variable
+ const todoItems = await db.collection("todos").find().toArray();
+ // return from the db all the todos that aren't completed yet, store in itemsLeft variable
+ const itemsLeft = await db
+ .collection("todos")
+ .countDocuments({ completed: false });
+ // render the response in ejs, passin the variables under items and left
+ response.render("index.ejs", { items: todoItems, left: itemsLeft });
// db.collection('todos').find().toArray()
// .then(data => {
// db.collection('todos').countDocuments({completed: false})
@@ -33,61 +57,107 @@ app.get('/',async (request, response)=>{
// })
// })
// .catch(error => console.error(error))
-})
-
-app.post('/addTodo', (request, response) => {
- db.collection('todos').insertOne({thing: request.body.todoItem, completed: false})
- .then(result => {
- console.log('Todo Added')
- response.redirect('/')
- })
- .catch(error => console.error(error))
-})
-
-app.put('/markComplete', (request, response) => {
- db.collection('todos').updateOne({thing: request.body.itemFromJS},{
- $set: {
- completed: true
- }
- },{
- sort: {_id: -1},
- upsert: false
- })
- .then(result => {
- console.log('Marked Complete')
- response.json('Marked Complete')
- })
- .catch(error => console.error(error))
-
-})
+});
-app.put('/markUnComplete', (request, response) => {
- db.collection('todos').updateOne({thing: request.body.itemFromJS},{
- $set: {
- completed: false
- }
- },{
- sort: {_id: -1},
- upsert: false
- })
- .then(result => {
- console.log('Marked Complete')
- response.json('Marked Complete')
- })
- .catch(error => console.error(error))
+// POST requests on the /addTodo route
+app.post("/addTodo", (request, response) => {
+ // to the db collection todos
+ db.collection("todos")
+ // insert one todo: thing comes from the request body "todoItem", and completed is set to false
+ .insertOne({ thing: request.body.todoItem, completed: false })
+ // after this is done
+ .then((result) => {
+ // log to the console
+ console.log("Todo Added");
+ // refresh the page to the root route
+ response.redirect("/");
+ })
+ // throw the error if we have one
+ .catch((error) => console.error(error));
+});
-})
+// a PUT request on the "mark complete route"
+app.put("/markComplete", (request, response) => {
+ // on the todos DB collection
+ db.collection("todos")
+ // update one item in the databse
+ .updateOne(
+ // get the item from the request body in the JS (comes from the client side code)
+ { thing: request.body.itemFromJS },
+ {
+ // set the completed field to true
+ $set: {
+ completed: true,
+ },
+ },
+ {
+ // move the item to the bottom of the list
+ sort: { _id: -1 },
+ // if this item doesn't exist, don't insert it
+ upsert: false,
+ }
+ )
+ // upon success
+ .then((result) => {
+ // log to to the console
+ console.log("Marked Complete");
+ // send a json response to the client that it was successful
+ response.json("Marked Complete");
+ })
+ // print the error if there is one
+ .catch((error) => console.error(error));
+});
-app.delete('/deleteItem', (request, response) => {
- db.collection('todos').deleteOne({thing: request.body.itemFromJS})
- .then(result => {
- console.log('Todo Deleted')
- response.json('Todo Deleted')
- })
- .catch(error => console.error(error))
+// a PUT request on the mark uncomplete route
+app.put("/markUnComplete", (request, response) => {
+ // on the todo database
+ db.collection("todos")
+ // update one item in the database
+ .updateOne(
+ // get the thing from the request body from the client JS
+ { thing: request.body.itemFromJS },
+ {
+ // set completed to false
+ $set: {
+ completed: false,
+ },
+ },
+ {
+ // sort to the bottom of the list
+ sort: { _id: -1 },
+ // don't insert this if it doesn't exist already
+ upsert: false,
+ }
+ )
+ .then((result) => {
+ // log to the console
+ console.log("Marked Complete");
+ // send a response back to the client that it's successful
+ response.json("Marked Complete");
+ })
+ // log the error
+ .catch((error) => console.error(error));
+});
-})
+// DELETE request on the deleteitem route
+app.delete("/deleteItem", (request, response) => {
+ // on the todos database
+ db.collection("todos")
+ // delete one item, based on the request body we get from the client side JS
+ .deleteOne({ thing: request.body.itemFromJS })
+ // upon success
+ .then((result) => {
+ // log to the console
+ console.log("Todo Deleted");
+ // send a response to the client
+ response.json("Todo Deleted");
+ })
+ // log the error if there is one
+ .catch((error) => console.error(error));
+});
-app.listen(process.env.PORT || PORT, ()=>{
- console.log(`Server running on port ${PORT}`)
-})
\ No newline at end of file
+// set the app to listen on the port set within the .env file
+app.listen(process.env.PORT || PORT, () => {
+ // log that the server is running
+ console.log(`Server running on port ${PORT}`);
+});
diff --git a/views/index.ejs b/views/index.ejs
index a26617ae..e4953e89 100644
--- a/views/index.ejs
+++ b/views/index.ejs
@@ -1,47 +1,57 @@
+
+
-
-
-
-
- Document
-
-
-
-
-
-
-
-
-
-
- Document
-
-
-