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
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"editor.fontSize": 42,
"terminal.integrated.fontSize": 62
"editor.fontSize": 14,
"terminal.integrated.fontSize": 14
}
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
npm install
add DB_STRING to .env file
add DB_STRING to .env file

---

[From crispyyychrisss at 100Devs:](https://discord.com/channels/735923219315425401/735923219315425406/1179285184504402011)

Also if anyone is struggling to make the terminal and editor font size smaller in the todo-list-express-main files just
1. click the gear icon in the bottom left corner in vs code (with the project folder open)
2. Click settings
3. Type in “@id:terminal.integrated.fontSize” to edit terminal font size or “@id:editor.fontSize” to edit editor font size
4. Click the Workspace tab right below the input where you just typed into in step 3
5. Type in your desired font size in the input box to the right
6. Yay
109 changes: 55 additions & 54 deletions public/js/main.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,73 @@
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') // grab all trash can icons (returns a NodeList)
const item = document.querySelectorAll('.item span') // grab all todo items (returns a NodeList)
const itemCompleted = document.querySelectorAll('.item span.completed') // grab all completed todo items (returns a NodeList)

Array.from(deleteBtn).forEach((element)=>{
element.addEventListener('click', deleteItem)

// convert NodeLists to arrays and add event listeners
Array.from(deleteBtn).forEach((element)=>{ // convert the NodeList of delete buttons to an array
element.addEventListener('click', deleteItem) // add a click event listener to each delete button that calls deleteItem
})

Array.from(item).forEach((element)=>{
element.addEventListener('click', markComplete)
Array.from(item).forEach((element)=>{ // convert the NodeList of todo items to an array
element.addEventListener('click', markComplete) // add a click event listener to each todo item that calls markComplete
})

Array.from(itemCompleted).forEach((element)=>{
element.addEventListener('click', markUnComplete)
Array.from(itemCompleted).forEach((element)=>{ // convert the NodeList of completed todo items to an array
element.addEventListener('click', markUnComplete) // add a click event listener to each completed todo item that calls markUnComplete
})

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

}catch(err){
console.log(err)
// async functions for handling the different actions
async function deleteItem(){ // event handler to delete a todo
const itemText = this.parentNode.childNodes[1].innerText // get the text of the todo item
try{ // try to delete the todo
const response = await fetch('deleteItem', { // make a request to the server to the /deleteItem route to delete the todo
method: 'delete', // use the DELETE method
headers: {'Content-Type': 'application/json'}, // set the content type to JSON
body: JSON.stringify({ // stringify the data to be sent
'itemFromJS': itemText // include the todo item text
})
})
const data = await response.json() // parse the response as JSON (get it & transform it)
console.log(data) // log the response data
location.reload() // reload the page (refresh)
}catch(err){ // if there's an error
console.log(err) // log the error
}
}

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
async function markComplete(){ // event handler to mark a todo as complete
const itemText = this.parentNode.childNodes[1].innerText // get the text of the todo item
try{ // try to mark the todo as complete
const response = await fetch('markComplete', { // make a request to the server to the /markComplete route to mark the todo as complete
method: 'put', // use the PUT method
headers: {'Content-Type': 'application/json'}, // set the content type to JSON
body: JSON.stringify({ // stringify the data to be sent
'itemFromJS': itemText // include the todo item text
})
})
const data = await response.json()
console.log(data)
location.reload()

}catch(err){
console.log(err)
})
const data = await response.json() // parse the response as JSON (get it & transform it)
console.log(data) // log the response data
location.reload() // reload the page (refresh)
}catch(err){ // if there's an error
console.log(err) // log the error
}
}

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
async function markUnComplete(){ // event handler to mark a todo as incomplete (same as above, but for uncompleting)
const itemText = this.parentNode.childNodes[1].innerText // get the text of the todo item
try{ // try to mark the todo as incomplete
const response = await fetch('markUnComplete', { // make a request to the server to the /markUnComplete route to mark the todo as incomplete
method: 'put', // use the PUT method
headers: {'Content-Type': 'application/json'}, // set the content type to JSON
body: JSON.stringify({ // stringify the data to be sent
'itemFromJS': itemText // include the todo item text
})
})
const data = await response.json()
console.log(data)
location.reload()

}catch(err){
console.log(err)
})
const data = await response.json() // parse the response as JSON
console.log(data) // log the response data
location.reload() // reload the page (refresh)
}catch(err){ // if there's an error
console.log(err) // log the error
}
}
120 changes: 62 additions & 58 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
const express = require('express')
const app = express()
const MongoClient = require('mongodb').MongoClient
const PORT = 2121
require('dotenv').config()

const express = require('express') // import express into the project
const app = express() // variable name to create an instance of express
const MongoClient = require('mongodb').MongoClient // import mongo db into the project
const PORT = 2121 // set the port for the server to listen for requests
require('dotenv').config() // import dotenv toload environment variables from .env file

// read db connection info from environment variables (db, donnection string)
// assign 'todo' to db name
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)
// connect to the db using Mongo instance (declared above)
MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true }) // connect to MongoDB
.then(client => { // take that connection & do something with it
console.log(`Connected to ${dbName} Database`) // log the connection
db = client.db(dbName) // assign the database to the db variable
})

