Skip to content

Commit acc14bb

Browse files
committed
Add comments to to-do list. Added .vscode to gitignore file. Updated README.md with project details
1 parent 8247adf commit acc14bb

File tree

6 files changed

+126
-69
lines changed

6 files changed

+126
-69
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
2-
.env
2+
.env
3+
.vscode

README.md

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,42 @@
1-
npm install
2-
add DB_STRING to .env file
1+
# todo-list - Express App
2+
3+
This is a simplified CRUD app for Todo List.
4+
It provides basic functionalities to manage to-do list items including add, delete, and update the status as complete or incomplete. The to-do list items are on a database on MongoDB Atlas for easy access.
5+
6+
## How It's Made:
7+
8+
**Tech used:** HTML, CSS, JavaScript, Node, Express, MongoDB Atlas
9+
10+
CRUD app created using Node, Express, MongoDB Atlas. The app functions include -- Create, Read, Update and Delete data that are on a MongoDB Atlas database using Node and Express.
11+
12+
## How to Use:
13+
14+
### Set up & Requirements to Play with it on your local machine
15+
16+
🔑 Clone this repo:
17+
18+
```clone git
19+
git clone https://github.com/100devs/todo-list-express.git
20+
```
21+
22+
🔑 To install requirements:
23+
24+
```
25+
mkdir todo-list
26+
cd todo-list
27+
npm init
28+
npm install express mongodb ejs dotenv --save
29+
```
30+
31+
🔑 Create `.env` file and add `DB_STRING` that is a Connection String to your MongoDB.
32+
For example,
33+
34+
```
35+
echo "DB_STRING = mongodb+srv://<your-user-id>:<your-password>@cluster0.example.mongodb.net/?retryWrites=true&w=majority" > .env
36+
```
37+
38+
**For more information, check out MongoDB Docs on [Connection Strings](https://www.mongodb.com/docs/manual/reference/connection-string/)**
39+
40+
## Lessons Learned:
41+
42+
Learned how to create a simple API that allows users to handle data on MongoDB via creating requests to Post, Get, Put, Delete via server and render results as HTML using EJS engine.

public/css/style.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
h1{
2-
color: red;
2+
color: red; /* set h1 text color to red */
33
}
44
.completed{
5-
color: gray;
6-
text-decoration: line-through;
5+
color: gray; /* turn the text color gray for the completed item*/
6+
text-decoration: line-through; /* strike through the completed item */
77
}

public/js/main.js

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,75 @@
1-
const deleteBtn = document.querySelectorAll('.fa-trash')
2-
const item = document.querySelectorAll('.item span')
3-
const itemCompleted = document.querySelectorAll('.item span.completed')
4-
1+
const deleteBtn = document.querySelectorAll('.fa-trash') // trash can icons
2+
const item = document.querySelectorAll('.item span') // select todo items
3+
const itemCompleted = document.querySelectorAll('.item span.completed') // select completed todo items
4+
// add event listener to trash can icons next to todo items. Click to Delete the todo item
55
Array.from(deleteBtn).forEach((element)=>{
66
element.addEventListener('click', deleteItem)
77
})
8-
8+
// add event listener todo items. Click to toggle complete/incomplete
99
Array.from(item).forEach((element)=>{
1010
element.addEventListener('click', markComplete)
1111
})
12-
12+
// add event listener to completed todo items next to todo items. Click to toggle complete/incomplete
1313
Array.from(itemCompleted).forEach((element)=>{
1414
element.addEventListener('click', markUnComplete)
1515
})
16-
16+
// Asynchronously delete an item
1717
async function deleteItem(){
18-
const itemText = this.parentNode.childNodes[1].innerText
18+
const itemText = this.parentNode.childNodes[1].innerText // Get the text content of the item to be deleted, that is the second child of the parent node
1919
try{
20+
// Send a delete request to the server with the itemText in its body
2021
const response = await fetch('deleteItem', {
2122
method: 'delete',
2223
headers: {'Content-Type': 'application/json'},
2324
body: JSON.stringify({
2425
'itemFromJS': itemText
2526
})
2627
})
27-
const data = await response.json()
28-
console.log(data)
29-
location.reload()
28+
const data = await response.json() // Parse the JSON response
29+
console.log(data) // Log the data
30+
location.reload() // reload page to render deletion
3031

3132
}catch(err){
32-
console.log(err)
33+
console.log(err) // Log any errors
3334
}
3435
}
35-
36+
// Asynchronously mark an item as completed
3637
async function markComplete(){
37-
const itemText = this.parentNode.childNodes[1].innerText
38+
const itemText = this.parentNode.childNodes[1].innerText // Get the text content of the todo item to mark complete
3839
try{
40+
// Send a put/update request to the server to mark the item complete with its itemText in its body
3941
const response = await fetch('markComplete', {
4042
method: 'put',
4143
headers: {'Content-Type': 'application/json'},
4244
body: JSON.stringify({
4345
'itemFromJS': itemText
4446
})
4547
})
46-
const data = await response.json()
47-
console.log(data)
48-
location.reload()
48+
const data = await response.json() // Parse the JSON response
49+
console.log(data) // Log the data
50+
location.reload() // reload page to render deletion
4951

5052
}catch(err){
51-
console.log(err)
53+
console.log(err) // Log any errors
5254
}
5355
}
54-
56+
// Asynchronously mark an item as incomplete
5557
async function markUnComplete(){
56-
const itemText = this.parentNode.childNodes[1].innerText
58+
const itemText = this.parentNode.childNodes[1].innerText // Get the text content of the todo item to unmark complete
5759
try{
60+
// Send a put/update request to the server to unmark the item complete with its itemText in its body
5861
const response = await fetch('markUnComplete', {
5962
method: 'put',
6063
headers: {'Content-Type': 'application/json'},
6164
body: JSON.stringify({
6265
'itemFromJS': itemText
6366
})
6467
})
65-
const data = await response.json()
66-
console.log(data)
67-
location.reload()
68+
const data = await response.json() // Parse the JSON response
69+
console.log(data) // Log the data
70+
location.reload() // reload page to render deletion
6871

6972
}catch(err){
70-
console.log(err)
73+
console.log(err) // Log any errors
7174
}
7275
}

server.js

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,101 @@
1+
// Load modules
12
const express = require('express')
23
const app = express()
34
const MongoClient = require('mongodb').MongoClient
45
const PORT = 2121
56
require('dotenv').config()
67

7-
8+
// initialize db related variables
89
let db,
910
dbConnectionStr = process.env.DB_STRING,
10-
dbName = 'todo'
11-
11+
dbName = 'todos'
12+
// MongoDB client setup
1213
MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true })
1314
.then(client => {
1415
console.log(`Connected to ${dbName} Database`)
1516
db = client.db(dbName)
1617
})
17-
18-
app.set('view engine', 'ejs')
19-
app.use(express.static('public'))
20-
app.use(express.urlencoded({ extended: true }))
21-
app.use(express.json())
18+
app.set('view engine', 'ejs') // set EJS as template engine
19+
app.use(express.static('public')) // server static from public folder
20+
app.use(express.urlencoded({ extended: true })) // Parse incoming requests with URL-encoded payloads
21+
app.use(express.json()) // Parse incoming requests with JSON payloads
2222

