Skip to content

Commit 7c517c1

Browse files
committed
Implement CRUD functionality for Categories and Articles section, express-validator with custom message on form entry errors implemented.
1 parent 3cd1c1c commit 7c517c1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+7713
-537
lines changed

05_Sports_Blog/.vscode/settings.json

Lines changed: 0 additions & 3 deletions
This file was deleted.

05_Sports_Blog/README.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
# Sports Blog
22

3-
>## Sports Blog Demo - Web View
3+
> ## Sports Blog Demo - Web View
44
55
![](demo.gif)
66

7-
8-
>## Mobile View
7+
> ## Mobile View
98
109
![](mobile.gif)
1110

12-
1311
## 05_01 Project Intro
1412

1513
- We will create a Sports Blog with full CRUD functionality. We will use mongoose this time around. It is another method of connecting to MongoDB, and is more advanced than standard MongoDB driver which we used in last project of TODO App. It's more efficient, advanced and sort of more intuitive to connect to NoSQL DB.
14+
1615
- Functionality also includes visitors being able to post comments on every blog post.
16+
1717
- We have category sort available as well on blog. Where users can sort as per their choice.
18+
1819
- Admin features such as being able to add and remove categories along with notification messages whenever there is some edit done.
20+
1921
- Same functionality available to manage articles also available.
22+
2023
- Use of data and time formatter to present Data, Time in a more clean manner.
24+
2125
- Form validation as well.
26+
2227
- Run MongoDB in docker using `sudo docker run -d -p 27017:27017 -v ~/data:/data/db mongo`, visit [this](https://www.thachmai.info/2015/04/30/running-mongodb-container/) for detailed info.
2328

2429
- Or you can do this to remove related to mongoDB if you have any, I'd recommend Docker:
@@ -36,29 +41,30 @@ sudo apt install mongodb
3641
sudo service mongodb start
3742
mongo
3843
sudo service mongodb stop
39-
```
44+
```
4045

4146
## Tools/Technologies Used
4247

4348
- Mongoose ODM (Object Document Mapper) - Models & Schemas
4449
- Multiple Collections (articles and categories)
4550
- Express Messages & Validator, Sessions
4651
- Working with advanced Pug Layouts
47-
- Express Router
52+
- Express Router, with routes on separate files. We set up everything from scratch.
4853

4954
## 05_02 Mongoose ODM (Object Document Mapper)
5055

5156
- **Mongoose**: A more powerful way to work with Node and MongoDB. ODM is similar to an Object Relational Mapper which we get in relational databases.
5257
- It is an elegant object modelling package for Node and allows us to easily create CRUD apps.
5358
- Mongoose also includes things like type casting, validation, query building, hooks, etc.
5459
- Mongoose uses models to represent documents that can be saved and fetched from the database.
55-
- Mongoose models must have a schema, which is used to define attributes for documents.
60+
- Mongoose models must have a schema, which is used to define attributes for documents.
5661
- Methods can also be defined on mongoose schemas.
5762
- **Allowed Schema Types**: String, Number, Data, Buffer, Boolean, Mixed, ObjectID, Array.
5863

5964
## 05_03 App Middleware Setup
6065

6166
- We will proceed in same manner as we did for **PC Repair** website such as using external routing files, Pug template engine, but this time we won't use express generator, rather we will set everything up from scratch and create our own app.js file as this gives us less limitations and more flexibility while setting up our project.
67+
6268
- We have a lot more dependencies for this app. So instead of doing npm install --save, we will directly put all of our requirements in package.json file so that we can just run npm install and it will set it up everything in one go.
6369

6470
- See the docs for express-messages and validator on these links: [Validator](https://express-validator.github.io/docs/), [messages](https://github.com/visionmedia/express-messages)
@@ -77,9 +83,11 @@ sudo service mongodb stop
7783

7884
## 05_05 Fetching Categories and Working with Mongoose
7985

80-
- Create db and add categories using the following
86+
- Create db and add categories using the following, db.createCollection docs [here](https://docs.mongodb.com/manual/reference/method/db.createCollection/)
8187

82-
```
88+
![](https://i.imgur.com/rV5Ek63.png)
89+
90+
```sql
8391
use sportsblog
8492
db.createCollection('categories')
8593
db.createCollection('articles')
@@ -89,6 +97,7 @@ db.categories.insert({title:'Football','description':'These are Football article
8997
db.categories.insert({title:'Cricket','description':'These are Cricket articles.'})
9098
db.categories.find()
9199
```
100+
92101
- Now we have 4 categories in our DB, next want to fetch these categories using Mongoose. In Mongoose we deal with models, create a directory called models and inside it create a file called `category.js`. We try keeping everything encapsulated inside module.
93102
- To connect to mongoose, we go to app.js and define the required methods. After doing mongoose.connection go to `routes/categories.js` and bring up Category model. Now on visiting localhost:5000/categories you would see all the categories and description in the console. Next we want to take those categories and pass them into our template of categories page.
94103
- Next we work on implementing functionality for `/manage/categories/add` route using a form we would be able to add new categories.
@@ -149,7 +158,7 @@ db.categories.find()
149158

150159
## 05_10 Messages
151160

152-
- To show a message we can see that in the route /manage/categories when we add something and do a res.redirect, before that we can send a flash message. We can do so by entering the following `req.flash('Success', 'Added To Category')` after that we go to app.js and setup connect-flash and we use a variable globally called messages which we may use in our templates to show messages. So we should add the message in `/manage/categories/` route as that's where we will be redirected once we submit the request successfully. Make some changes to style.css and messages will work on your page.
161+
- To show a message we can see that in the route /manage/categories when we add something and do a res.redirect, before that we can send a flash message. We can do so by entering the following `req.flash('Success', 'Added To Category')` after that we go to app.js and setup connect-flash and we use a variable globally called messages which we may use in our templates to show messages. So we should add the message in `/manage/categories/` route as that's where we will be redirected once we submit the request successfully. Make some changes to style.css and messages will work on your page.
153162
- On adding articles also we want the same effect, so we go to articles.js and before the redirect request we do the same as we did for categories.
154163
- With messages showing up on Add and Edit for category and articles we are done with admin side or things related to controlling the content on the site.
155164

05_Sports_Blog/sportsblog/app.js

Lines changed: 31 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
const express = require('express')
22
const path = require('path')
3-
const bodyParser = require('body-parser')
43
const session = require('express-session')
54
const mongoose = require('mongoose')
6-
// const expressValidator = require('express-validator')
7-
8-
const {
9-
check,
10-
validationResult
11-
} = require('express-validator')
125

136
// Mongoose connect
14-
157
mongoose.connect('mongodb://localhost:27017/sportsblog', {
168
useNewUrlParser: true,
179
useUnifiedTopology: true
@@ -20,59 +12,50 @@ const db = mongoose.connection
2012

2113

2214
// Port
23-
const port = 5000
15+
const port = 3000;
2416

25-
// init app
26-
const app = express()
27-
28-
// Moment for Date and Time
17+
var app = express();
2918
app.locals.moment = require('moment')
3019

31-
// Routes
32-
33-
const index = require('./routes/index')
34-
const articles = require('./routes/articles')
35-
const categories = require('./routes/categories')
36-
const manage = require('./routes/manage')
20+
app.use(session({ cookie: { maxAge: 60000 },
21+
secret: 'woot',
22+
resave: false,
23+
saveUninitialized: false}));
24+
// Views dir setup
3725

38-
// View setup
39-
app.set('views', path.join(__dirname, 'views'))
40-
app.set('view engine', 'pug')
26+
app.set('views',path.join(__dirname,'views'));
27+
app.set('view engine','pug');
4128

42-
// BodyParser middleware
43-
app.use(bodyParser.json())
44-
app.use(bodyParser.urlencoded({
45-
extended: false
46-
}))
29+
// More on how body-parser or express parsing capability works https://www.geeksforgeeks.org/body-parser-middleware-in-node-js/
4730

48-
// Express session
31+
app.use(express.json());
32+
app.use(express.urlencoded({extended: false}));
4933

50-
app.use(session({
51-
secret: 'secret',
52-
resave: false,
53-
saveUninitialized: true
54-
}))
34+
// Set static dir
5535

36+
app.use(express.static(path.join(__dirname,'public')))
5637

57-
// Set static folder
58-
app.use(express.static(path.join(__dirname, 'public')))
38+
// Middleware for express messages
5939

60-
// See docs for express messages and validator github.com/expressjs/express-messages ver: Express3+
61-
app.use(require('connect-flash')())
40+
app.use(require('connect-flash')());
6241
app.use((req, res, next) => {
63-
res.locals.messages = require('express-messages')(req, res)
64-
next()
65-
})
42+
res.locals.messages = require('express-messages')(req, res);
43+
next();
44+
});
6645

67-
app.use(express.json());
68-
app.use('/', index)
69-
app.use('/articles', articles)
70-
app.use('/categories', categories)
71-
app.use('/manage', manage)
46+
const index = require('./routes/index')
47+
const categories = require('./routes/categories')
48+
const manage = require('./routes/manage')
49+
const articles = require('./routes/articles')
7250

51+
// -x-x-x-x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x--x-x-
7352

53+
app.use('/', index);
54+
app.use('/articles', articles);
55+
app.use('/categories', categories);
56+
app.use('/manage', manage);
7457

7558

76-
app.listen(port, '0.0.0.0', () => {
77-
console.log('Server started on port: ' + port)
78-
})
59+
app.listen(port, () => {
60+
console.info(`Server started on port ${port} ✅ 🚀`);
61+
});

05_Sports_Blog/sportsblog/models/article.js

Lines changed: 16 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,22 @@ const mongoose = require('mongoose')
33
// Article Schema - Title, Subtitle, Category, Body, Author, Created_At
44

55
const articleSchema = mongoose.Schema({
6-
title: {
7-
type: String
8-
},
9-
subtitle: {
10-
type: String
11-
},
12-
category: {
13-
type: String
14-
},
15-
body: {
16-
type: String
17-
},
18-
author: {
19-
type: String
20-
},
21-
created_at: {
22-
type: Date,
23-
default: Date.now,
24-
},
25-
comments: [{
26-
comment_subject: {
27-
type: String
28-
},
29-
comment_body: {
30-
type: String
31-
},
32-
comment_author: {
33-
type: String
34-
},
35-
comment_email: {
36-
type: String
37-
},
38-
comment_date: {
39-
type: String
6+
title: {type: String},
7+
subtitle: { type: String },
8+
category: {type: String},
9+
body: {type: String},
10+
author: {type: String},
11+
created_at: {type: Date,default: Date.now},
12+
13+
comments: [
14+
{
15+
comment_subject: {type: String},
16+
comment_body: {type: String},
17+
comment_author: {type: String},
18+
comment_email: {type: String},
19+
comment_date: {type: String}
4020
}
41-
42-
}]
21+
]
4322
})
4423

4524

@@ -57,17 +36,14 @@ module.exports.getArticles = function (callback, limit) {
5736
}
5837

5938
// Add Article
60-
6139
module.exports.addArticle = function (article, callback) {
6240
Article.create(article, callback)
6341
}
6442

6543
// Get Article By Category
6644

6745
module.exports.getCategoryArticles = function (categoryId, callback) {
68-
let query = {
69-
category: categoryId
70-
}
46+
let query = {category: categoryId}
7147
Article.find(query, callback).sort([
7248
['title', 'ascending']
7349
])
@@ -86,13 +62,11 @@ module.exports.updateArticle = function (query, update, options, callback) {
8662
}
8763

8864
// Remove article
89-
9065
module.exports.removeArticle = function (query, callback) {
9166
Article.deleteOne(query, callback)
9267
}
9368

9469
// Create Method for Comment
95-
9670
module.exports.addComment = function (query, comment, callback) {
9771
Article.updateOne(query, {
9872
$push: {

05_Sports_Blog/sportsblog/models/category.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,30 @@
1-
const mongoose = require('mongoose')
1+
// Contains all models related to category
22

3-
// Category Schema
3+
// Bring in mongoose
4+
const mongoose = require('mongoose')
45

56
const categorySchema = mongoose.Schema({
6-
title: {
7-
type: String
8-
},
9-
description: {
10-
type: String
11-
}
7+
title: {type: String},
8+
description: {type:String}
129
})
1310

14-
// Category will allow access outside the file.
15-
const Category = module.exports = mongoose.model('Category', categorySchema);
11+
// Allows access from outside when we export
12+
const Category = module.exports = mongoose.model('Category',categorySchema)
13+
14+
// Functions that we can reference related to database can be kept here as well.
1615

17-
// We try to keep everything encapsulated inside the module.
16+
// Get Categories
1817

19-
module.exports.getCategories = function (callback, limit) {
20-
Category.find(callback).limit(limit).sort([
21-
['title', 'ascending']
22-
])
18+
module.exports.getCategories = function(callback,limit){
19+
Category.find(callback).limit(limit).sort([['title','ascending']]);
2320
}
2421

2522
// Add category
26-
2723
module.exports.addCategory = function (category, callback) {
2824
Category.create(category, callback)
2925
}
3026

3127
// Get Single Category by its ID
32-
3328
module.exports.getCategoryById = function (id, callback) { // We can directly do callById outside as well, but we are sticking to encapsulating stuff
3429
Category.findById(id, callback) // Mongoose method
3530
}

0 commit comments

Comments
 (0)