Skip to content

added clarifying comments for to do list #867

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

Open
wants to merge 2 commits 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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
node_modules
.env
.env
.DS_Store
.vscode
settings.json
9 changes: 5 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"editor.fontSize": 42,
"terminal.integrated.fontSize": 62
}
// commented out original code, which increases font size. would be in .gitignore
// {
// "editor.fontSize": 42,
// "terminal.integrated.fontSize": 62
// }
12 changes: 12 additions & 0 deletions public/js/main.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// variables for spans in the li
const deleteBtn = document.querySelectorAll('.fa-trash')
const item = document.querySelectorAll('.item span')
const itemCompleted = document.querySelectorAll('.item span.completed')

// 3 event listeners for each clickable span
Array.from(deleteBtn).forEach((element)=>{
element.addEventListener('click', deleteItem)
})
Expand Down Expand Up @@ -33,21 +35,28 @@ async function deleteItem(){
}
}

// these two functions link to the put update on server side
async function markComplete(){
// parent node is li and span is the childNode (things that take up space makes this text 1 instead of 0)
const itemText = this.parentNode.childNodes[1].innerText
try{
const response = await fetch('markComplete', {
method: 'put',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
// get task span
'itemFromJS': itemText
})
})
// request body included in form data
const data = await response.json()
// marked complete if successful
console.log(data)
// refresh page and trigger get request
location.reload()

}catch(err){
// give error if there is one
console.log(err)
}
}
Expand All @@ -59,14 +68,17 @@ async function markUnComplete(){
method: 'put',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
// get task span
'itemFromJS': itemText
})
})
const data = await response.json()
console.log(data)
// refresh page and trigger get request
location.reload()

}catch(err){
// give error if there is one
console.log(err)
}
}
128 changes: 82 additions & 46 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,93 +1,129 @@
// import Express module from Node.js package manager (npm)
const express = require('express')
// create an Express app
const app = express()
// import MongoDb package. MongoClient class allows connections to be made to MongoDB
const MongoClient = require('mongodb').MongoClient
// set endpoint for server, allowing it to listen for incoming client-side requests
const PORT = 2121
require('dotenv').config()


// initialize db (will assign value later when connecting to MongoDB database), dbConnectionStr (environment variable holding database connection string to connect to MongoDB database), and dbName (database name of 'todo') variables
let db,
dbConnectionStr = process.env.DB_STRING,
dbName = 'todo'

// connect to MongoDB database
MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true })
.then(client => {
//console log name of database once connected
console.log(`Connected to ${dbName} Database`)
// calls db() method on client object (usually MongoClient instance) and selects database by dbName. Assign matching object to db variable
db = client.db(dbName)
})
// set EJS (Embedded JavaScript) as the view engine in the express app
app.set('view engine', 'ejs')
// middleware: serve static files (images, css, javascript) in the public folder
app.use(express.static('public'))
// middleware: get data from request body, usually used for form submissions
app.use(express.urlencoded({ extended: true }))
// middleware: parse JSON from req.body into JavaScript object (useful if clients send JSON from APIs)
app.use(express.json())

// when making get request from root route...
app.get('/', async (request, response) => {
// async/await option
// 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)=>{
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))
// find collection called 'todos' in database and add documents to an array (which can hold objects)
db.collection('todos').find().toArray()
// pass resulting array into parameter data
.then(data => {
//
db.collection('todos').countDocuments({completed: false})
.then(itemsLeft => {
// data (items AKA objects in arr) passed into EJS
response.render('index.ejs', { items: data, left: itemsLeft })
})
})
.catch(error => console.error(error))
})

// when making post request (linked to 'addTodo' action on form that made post request) from addTodo route
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))
// grab value from request body containing todoItem, add to database and give completed value of false
db.collection('todos').insertOne({ thing: request.body.todoItem, completed: false })
.then(result => {
// console log for debugging
console.log('Todo Added')
// respond by refreshing & initiating get request
response.redirect('/')
})
// console log error if there is one
.catch(error => console.error(error))
})

// when making put request from markcomplete route (linked to 'markComplete' action on form)
app.put('/markComplete', (request, response) => {
db.collection('todos').updateOne({thing: request.body.itemFromJS},{
db.collection('todos').updateOne({ thing: request.body.itemFromJS }, {
// default is a false value for completed but this will now be set to true
$set: {
completed: true
}
},{
sort: {_id: -1},
}
}, {
sort: { _id: -1 },
// if true, updating something that wouldn't there creates document for you with value entered
upsert: false
})
.then(result => {
console.log('Marked Complete')
response.json('Marked Complete')
})
.catch(error => console.error(error))
// respond with 'marked completed' in console log and respond as json
.then(result => {
console.log('Marked Complete')
response.json('Marked Complete')
})
// return error if there is one
.catch(error => console.error(error))

})

// when making put request from markUncomplete route (inked to 'markUncomplete' action)
app.put('/markUnComplete', (request, response) => {
db.collection('todos').updateOne({thing: request.body.itemFromJS},{
db.collection('todos').updateOne({ thing: request.body.itemFromJS }, {
// set value for completed to false
$set: {
completed: false
}
},{
sort: {_id: -1},
}
}, {
sort: { _id: -1 },
// if true, updating something that wouldn't there creates document for you with value entered
upsert: false
})
.then(result => {
console.log('Marked Complete')
response.json('Marked Complete')
})
.catch(error => console.error(error))
.then(result => {
// respond with 'marked completed' in console log and respond as json
console.log('Marked Complete')
response.json('Marked Complete')
})
//return error if there is one
.catch(error => console.error(error))

})

// when making delete request from deleteItem route...
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))
// go to databas, find property with matching thing property, and delete
db.collection('todos').deleteOne({ thing: request.body.itemFromJS })
.then(result => {
// respond with todo deleted
console.log('Todo Deleted')
response.json('Todo Deleted')
})
// return error if there is one
.catch(error => console.error(error))

})

app.listen(process.env.PORT || PORT, ()=>{
// set up Express app to listen for requests on a specific port
// PORT variable is set by us but process.env.PORT is the PORT environment variable, which can be set on the server where the app is running (usually when deploying to another platform)
app.listen(process.env.PORT || PORT, () => {
console.log(`Server running on port ${PORT}`)
})
6 changes: 6 additions & 0 deletions views/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,19 @@
</head>
<body>
<h1>Todo List: </h1>
<!-- parent node -->
<ul class="todoItems">
<!-- iterating over array for num of items in array and increment by 1 -->
<% for(let i=0; i < items.length; i++) {%>
<li class="item">
<!-- items holds array of objects. if property is true then build span with completed class...-->
<% if(items[i].completed === true) {%>
<span class='completed'><%= items[i].thing %></span>
<% }else{ %>
<!-- otherwise render span without completed class -->
<span><%= items[i].thing %></span>
<% } %>
<!-- add trash can icon to the end of either span above -->
<span class='fa fa-trash'></span>
</li>
<% } %>
Expand All @@ -36,6 +41,7 @@

<h2>Add A Todo:</h2>

<!-- form action linked to post request -->
<form action="/addTodo" method="POST">
<input type="text" placeholder="Thing To Do" name="todoItem">
<input type="submit">
Expand Down