diff --git a/public/css/style.css b/public/css/style.css index 0475253a..fd62492f 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,7 +1,8 @@ -h1{ - color: red; +h1{ /* select all h1s */ + color: red; /* set the text to color red */ } -.completed{ - color: gray; - text-decoration: line-through; -} \ No newline at end of file +.completed{ /* select elements with class completed */ + color: gray; /* set text color to gray */ + text-decoration: line-through; /* set a strike-through decoration on the text */ +} + diff --git a/public/js/main.js b/public/js/main.js index ff0eac39..5d245338 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,72 +1,72 @@ -const deleteBtn = document.querySelectorAll('.fa-trash') -const item = document.querySelectorAll('.item span') -const itemCompleted = document.querySelectorAll('.item span.completed') +const deleteBtn = document.querySelectorAll('.fa-trash') //select all elements with a trashcan item and store them in a variable +const item = document.querySelectorAll('.item span') //select all spans that are general children of item class and store them in a variable +const itemCompleted = document.querySelectorAll('.item span.completed') //select all the spans with the completed class and store them in a variable -Array.from(deleteBtn).forEach((element)=>{ - element.addEventListener('click', deleteItem) +Array.from(deleteBtn).forEach((element)=>{ //loop through all spans with a delete variable and give them an event listener that runs a deleteItem function + element.addEventListener('click', deleteItem) //add a click event and the ability to run the delete function }) -Array.from(item).forEach((element)=>{ - element.addEventListener('click', markComplete) +Array.from(item).forEach((element)=>{ //loop through all todo items + element.addEventListener('click', markComplete) //add a click event listener to run a markComplete function to all todo items }) -Array.from(itemCompleted).forEach((element)=>{ - element.addEventListener('click', markUnComplete) +Array.from(itemCompleted).forEach((element)=>{ //loop through all items that are marked as compelte + element.addEventListener('click', markUnComplete) //add a click event listener to run a markUnComplete function }) -async function deleteItem(){ - const itemText = this.parentNode.childNodes[1].innerText +async function deleteItem(){ //declare an asyncronoys function caleld by the event listener + const itemText = this.parentNode.childNodes[1].innerText //grab the todo text by using the child node and the span name try{ - const response = await fetch('deleteItem', { - method: 'delete', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ - 'itemFromJS': itemText + const response = await fetch('deleteItem', { //make a fetch using the route deleteItem + method: 'delete', //perform a delete request + headers: {'Content-Type': 'application/json'}, //set up the content type as json + body: JSON.stringify({ //get the request ready as a json string + 'itemFromJS': itemText //send the todo item with the request with a property of itemFromJS }) }) - const data = await response.json() - console.log(data) - location.reload() + const data = await response.json() //grab the response and store it as data + console.log(data) //log to the console the data it grabbed from the server response + location.reload() //reload the page triggering the root get https requests allowing us to see the change from this event listener function - }catch(err){ - console.log(err) + }catch(err){ //listen for any errors + console.log(err) //when an error is heard log to the console the error msg } } -async function markComplete(){ - const itemText = this.parentNode.childNodes[1].innerText +async function markComplete(){ //set up an asyncronous function called by the event listener + const itemText = this.parentNode.childNodes[1].innerText //grab the todo text by using the child node try{ - const response = await fetch('markComplete', { - method: 'put', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ - 'itemFromJS': itemText + const response = await fetch('markComplete', { //make a fetch using the route markComplete + method: 'put', //create an update request + headers: {'Content-Type': 'application/json'}, //set the content type as json + body: JSON.stringify({ //get the request ready as a json string + 'itemFromJS': itemText //send the todo item with the request with a property of itemFromJS }) }) - const data = await response.json() - console.log(data) - location.reload() + const data = await response.json() //grab the response and store it as data + console.log(data) //log to the console the data it grabbed from the server response + location.reload() //reload the page triggering the root get http request allowing us to see the change from this event listener function - }catch(err){ - console.log(err) + }catch(err){ //listen for any errors + console.log(err) //when an error is heard log to the console the error msg } } -async function markUnComplete(){ - const itemText = this.parentNode.childNodes[1].innerText +async function markUnComplete(){ //declare an asyncronous function that will be run by an even listener + const itemText = this.parentNode.childNodes[1].innerText //grab the todo text from the span in the ejs file using the parentNode selector and store it in a variable try{ - const response = await fetch('markUnComplete', { - method: 'put', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ - 'itemFromJS': itemText + const response = await fetch('markUnComplete', { //make a fetch request using the markUnComplete route + method: 'put', //set up the update http method + headers: {'Content-Type': 'application/json'}, //set up the content type as json + body: JSON.stringify({ //get the request ready as a json string + 'itemFromJS': itemText //send the todo item with the request as an object with the property of itemFromJS }) }) - const data = await response.json() - console.log(data) - location.reload() + const data = await response.json() //wait for the server response and store the response as data + console.log(data) //log the data response from the server to the console + location.reload() //reload the page triggering a get request for the root directory - }catch(err){ - console.log(err) + }catch(err){ //listen for any errors + console.log(err) //log the error to the console. } } \ No newline at end of file diff --git a/server.js b/server.js index 58b53e2f..fb4affb2 100644 --- a/server.js +++ b/server.js @@ -1,30 +1,35 @@ +//assign a variable to require express, allowing us to use it const express = require('express') +//assign a variable to the express function const app = express() +//assign a variable importing mongo db const MongoClient = require('mongodb').MongoClient +//hard coded port variable ther server can use to run the application const PORT = 2121 +//configure our ability to use the .env file require('dotenv').config() - +//create a db variable, create and assign a variable storing the mongo db connection string in the .env file, create and assin a database name to the db in mongo db let db, dbConnectionStr = process.env.DB_STRING, dbName = 'todo' - +//connect to the mongo db cluster using the db string 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()) + .then(client => { //wait for a successful db connection and pass data from the client + console.log(`Connected to ${dbName} Database`) //log to the console the name of the database used within mongo db + db = client.db(dbName) //assign the db variable to the database used within mongo db + }) +app.set('view engine', 'ejs') //set up the server to use the ejs teplate file +app.use(express.static('public')) //let express know to look in the public folder to serve up clien side files +app.use(express.urlencoded({ extended: true })) //sets up express to be able to read urls +app.use(express.json()) //sets up express to use json files -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 }) + +app.get('/',async (request, response)=>{ //begin an http read method with the '/' URL as an asyncronoys method and set up request and response parameters. + const todoItems = await db.collection('todos').find().toArray() //declare and wait to assign a constant variable grabbing data from the collection 'todos' and store in an array + const itemsLeft = await db.collection('todos').countDocuments({completed: false}) //decale and wait to assign a constant variable storing the count of objects in the 'todos' collection that have a key value of false + response.render('index.ejs', { items: todoItems, left: itemsLeft }) //respond to the read request by rendering the index.ejs template file with the key preoperty set to variable todoItems and set the key of left to the variable itemsLeft // db.collection('todos').find().toArray() // .then(data => { // db.collection('todos').countDocuments({completed: false}) @@ -35,59 +40,64 @@ 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('/') +app.post('/addTodo', (request, response) => { //begin an http create method with the '/addTodo' route and set up request/response parameters + db.collection('todos').insertOne({thing: request.body.todoItem, completed: false}) //reach into the 'todos' collection in the db and inster one record from a request form, filteting by the todoItem name and completed key + .then(result => { //once the todo item is succesfully inserted do the following + console.log('Todo Added') //log to the console that a todo was added + response.redirect('/') //respond to the client request by loading up the root directory showing the updated ejs html file }) - .catch(error => console.error(error)) + .catch(error => console.error(error)) //if an error occurs pass the error to the console }) -app.put('/markComplete', (request, response) => { - db.collection('todos').updateOne({thing: request.body.itemFromJS},{ - $set: { - completed: true +app.put('/markComplete', (request, response) => { //begin an http update method with the '/markComplete' route and set up request and response parameters + db.collection('todos').updateOne({thing: request.body.itemFromJS},{ //reach into the 'todos' collection and update one object when the item gets selected from the client side JS, filtering the name of the todo span + $set: { //select a key in the object + completed: true //change the key value to true } },{ - sort: {_id: -1}, - upsert: false + sort: {_id: -1}, //sort the updated object in descending order + upsert: false //do not insert object if the object doesnt already exist }) - .then(result => { - console.log('Marked Complete') - response.json('Marked Complete') + .then(result => { //once the update is successful do the following + console.log('Marked Complete') //log to the console that the todo was marked complete + response.json('Marked Complete') //respond to the client request with a json object letting them the to do was marked complete }) - .catch(error => console.error(error)) + .catch(error => console.error(error)) //if anything goes wrong pass the error to the console }) -app.put('/markUnComplete', (request, response) => { - db.collection('todos').updateOne({thing: request.body.itemFromJS},{ - $set: { - completed: false +app.put('/markUnComplete', (request, response) => { //begin an http update method once the /markUnComplete route is passed and set up request/response parameters + db.collection('todos').updateOne({thing: request.body.itemFromJS},{ //reach into the 'todos' collection in the db and update one object when the item is clicked in the client side JS. Filter by the name of the todo span + $set: { //select a key in the object + completed: false //change the complete key to false } },{ - sort: {_id: -1}, - upsert: false + sort: {_id: -1}, //sort the updated object in descending order + upsert: false //do not insert object if the object doesnt already exist }) - .then(result => { - console.log('Marked Complete') - response.json('Marked Complete') + .then(result => { //once the update is successful do the following + console.log('Marked Uncomplete') //log to the console that the todo was marked again + response.json('Marked Uncomplete') //responde to the cliens request with a json object telling them the todo was marked }) - .catch(error => console.error(error)) + .catch(error => console.error(error)) //if there is an error pass the error to the conosle }) - +//we use the express method .delete() to initiate a delete request/response using the /deleteItem URL app.delete('/deleteItem', (request, response) => { +//go into the database called todo and the collection called todos. Delete one document filtering by the this key property of 'thing' from the form body. db.collection('todos').deleteOne({thing: request.body.itemFromJS}) +//once the deletion is succesful console log a confimration of deletion .then(result => { console.log('Todo Deleted') +//respond to the user that a todo was deleted response.json('Todo Deleted') }) +//if any errors occur log the error .catch(error => console.error(error)) }) - +//the server listens to a PORT defined in the .env file or a port declared within the server app.listen(process.env.PORT || PORT, ()=>{ +//log to the console a message indicating the port the server is running on console.log(`Server running on port ${PORT}`) }) \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs index a26617ae..4a800ab4 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -26,7 +26,7 @@ <%= items[i].thing %> <% }else{ %> <%= items[i].thing %> - <% } %> + <% } %> <% } %>