Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class 41 HW: Commenting Todos #851

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions public/css/style.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
h1{
color: red;
}
.completed{
color: gray;
text-decoration: line-through;
}
h1{ /* selects the h1 tag in the ejs file and sets style properties for it */
color: red; /* makes the text color red */
} /* closes h1 tag selector */

.completed{ /* selects items with a class of completed in the ejs file */
color: gray; /* makes text color gray */
text-decoration: line-through; /* displays text with a strikethrough line */
} /* closes selector for this custom class */
127 changes: 63 additions & 64 deletions public/js/main.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,71 @@
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') /* stores all the delete icon elements from the dom into a variable */
const item = document.querySelectorAll('.item span') /* stores todo list items from the DOM into a variable */
const itemCompleted = document.querySelectorAll('.item span.completed') /* collects all the completed items from the DOM */

Array.from(deleteBtn).forEach((element)=>{
element.addEventListener('click', deleteItem)
})
Array.from(deleteBtn).forEach((element)=>{ /* creates an array from deleteBtn and loops through each element */
element.addEventListener('click', deleteItem) /* adds a click event listener and calls the deleteItem function */
}) /* closes for loop */

Array.from(item).forEach((element)=>{
element.addEventListener('click', markComplete)
})
Array.from(item).forEach((element)=>{ /* turns item into an array and loops through each element */
element.addEventListener('click', markComplete) /* adds an event listener for clicks and calls the markComplete function */
}) /* closes loop */

Array.from(itemCompleted).forEach((element)=>{
element.addEventListener('click', markUnComplete)
})
Array.from(itemCompleted).forEach((element)=>{ /* turns itemCompleted into an array and loops through each element */
element.addEventListener('click', markUnComplete) /* adds an event listener to each completed element and calls markUnComplete function */
}) /* closes loop */

async function deleteItem(){
const itemText = this.parentNode.childNodes[1].innerText
try{
const response = await fetch('deleteItem', {
method: 'delete',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
'itemFromJS': itemText
})
})
const data = await response.json()
console.log(data)
location.reload()
async function deleteItem(){ /* declares an async function */
const itemText = this.parentNode.childNodes[1].innerText /* looks in the list item and saves the todo item text in a variable */
try{ /* once a response is received run the try block */
const response = await fetch('deleteItem', { /* stores response for the deleteItem route in a variable */
method: 'delete', /* the CRUD operation used */
headers: {'Content-Type': 'application/json'}, /* specifies the content will be JSON format */
body: JSON.stringify({ /* convert the data into a string */
'itemFromJS': itemText /* storing the inner text of the todo item with a key of itemFromJS */
}) /* closing the body block */
}) /* closing the response object */
const data = await response.json() /* saving the server response as JSON */
console.log(data) /* print the promise to the console */
location.reload() /* refresh the page with the data received */

}catch(err){
console.log(err)
}
}
}catch(err){ /* retain any errors that occur into the catch block */
console.log(err) /* print those errors to the console */
} /* close error catch block */
} /* close async function block */

async function markComplete(){
const itemText = this.parentNode.childNodes[1].innerText
try{
const response = await fetch('markComplete', {
method: 'put',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
'itemFromJS': itemText
})
})
const data = await response.json()
console.log(data)
location.reload()
async function markComplete(){ /* declares an async function */
const itemText = this.parentNode.childNodes[1].innerText /* looks into the list item and saves the text in a variable */
try{ /* starting a try block */
const response = await fetch('markComplete', { /* stores fetch response for the markComplete route in a variable */
method: 'put', /* setting the CRUD method used */
headers: {'Content-Type': 'application/json'}, /* indicates the data format used (JSON) */
body: JSON.stringify({ /* turn the response into a string and storing it under a key of body */
'itemFromJS': itemText /* storing the actual text in a key that can be called */
}) /* closing the body object block */
}) /* closing the fetch response block */
const data = await response.json() /* saving the JSON confirmation of the update that we are waiting for */
console.log(data) /* printing the updated response to the console */
location.reload() /* refreshing the page with the updated response */
}catch(err){ /* save any errors and use in this catch block */
console.log(err) /* print errors to the console */
} /* close the catch block */
} /* close the async function block */

}catch(err){
console.log(err)
}
}
async function markUnComplete(){ /* declaring an async function */
const itemText = this.parentNode.childNodes[1].innerText /* looks into the list item span and saves the text in a variable */
try{ /* starting a try block */
const response = await fetch('markUnComplete', { /* saving the fetch response to the markUnComplete route as a variable */
method: 'put', /* sets the CRUD method to update */
headers: {'Content-Type': 'application/json'}, /* sets the content type as JSON */
body: JSON.stringify({ /* turn the JSON response into a string */
'itemFromJS': itemText /* save the string text in a key of itemFromJS */
}) /* close the body block */
}) /* close the object */
const data = await response.json() /* store the JSON message confirming the update in a variable */
console.log(data) /* print the result to the console */
location.reload() /* refresh the page with updated data displayed */

async function markUnComplete(){
const itemText = this.parentNode.childNodes[1].innerText
try{
const response = await fetch('markUnComplete', {
method: 'put',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
'itemFromJS': itemText
})
})
const data = await response.json()
console.log(data)
location.reload()

}catch(err){
console.log(err)
}
}
}catch(err){ /* save any errors that occur */
console.log(err) /* print those errors to the console */
} /* close catch block */
} /* close async function block */
146 changes: 72 additions & 74 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
const express = require('express')
const app = express()
const MongoClient = require('mongodb').MongoClient
const PORT = 2121
require('dotenv').config()
const express = require('express') // allows us to use express methods in this file
const app = express() // executes an instance of express in app variable
const MongoClient = require('mongodb').MongoClient // provides access to database methods (within MongoClient class) and to interact with MongoDB items
const PORT = 2121 // saves the port location where our server is listening
require('dotenv').config() // connects the .env file so we can use the database key/link without exposing our password.

