diff --git a/public/js/main.js b/public/js/main.js index ff0eac39..40cca85d 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,22 +1,33 @@ +// declare variable for delete button const deleteBtn = document.querySelectorAll('.fa-trash') + +// declare variable for todo item (span elements within a parent class of item) const item = document.querySelectorAll('.item span') + +// declare variable for completed items const itemCompleted = document.querySelectorAll('.item span.completed') +// listen to delete item clicks Array.from(deleteBtn).forEach((element)=>{ element.addEventListener('click', deleteItem) }) +// listen to todo item clicks Array.from(item).forEach((element)=>{ element.addEventListener('click', markComplete) }) +// listen to 'completed' class clicks Array.from(itemCompleted).forEach((element)=>{ element.addEventListener('click', markUnComplete) }) +//when delete item is clicked, get text from the list item async function deleteItem(){ const itemText = this.parentNode.childNodes[1].innerText try{ + + //label list item text as "itemFromJS" and make a delete request to the server with the route '/deleteItem' const response = await fetch('deleteItem', { method: 'delete', headers: {'Content-Type': 'application/json'}, @@ -24,6 +35,8 @@ async function deleteItem(){ 'itemFromJS': itemText }) }) + + //when server responds, the data will be console logged and the page will refresh const data = await response.json() console.log(data) location.reload() @@ -33,9 +46,12 @@ async function deleteItem(){ } } +//when item is marked as complete, get text from the list item async function markComplete(){ const itemText = this.parentNode.childNodes[1].innerText try{ + + //label list item text as "itemFromJS" and make a put request to the server with the route '/markComplete' const response = await fetch('markComplete', { method: 'put', headers: {'Content-Type': 'application/json'}, @@ -43,6 +59,8 @@ async function markComplete(){ 'itemFromJS': itemText }) }) + + //when server responds, the data will be console logged and the page will refresh const data = await response.json() console.log(data) location.reload() @@ -52,9 +70,12 @@ async function markComplete(){ } } +//when item is marked as incomplete, get text from the list item async function markUnComplete(){ const itemText = this.parentNode.childNodes[1].innerText try{ + + //label list item text as "itemFromJS" and make a put request to the server with the route '/markUnComplete' const response = await fetch('markUnComplete', { method: 'put', headers: {'Content-Type': 'application/json'}, @@ -62,6 +83,8 @@ async function markUnComplete(){ 'itemFromJS': itemText }) }) + + //when server responds, the data will be console logged and the page will refresh const data = await response.json() console.log(data) location.reload() diff --git a/server.js b/server.js index 58b53e2f..f331cfe1 100644 --- a/server.js +++ b/server.js @@ -1,41 +1,64 @@ -const express = require('express') +//imports express framework +const express = require('express') const app = express() -const MongoClient = require('mongodb').MongoClient -const PORT = 2121 -require('dotenv').config() +//imports MongoDB module +const MongoClient = require('mongodb').MongoClient +//hardcode port to local server +const PORT = 2121 + +// loads environmental variables from a .env file. Allows secret keys to be stored in .env file +require('dotenv').config() + +// declares variables needed to connect to MongoDB, including the connection string (in .env file as "DB_String") and database name let db, - dbConnectionStr = process.env.DB_STRING, - dbName = 'todo' + dbConnectionStr = process.env.DB_STRING, + dbName = 'todo' //MongoDB database name +//connects to MongoDB using connection string and console logs result. 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()) +// sets template engine to EJS +app.set('view engine', 'ejs') + +//sets route for static files (CSS and JS). files stored in 'public' folder +app.use(express.static('public')) -app.get('/',async (request, response)=>{ +//will parse information from post and put requests +app.use(express.urlencoded({ extended: true })) + +// parses JSON data from request body and stores it in req.body +app.use(express.json()) + +//listen for request on homepage +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 }) - // db.collection('todos').find().toArray() - // .then(data => { - // db.collection('todos').countDocuments({completed: false}) - // .then(itemsLeft => { - // response.render('index.ejs', { items: data, left: itemsLeft }) - // }) - // }) - // .catch(error => console.error(error)) + + //finds all documents in the todo collection and put the documents into an array. + db.collection('todos').find().toArray() + + //the array will be held in the variable 'data' + .then(data => { + db.collection('todos').countDocuments({completed: false}) + .then(itemsLeft => { + //pass the data (array) into the ejs template. The data is given the name of items. + response.render('index.ejs', { items: data, left: itemsLeft }) + }) + }) + }) +//listens for post request from form with route '/addTodo' app.post('/addTodo', (request, response) => { + + //parses information in form, creates new database document, prints result, refreshes page, and catches errors db.collection('todos').insertOne({thing: request.body.todoItem, completed: false}) .then(result => { console.log('Todo Added') @@ -44,15 +67,25 @@ app.post('/addTodo', (request, response) => { .catch(error => console.error(error)) }) +//Listens for put request with the route of '/markComplete' app.put('/markComplete', (request, response) => { + + //updates database document that matches the text in itemFromJs db.collection('todos').updateOne({thing: request.body.itemFromJS},{ + + //updates completed property to true $set: { completed: true } },{ + //sorts completed list items to the bottom of the list sort: {_id: -1}, + + //sets upsert to false -- meaning no new document will be created if document isn't found upsert: false }) + + //respond to client side request and print result to the console .then(result => { console.log('Marked Complete') response.json('Marked Complete') @@ -61,15 +94,25 @@ app.put('/markComplete', (request, response) => { }) +//Listens for put request with the route of '/markUnComplete' app.put('/markUnComplete', (request, response) => { + + //update database document that matches the text in itemFromJs db.collection('todos').updateOne({thing: request.body.itemFromJS},{ + + //updates completed property to false $set: { completed: false } },{ + //sorts completed list items to the bottom of the list sort: {_id: -1}, + + //sets upsert to false -- meaning no new document will be created if document isn't found upsert: false }) + + //respond to client side request and print result to the console .then(result => { console.log('Marked Complete') response.json('Marked Complete') @@ -78,8 +121,14 @@ app.put('/markUnComplete', (request, response) => { }) + +//Listens for delete request with the route of '/deleteItem' app.delete('/deleteItem', (request, response) => { + + //deletes document that matches text in itemFromJS db.collection('todos').deleteOne({thing: request.body.itemFromJS}) + + //respond to client side request and print result to the console .then(result => { console.log('Todo Deleted') response.json('Todo Deleted') @@ -88,6 +137,8 @@ app.delete('/deleteItem', (request, response) => { }) + +//access port from environment variable or from port 2121 and print result to the console. app.listen(process.env.PORT || PORT, ()=>{ console.log(`Server running on port ${PORT}`) }) \ No newline at end of file