2323

24+
// CRUD - Read
25+
// 1. GET data from MongoDB
26+
// 2. Render the data in HTML with a template engine (ejs)
2427
app.get('/',async (request, response)=>{
25-
const todoItems = await db.collection('todos').find().toArray()
26-
const itemsLeft = await db.collection('todos').countDocuments({completed: false})
27-
response.render('index.ejs', { items: todoItems, left: itemsLeft })
28-
// db.collection('todos').find().toArray()
28+
// find all documents under the collection and return promise with the data
29+
const todoItems = await db.collection('todos').find().toArray() // find all docs and put them in an array `data`
30+
const itemsLeft = await db.collection('todos').countDocuments({completed: false}) // count documents with completed:false
31+
response.render('index.ejs', { items: todoItems, left: itemsLeft }) // data array passed to template as key-value pair(named 'items')
32+
// db.collection('todos').find().toArray()
2933
// .then(data => {
3034
// db.collection('todos').countDocuments({completed: false})
3135
// .then(itemsLeft => {
32-
// response.render('index.ejs', { items: data, left: itemsLeft })
36+
// response.render('index.ejs', { items: data, left: itemsLeft })
3337
// })
3438
// })
3539
// .catch(error => console.error(error))
3640
})
37-
41+
// CRUD - Create
42+
// 1. form submission triggers POST request to server
43+
// 2. refresh/get('/') with updated data from MongoDB
3844
app.post('/addTodo', (request, response) => {
39-
db.collection('todos').insertOne({thing: request.body.todoItem, completed: false})
45+
db.collection('todos').insertOne({thing: request.body.todoItem, completed: false}) // find 'todos' collection and insert the object to database. toDoItem is the body of input from the forms.
4046
.then(result => {
41-
console.log('Todo Added')
42-
response.redirect('/')
47+
console.log('Todo Added') // console log so we know this happened
48+
response.redirect('/') // response to refresh the page -> trigger get('/') req
4349
})
44-
.catch(error => console.error(error))
50+
.catch(error => console.error(error)) // catch and log error
4551
})
46-
52+
// CRUD - Update
53+
// 1. Update `completed` to true.
4754
app.put('/markComplete', (request, response) => {
4855
db.collection('todos').updateOne({thing: request.body.itemFromJS},{
4956
$set: {
50-
completed: true
57+
completed: true // notice set `true`
5158
}
5259
},{
53-
sort: {_id: -1},
54-
upsert: false
60+
sort: {_id: -1}, // descending order
61+
upsert: false // upsert: insert a document if no documents can be found
5562
})
5663
.then(result => {
57-
console.log('Marked Complete')
58-
response.json('Marked Complete')
64+
console.log('Marked Complete') // console log so we know this happened
65+
response.json('Marked Complete') // response to json
5966
})
60-
.catch(error => console.error(error))
67+
.catch(error => console.error(error)) // catch and log error
6168

6269
})
63-
70+
// CRUD - Update
71+
// 1. Update `completed` to false
6472
app.put('/markUnComplete', (request, response) => {
6573
db.collection('todos').updateOne({thing: request.body.itemFromJS},{
6674
$set: {
67-
completed: false
75+
completed: false // notice set `false`
6876
}
6977
},{
70-
sort: {_id: -1},
71-
upsert: false
78+
sort: {_id: -1}, // descending order
79+
upsert: false // upsert: insert a document if no documents can be found
7280
})
7381
.then(result => {
74-
console.log('Marked Complete')
75-
response.json('Marked Complete')
82+
console.log('Marked Complete') // console log so we know this happened
83+
response.json('Marked Complete') // response to json
7684
})
77-
.catch(error => console.error(error))
85+
.catch(error => console.error(error)) // catch and log error
7886

7987
})
8088

