Skip to content

Commit 58181c0

Browse files
committed
Add week 4 performance unzipped files
1 parent 2e1f8af commit 58181c0

Some content is hidden

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

43 files changed

+5559
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
To check whether you have added the right index on the posts collection, run
2+
cd validate
3+
npm install
4+
node hw4-3_validate.js
5+
You don't need to have the blog running for validate to succeed.
6+
You might want to look at the blog code to see what queries it does to the posts collection. they need to be fast.
7+
Need to import posts.json.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Blog project for M101JS
2+
3+
./app.js - entry point
4+
./package.json - npm package description
5+
./posts.js - Posts Data Access Helper
6+
./sessions.js - Sessions Data Access Helper
7+
./users.js - Users Data Access Helper
8+
./views/ - html templates
9+
10+
Getting started
11+
12+
npm install
13+
node app.js
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
var express = require('express')
2+
, app = express() // Web framework to handle routing requests
3+
, cons = require('consolidate') // Templating library adapter for Express
4+
, MongoClient = require('mongodb').MongoClient // Driver for connecting to MongoDB
5+
, routes = require('./routes'); // Routes for our application
6+
7+
MongoClient.connect('mongodb://localhost:27017/blog', function(err, db) {
8+
"use strict";
9+
if(err) throw err;
10+
11+
// Register our templating engine
12+
app.engine('html', cons.swig);
13+
app.set('view engine', 'html');
14+
app.set('views', __dirname + '/views');
15+
16+
// Express middleware to populate 'req.cookies' so we can access cookies
17+
app.use(express.cookieParser());
18+
19+
// Express middleware to populate 'req.body' so we can access POST variables
20+
app.use(express.bodyParser());
21+
22+
// Application routes
23+
routes(app, db);
24+
25+
app.listen(8082);
26+
console.log('Express server listening on port 8082');
27+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "blog",
3+
"version": "0.0.0",
4+
"description": "Blog Project for M101JS",
5+
"main": "app.js",
6+
"dependencies": {
7+
"bcrypt-nodejs": "~0.0.3",
8+
"consolidate": "~0.9.1",
9+
"express": ">=3.x",
10+
"mongodb": "~1.3.9",
11+
"swig": "~0.14.0",
12+
"validator": "~1.1.3"
13+
},
14+
"devDependencies": {},
15+
"scripts": {
16+
"test": "echo \"Error: no test specified\" && exit 1"
17+
},
18+
"repository": "",
19+
"author": "Shaun Verch <[email protected]>",
20+
"license": "BSD",
21+
"private": true
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* The PostsDAO must be constructed with a connected database object */
2+
function PostsDAO(db) {
3+
"use strict";
4+
5+
/* If this constructor is called without the "new" operator, "this" points
6+
* to the global object. Log a warning and call it correctly. */
7+
if (false === (this instanceof PostsDAO)) {
8+
console.log('Warning: PostsDAO constructor called without "new" operator');
9+
return new PostsDAO(db);
10+
}
11+
12+
var posts = db.collection("posts");
13+
14+
this.insertEntry = function (title, body, tags, author, callback) {
15+
"use strict";
16+
console.log("inserting blog entry" + title + body);
17+
18+
// fix up the permalink to not include whitespace
19+
var permalink = title.replace( /\s/g, '_' );
20+
permalink = permalink.replace( /\W/g, '' );
21+
22+
// Build a new post
23+
var post = {"title": title,
24+
"author": author,
25+
"body": body,
26+
"permalink":permalink,
27+
"tags": tags,
28+
"comments": [],
29+
"date": new Date()}
30+
31+
// now insert the post
32+
// hw3.2 TODO
33+
posts.insert(post, function (err, result) {
34+
"use strict";
35+
36+
if (err) return callback(err, null);
37+
38+
console.log("Inserted new post");
39+
callback(err, permalink);
40+
});
41+
}
42+
43+
this.getPosts = function(num, callback) {
44+
"use strict";
45+
46+
posts.find().sort('date', -1).limit(num).toArray(function(err, items) {
47+
"use strict";
48+
49+
if (err) return callback(err, null);
50+
51+
console.log("Found " + items.length + " posts");
52+
53+
callback(err, items);
54+
});
55+
}
56+
57+
this.getPostsByTag = function(tag, num, callback) {
58+
"use strict";
59+
60+
posts.find({ tags : tag }).sort('date', -1).limit(num).toArray(function(err, items) {
61+
"use strict";
62+
63+
if (err) return callback(err, null);
64+
65+
console.log("Found " + items.length + " posts");
66+
67+
callback(err, items);
68+
});
69+
}
70+
71+
this.getPostByPermalink = function(permalink, callback) {
72+
"use strict";
73+
posts.findOne({'permalink': permalink}, function(err, post) {
74+
"use strict";
75+
76+
if (err) return callback(err, null);
77+
78+
callback(err, post);
79+
});
80+
}
81+
82+
this.addComment = function(permalink, name, email, body, callback) {
83+
"use strict";
84+
85+
var comment = {'author': name, 'body': body}
86+
87+
if (email != "") {
88+
comment['email'] = email
89+
}
90+
91+
// hw3.3 TODO
92+
posts.update({'permalink': permalink}, {'$push': {'comments': comment}}, function(err, numModified) {
93+
"use strict";
94+
95+
if (err) return callback(err, null);
96+
97+
callback(err, numModified);
98+
});
99+
}
100+
}
101+
102+
module.exports.PostsDAO = PostsDAO;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
var PostsDAO = require('../posts').PostsDAO
2+
, sanitize = require('validator').sanitize; // Helper to sanitize form input
3+
4+
/* The ContentHandler must be constructed with a connected db */
5+
function ContentHandler (db) {
6+
"use strict";
7+
8+
var posts = new PostsDAO(db);
9+
10+
this.displayMainPage = function(req, res, next) {
11+
"use strict";
12+
13+
posts.getPosts(10, function(err, results) {
14+
"use strict";
15+
16+
if (err) return next(err);
17+
18+
return res.render('blog_template', {
19+
title: 'blog homepage',
20+
username: req.username,
21+
myposts: results
22+
});
23+
});
24+
}
25+
26+
this.displayMainPageByTag = function(req, res, next) {
27+
"use strict";
28+
29+
var tag = req.params.tag;
30+
31+
posts.getPostsByTag(tag, 10, function(err, results) {
32+
"use strict";
33+
34+
if (err) return next(err);
35+
36+
return res.render('blog_template', {
37+
title: 'blog homepage',
38+
username: req.username,
39+
myposts: results
40+
});
41+
});
42+
}
43+
44+
this.displayPostByPermalink = function(req, res, next) {
45+
"use strict";
46+
47+
var permalink = req.params.permalink;
48+
49+
posts.getPostByPermalink(permalink, function(err, post) {
50+
"use strict";
51+
52+
if (err) return next(err);
53+
54+
if (!post) return res.redirect("/post_not_found");
55+
56+
// init comment form fields for additional comment
57+
var comment = {'name': req.username, 'body': "", 'email': ""}
58+
59+
return res.render('entry_template', {
60+
title: 'blog post',
61+
username: req.username,
62+
post: post,
63+
comment: comment,
64+
errors: ""
65+
});
66+
});
67+
}
68+
69+
this.handleNewComment = function(req, res, next) {
70+
"use strict";
71+
var name = req.body.commentName;
72+
var email = req.body.commentEmail;
73+
var body = req.body.commentBody;
74+
var permalink = req.body.permalink;
75+
76+
// Override the comment with our actual user name if found
77+
if (req.username) {
78+
name = req.username;
79+
}
80+
81+
if (!name || !body) {
82+
// user did not fill in enough information
83+
84+
posts.getPostByPermalink(permalink, function(err, post) {
85+
"use strict";
86+
87+
if (err) return next(err);
88+
89+
if (!post) return res.redirect("/post_not_found");
90+
91+
// init comment form fields for additional comment
92+
var comment = {'name': name, 'body': "", 'email': ""}
93+
94+
var errors = "Post must contain your name and an actual comment."
95+
return res.render('entry_template', {
96+
title: 'blog post',
97+
username: req.username,
98+
post: post,
99+
comment: comment,
100+
errors: errors
101+
});
102+
});
103+
104+
return;
105+
}
106+
107+
// even if there is no logged in user, we can still post a comment
108+
posts.addComment(permalink, name, email, body, function(err, updated) {
109+
"use strict";
110+
111+
if (err) return next(err);
112+
113+
if (updated == 0) return res.redirect("/post_not_found");
114+
115+
return res.redirect("/post/" + permalink);
116+
});
117+
}
118+
119+
this.displayPostNotFound = function(req, res, next) {
120+
"use strict";
121+
return res.send('Sorry, post not found', 404);
122+
}
123+
124+
this.displayNewPostPage = function(req, res, next) {
125+
"use strict";
126+
127+
if (!req.username) return res.redirect("/login");
128+
129+
return res.render('newpost_template', {
130+
subject: "",
131+
body: "",
132+
errors: "",
133+
tags: "",
134+
username: req.username
135+
});
136+
}
137+
138+
function extract_tags(tags) {
139+
"use strict";
140+
141+
var cleaned = [];
142+
143+
var tags_array = tags.split(',');
144+
145+
for (var i = 0; i < tags_array.length; i++) {
146+
if ((cleaned.indexOf(tags_array[i]) == -1) && tags_array[i] != "") {
147+
cleaned.push(tags_array[i].replace(/\s/g,''));
148+
}
149+
}
150+
151+
return cleaned
152+
}
153+
154+
this.handleNewPost = function(req, res, next) {
155+
"use strict";
156+
157+
var title = req.body.subject
158+
var post = req.body.body
159+
var tags = req.body.tags
160+
161+
if (!req.username) return res.redirect("/signup");
162+
163+
if (!title || !post) {
164+
var errors = "Post must contain a title and blog entry";
165+
return res.render("newpost_template", {subject:title, username:req.username, body:post, tags:tags, errors:errors});
166+
}
167+
168+
var tags_array = extract_tags(tags)
169+
170+
// looks like a good entry, insert it escaped
171+
var escaped_post = sanitize(post).escape();
172+
173+
// substitute some <br> for the paragraph breaks
174+
var formatted_post = escaped_post.replace(/\r?\n/g,'<br>');
175+
176+
posts.insertEntry(title, formatted_post, tags_array, req.username, function(err, permalink) {
177+
"use strict";
178+
179+
if (err) return next(err);
180+
181+
// now redirect to the blog permalink
182+
return res.redirect("/post/" + permalink)
183+
});
184+
}
185+
}
186+
187+
module.exports = ContentHandler;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Error handling middleware
2+
3+
exports.errorHandler = function(err, req, res, next) {
4+
"use strict";
5+
console.error(err.message);
6+
console.error(err.stack);
7+
res.status(500);
8+
res.render('error_template', { error: err });
9+
}

0 commit comments

Comments
 (0)