Skip to content
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
13 changes: 7 additions & 6 deletions public/css/style.css
Original file line number Diff line number Diff line change
@@ -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;
}
.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 */
}

90 changes: 45 additions & 45 deletions public/js/main.js
Original file line number Diff line number Diff line change
@@ -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.
}
}
96 changes: 53 additions & 43 deletions server.js
Original file line number Diff line number Diff line change
@@ -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})
Expand All @@ -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}`)
})
2 changes: 1 addition & 1 deletion views/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<span class='completed'><%= items[i].thing %></span>
<% }else{ %>
<span><%= items[i].thing %></span>
<% } %>
<% } %>
<span class='fa fa-trash'></span>
</li>
<% } %>
Expand Down