8189
app.delete('/deleteItem', (request, response) => {
8290
db.collection('todos').deleteOne({thing: request.body.itemFromJS})
8391
.then(result => {
84-
console.log('Todo Deleted')
85-
response.json('Todo Deleted')
92+
console.log('Todo Deleted') // console log so we know this happened
93+
response.json('Todo Deleted') // response to json
8694
})
87-
.catch(error => console.error(error))
95+
.catch(error => console.error(error)) // catch and log error
8896

8997
})
9098

9199
app.listen(process.env.PORT || PORT, ()=>{
92-
console.log(`Server running on port ${PORT}`)
100+
console.log(`Server running on port ${PORT}`) // so we know which server is running
93101
})

views/index.ejs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
<body>
2121
<h1>Todo List: </h1>
2222
<ul class="todoItems">
23-
<% for(let i=0; i < items.length; i++) {%>
23+
<!-- items hold array of objects from database passed from server.js-->
24+
<!-- for each item of items add to li and if completed is marked true, add `completed` class -->
25+
<!-- and add trash can icon as well -->
26+
27+
<% for(let i = 0; i < items.length; i++) {%>
2428
<li class="item">
2529
<% if(items[i].completed === true) {%>
2630
<span class='completed'><%= items[i].thing %></span>
@@ -34,8 +38,9 @@
3438

3539
<h2>Left to do: <%= left %></h2>
3640

37-
<h2>Add A Todo:</h2>
38-
41+
<h2>Add A Todo:</h2>
42+
43+
<!-- form to add todo item to database via Post req to server -->
3944
<form action="/addTodo" method="POST">
4045
<input type="text" placeholder="Thing To Do" name="todoItem">
4146
<input type="submit">

0 commit comments

Comments
 (0)