app.set('view engine', 'ejs')
app.use(express.static('public'))
app.use(express.urlencoded({ extended: true }))
app.use(express.json())

app.set('view engine', 'ejs') // set the view engine (templating language) to ejs
app.use(express.static('public')) // telling express to serve static files from the 'public' directory
app.use(express.urlencoded({ extended: true })) // lets express read URLs & params
app.use(express.json()) // lets express parse JSON in the request body

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 })
// first route: get all todos and count the number of incomplete todos
app.get('/',async (request, response)=>{ // sets the path we're listening on to "/", makes it async & declares request & response arguments
const todoItems = await db.collection('todos').find().toArray() // get all todos from "todos" collection & converts them to an array (they're objects on Mongo)
const itemsLeft = await db.collection('todos').countDocuments({completed: false}) // gets all of the incomplete todos (the ones with completed: false)
response.render('index.ejs', { items: todoItems, left: itemsLeft }) // render the index.ejs template with the todo items and the number of incomplete items
// db.collection('todos').find().toArray()
// .then(data => {
// db.collection('todos').countDocuments({completed: false})
Expand All @@ -35,59 +37,61 @@ 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('/')
// 2nd route: add a new todo
app.post('/addTodo', (request, response) => { // listens for POST requests to the '/addTodo' endpoint
db.collection('todos').insertOne({thing: request.body.todoItem, completed: false}) // insert a new todo into the "todos" collection
.then(result => { // if the insertion is successful
console.log('Todo Added') // log a message to the console
response.redirect('/') // redirect the user to the home page (refresh the page)
})
.catch(error => console.error(error))
.catch(error => console.error(error)) // if there's an error, log it to the console
})

app.put('/markComplete', (request, response) => {
db.collection('todos').updateOne({thing: request.body.itemFromJS},{
$set: {
completed: true
}
// 3rd route: mark a todo as complete
app.put('/markComplete', (request, response) => { // listens for PUT requests to the '/markComplete' endpoint
db.collection('todos').updateOne({thing: request.body.itemFromJS},{ // update a todo in the "todos" collection, find it by its 'thing' field
$set: { // set the completed field to true
completed: true // mark the todo as complete
}
},{
sort: {_id: -1},
upsert: false
sort: {_id: -1}, // sort by _id in descending order
upsert: false // don't create a new document if this one doesn't exist
})
.then(result => {
console.log('Marked Complete')
response.json('Marked Complete')
.then(result => { // if the update is successful
console.log('Marked Complete') // log a message to the console
response.json('Marked Complete') // send a JSON response to close out the request
})
.catch(error => console.error(error))

.catch(error => console.error(error)) // if there's an error, log it to the console
})

app.put('/markUnComplete', (request, response) => {
db.collection('todos').updateOne({thing: request.body.itemFromJS},{
$set: {
completed: false
}
// 4th route: mark a todo as incomplete (same logic as marking complete, but the opposite)
app.put('/markUnComplete', (request, response) => { // listens for PUT requests to the '/markUnComplete' endpoint
db.collection('todos').updateOne({thing: request.body.itemFromJS},{ // update a todo in the "todos" collection, find it by its 'thing' field
$set: { // set the completed field to false
completed: false // mark the todo as incomplete
}
},{
sort: {_id: -1},
upsert: false
sort: {_id: -1}, // sort by _id in descending order
upsert: false // don't create a new document if this one doesn't exist
})
.then(result => {
console.log('Marked Complete')
response.json('Marked Complete')
.then(result => { // if the update is successful
console.log('Marked Complete') // log a message to the console
response.json('Marked Complete') // send a JSON response to close out the request
})
.catch(error => console.error(error))

.catch(error => console.error(error)) // if there's an error, log it to the console
})

app.delete('/deleteItem', (request, response) => {
db.collection('todos').deleteOne({thing: request.body.itemFromJS})
.then(result => {
console.log('Todo Deleted')
response.json('Todo Deleted')
// 5th route: delete a todo
app.delete('/deleteItem', (request, response) => { // listens for DELETE requests to the '/deleteItem' endpoint
db.collection('todos').deleteOne({thing: request.body.itemFromJS}) // delete a todo from the "todos" collection, find it by its 'thing' field
.then(result => { // if the deletion is successful
console.log('Todo Deleted') // log a message to the console
response.json('Todo Deleted') // send a JSON response to close out the request
})
.catch(error => console.error(error))

.catch(error => console.error(error)) // if there's an error, log it to the console
})

app.listen(process.env.PORT || PORT, ()=>{
console.log(`Server running on port ${PORT}`)
// Start the server, listen on the specified port (use the environment variable or the default port)
app.listen(process.env.PORT || PORT, ()=>{ // listen for incoming requests
console.log(`Server running on port ${PORT}`) // log a message to the console
})