let db, /* set up a variable for the database in the glocal scope */
dbConnectionStr = process.env.DB_STRING, /* store connection string from .env file in a variable */
dbName = 'todo' /* save the name of our database to pass along to MongoClient */

let db,
dbConnectionStr = process.env.DB_STRING,
dbName = 'todo'

MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true })
.then(client => {
console.log(`Connected to ${dbName} Database`)
db = client.db(dbName)
})
MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true }) /* connect to the MongoDB with the connection string & an additional property (using MongoDB driver's new connection management engine set to false by default). We are establishing a promise here */
.then(client => { /* pass in client information back to the server once we get a promise response (which confirms a connection) */
console.log(`Connected to ${dbName} Database`) /* use a template literal to print a confirmation message to console with the specific database name we created */
db = client.db(dbName) /* store the database information we are getting in an instance of the client factory method in a previously declared variable */
}) /* closing the .then */

app.set('view engine', 'ejs')
app.use(express.static('public'))
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
/* Middleware methods we are using: Express */
app.set('view engine', 'ejs') /* setting the ejs format as the default render to view our page */
app.use(express.static('public')) /* sets the default location folder for static assets like style.css and main.js */
app.use(express.urlencoded({ extended: true })) /* tells express to decode and encode url's where the header matched the content. Supports arrays and objects as well (extended) */
app.use(express.json()) /* replaces bodyparser; parses json content from incoming requests */


app.get('/',async (request, response)=>{ /* starts an asynchronous GET method when the root route is passed in, sets up request and response parameters */
const todoItems = await db.collection('todos').find().toArray() /* awaits and stores all items in the database todos collection in an array */
const itemsLeft = await db.collection('todos').countDocuments({completed: false}) /* awaits the number of uncompleted tasks and stores it */
response.render('index.ejs', { items: todoItems, left: itemsLeft }) /* send the items and the count in an object to the ejs file so it can be rendered correctly, and render the EJS file */

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})
Expand All @@ -35,59 +36,56 @@ 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.post('/addTodo', (request, response) => { /* uses an express POST method to create a new item using the route we are passing in from our EJS form */
db.collection('todos').insertOne({thing: request.body.todoItem, completed: false}) /* finds the todos collection in the database and inserts a new todo item with a completed property of false */
.then(result => { /* execute a response once we have confirmation that the item has been added */
console.log('Todo Added') /* print a confirmation message to the console */
response.redirect('/') /* respond by getting rid of the /addTodo route and then redirects to the root route, refreshing the page */
}) /* closing the then response actions */
.catch(error => console.error(error)) /* print errors to the console */
}) /* close the post action */

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('/markComplete', (request, response) => { /* starts an express PUT method to change the completion property of a todo item in the database using the /markComplete route */
db.collection('todos').updateOne({thing: request.body.itemFromJS},{ /* look in the database to find the todo passed in from main.js and then start a new object */
$set: { /* setting a property value */
completed: true /* change the completion status to true */
} /* close set block */
},{ /* start another object */
sort: {_id: -1}, /* moves item to the bottom of the list */
upsert: false /* says if item does not already exist then do not insert this one */
}) /* closes this collection of properties */
.then(result => { /* if the update was successful then execute this arrow function */
console.log('Marked Complete') /* print a confirmation message to the console that the update was successful */
response.json('Marked Complete') /* send a JSON message to the client side (main.js) that change was successful */
}) /* */
.catch(error => console.error(error)) /* an arrow function to print any errors to the console */
}) /* closes the PUT method block */

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))
app.put('/markUnComplete', (request, response) => { /* start a PUT method to update a todo item as an uncompleted task through the /markUnComplete route and then manage the request and response with an arrow function */
db.collection('todos').updateOne({thing: request.body.itemFromJS},{ /* find the todo item in the database and update it with the properties inside an object we are passing in here */
$set: { /* set a property */
completed: false /* set the completed property to a false value */
} /* close the set block */
},{ /* start an object with further properties to pass in */
sort: {_id: -1}, /* sort the todo item to be at the bottom of the list */
upsert: false /* if the item is not there, do not insert it */
}) /* close this set of properties */
.then(result => { /* attempt this arrow function if the update is suceessful */
console.log('Marked Uncomplete') /* print a completion message to the console */
response.json('Marked Uncomplete') /* send a JSON message back to the client indicating the update was successful */
}) /* close the then block */
.catch(error => console.error(error)) /* save and print any errors to our console */
}) /* close the PUT method */

})

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))

})
app.delete('/deleteItem', (request, response) => { /* start a DELETE method to handle the request and response triggered by the /deleteItem route */
db.collection('todos').deleteOne({thing: request.body.itemFromJS}) /* find the specific todo item in the database to delete */
.then(result => { /* if the delete is successful complete the actions in this arrow function */
console.log('Todo Deleted') /* print a confirmation message to the console that the delete was successful */
response.json('Todo Deleted') /* send a JSON message back to the client side confirming the delete was successful */
}) /* close the then block */
.catch(error => console.error(error)) /* save any errors and print them to the console */
}) /* close the DELETE method */

app.listen(process.env.PORT || PORT, ()=>{
console.log(`Server running on port ${PORT}`)
})
app.listen(process.env.PORT || PORT, ()=>{ /* listen for a connection to the database at this saved port or the port of the .env file or deployment engine and then run an anonymous function */
console.log(`Server running on port ${PORT}`) /* print confirmation message to the console indicating the port used */
}) /* close listen block */
Loading