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

A commented todo list along with link to slides #25

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
8 changes: 5 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"editor.fontSize": 38,
"terminal.integrated.fontSize": 60
}
"editor.fontSize": 14,
"terminal.integrated.fontSize": 14
}

// we can keep our vs code settings
7 changes: 6 additions & 1 deletion config/database.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// using mongoose to make a connection to mongo db
const mongoose = require('mongoose')

// this const exports an async funtion which we call in our server JS -- connect DB
const connectDB = async () => {
try {
try { //familiar db string that is housed in the env
const conn = await mongoose.connect(process.env.DB_STRING, {
useNewUrlParser: true,
useUnifiedTopology: true,
Expand All @@ -16,3 +18,6 @@ const connectDB = async () => {
}

module.exports = connectDB


//environment variables are stored in the config folder
6 changes: 6 additions & 0 deletions controllers/home.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
//home controller that spits out an object that spits out a method
//why is it a method? we set getIndex equal to a function -- remember objects have certain properties and methods that we can define
// were putting our objects into their own folders and our functions into their own folders

module.exports = {
//this renders our ejs -- gives us our html
getIndex: (req,res)=>{
//responds that html back to the browser to answer the users initial request
res.render('index.ejs')
}
}
16 changes: 16 additions & 0 deletions controllers/todos.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
// this is the model -- and the controller is the only thing that talks to it
const Todo = require('../models/Todo')

//spits out an object with 5 methods
module.exports = {
//method gets run by the todo routes -- we use the getTodos method from the todoController
getTodos: async (req,res)=>{
try{
//the consts are accessing the database -- the todo variable is requiring the todo model
//mongoose already returns our array of objects without having to use toArray
const todoItems = await Todo.find()
//we count how many object we have left to (completed=false)
const itemsLeft = await Todo.countDocuments({completed: false})
//response with the EJS HTML
res.render('todos.ejs', {todos: todoItems, left: itemsLeft})
}catch(err){
console.log(err)
}
},
//method that creates a new todo using the Todo model
createTodo: async (req, res)=>{
try{
//create is analogous to createOne --> todoItem is present in the ejs forms under Name
await Todo.create({todo: req.body.todoItem, completed: false})
console.log('Todo has been added!')
//make a get request and reload to the main page -- todo
//why is this not jsut / --> because we are not on the main route -- so we make sure to not send them back to the main page but rather keep them on the todo page
res.redirect('/todos')
}catch(err){
console.log(err)
}
},

// method that runs in response to the controller
markComplete: async (req, res)=>{
try{
await Todo.findOneAndUpdate({_id:req.body.todoIdFromJSFile},{
//set complete to true which activated the css stylings
completed: true
})
console.log('Marked Complete')
Expand All @@ -41,9 +55,11 @@ module.exports = {
console.log(err)
}
},

deleteTodo: async (req, res)=>{
console.log(req.body.todoIdFromJSFile)
try{
// hey model find one and delete to dinf the todoId from the main js file -- utilizing the unique id given to the dang thing from the ejs
await Todo.findOneAndDelete({_id:req.body.todoIdFromJSFile})
console.log('Deleted Todo')
res.json('Deleted It')
Expand Down
5 changes: 5 additions & 0 deletions models/Todo.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
//mongoose to talk to the db
const mongoose = require('mongoose')

//this sets a structure for our data as it goes in and out of our DB
const TodoSchema = new mongoose.Schema({
// sets todo as a string and makes it required
todo: {
type: String,
required: true,
},
//sets completed as a booleana nd makes it required
completed: {
type: Boolean,
required: true,
}
})

//exporting the model
module.exports = mongoose.model('Todo', TodoSchema)
3 changes: 3 additions & 0 deletions public/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Array.from(todoComplete).forEach((el)=>{
})

async function deleteTodo(){
//data set grabs any data attributes.. if in the ejs the data attribute was set to butt (data-butt='<%=el._id%>') then this would say dataset.butt
const todoId = this.parentNode.dataset.id
try{
const response = await fetch('todos/deleteTodo', {
Expand All @@ -33,8 +34,10 @@ async function deleteTodo(){
}

async function markComplete(){
// if you have two identical items in your list this will only update the one you click one because of that unique id
const todoId = this.parentNode.dataset.id
try{
// todos route -> markComplete
const response = await fetch('todos/markComplete', {
method: 'put',
headers: {'Content-type': 'application/json'},
Expand Down
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h1>Link to slides</h1>
https://docs.google.com/presentation/d/12jnJlGOn6UT11QCQOOrKS2HG-lohlpPiX6J0ynTnzKo/edit?usp=sharing
3 changes: 3 additions & 0 deletions routes/home.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// we only doing one thing -- files sees the route and tells what controller handles the request
const express = require('express')
const router = express.Router()
const homeController = require('../controllers/home')

// the controller that handles the request -- handles our home/main pages
// determines that requests made on the main router are set to the home controller using the getIndex method of the home controller
router.get('/', homeController.getIndex)

module.exports = router
5 changes: 5 additions & 0 deletions routes/todos.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
// because we already are on the todos route -- we dont have to specify todos/ and todos/createTodo -- by linking the actual routes file in the server.js -- saves us time and code

const express = require('express')
const router = express.Router()
const todosController = require('../controllers/todos')

// once we are on the main route we use the todos controller -- go to the todocontroller and run gettodos -- an async request -> this is the getTodos method stored in the controller
router.get('/', todosController.getTodos)

//createTodo post fromt the EJS got sent through the router
router.post('/createTodo', todosController.createTodo)

//go to controller and use the markcomplete method
router.put('/markComplete', todosController.markComplete)

router.put('/markIncomplete', todosController.markIncomplete)
Expand Down
16 changes: 14 additions & 2 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
const express = require('express')
const app = express()
// we require our config folder which houses our database file
const connectDB = require('./config/database')

// our routes look at the request (see the url) and figure out which controller should handle that request
const homeRoutes = require('./routes/home')
const todoRoutes = require('./routes/todos')

require('dotenv').config({path: './config/.env'})

//uses the code in our database js -- this allows us to potentially use a different database
connectDB()

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

//beginning of our router -- whenever theres a request on the main route the routes home js file will handle it
app.use('/', homeRoutes)

//beginnnig of the router whenever we click the make a todo list link from the main page -- made by clicking the link in the homepage
// when it hears a todo rout we use the todoRoutes file -- definted in the const above
app.use('/todos', todoRoutes)



// PORT is not defined in this file -- that is in the environment files -- this is an example of ABSTRACTION
app.listen(process.env.PORT, ()=>{
console.log('Server is running, you better catch it!')
})
})

// if you try to run this code, will it run? no. because you dont have access to the env
3 changes: 3 additions & 0 deletions views/todos.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
<h1>Todos</h1>
<ul>
<% todos.forEach( el => { %>
<!-- we use the random _id that gets made with each object in the DB. Each li gets that ._id as a class. so now every new li is unique -->
<!-- id's are really used for keeping track of things such as assigning each post to a user -->
<li class='todoItem' data-id='<%=el._id%>'>
<span class='<%= el.completed === true ? 'completed' : 'not'%>'><%= el.todo %></span>
<span class='del'> Delete </span>
Expand All @@ -20,6 +22,7 @@

<h2>Things left to do: <%= left %></h2>

<!-- action with todos/createTodo and make a post request when we submit to the post reuest to todos router -->
<form action="/todos/createTodo" method='POST'>
<input type="text" placeholder="Enter Todo Item" name='todoItem'>
<input type="submit">
Expand Down