WebFund 2015W Final Exam Review
Jump to navigation
Jump to search
Audio
The audio from the exam review given on April 10, 2015 is now available.
Notes
The final exam will be based on exam-notes, a simplified version of the solutions to tls-notes from Assignment 10.
Code
routes/index.js
var express = require('express');
var router = express.Router();
var mongodb = require('mongodb');
var mc = mongodb.MongoClient;
var ObjectID = mongodb.ObjectID;
var notesCollection, usersCollection;
mc.connect('mongodb://localhost/exam-notes', function(err, db) {
if (err) {
throw err;
}
notesCollection = db.collection('notes');
usersCollection = db.collection('users');
});
router.post('/register', function(req, res) {
var username = req.body.username;
var password = req.body.password;
var checkInsert = function(err, newUsers) {
if (err) {
res.redirect("/?error=Unable to add user");
} else {
res.redirect("/?error=User " + username +
" successfully registered");
}
}
var checkUsername = function(err, user) {
if (err) {
res.redirect("/?error=unable to check username");
} else if (user === null) {
var newUser = {
username: username,
password: password
};
usersCollection.update({username: username},
newUser,
{upsert: true},
checkInsert);
} else {
res.redirect("/?error=user already exists");
}
}
usersCollection.findOne({username: username}, checkUsername);
});
router.get('/', function(req, res) {
if (req.session.username) {
res.redirect("/notes");
} else {
res.render('index', { title: 'COMP 2406 Exam Notes Demo',
error: req.query.error });
}
});
router.get('/notes', function(req, res) {
var username = req.session.username;
if (username) {
res.render("notes.jade", {username: username,
title: username +"'s Notes"});
} else {
res.redirect("/?error=Not Logged In");
}
});
router.post('/login', function(req, res) {
var username = req.body.username;
var password = req.body.password;
var authenticateUser = function(err, user){
if (err || user === null || password !== user.password) {
res.redirect("/?error=invalid username or password");
} else {
req.session.username = username;
res.redirect("/notes");
}
}
usersCollection.findOne({username: username}, authenticateUser);
});
router.post('/logout', function(req, res) {
req.session.destroy(function(err){
if (err) {
console.log("Error: %s", err);
}
});
res.redirect("/");
});
router.get('/getNotes', function(req, res) {
var username = req.session.username;
var renderNotes = function(err, notes) {
if (err) {
notes = [{"title": "Couldn't get notes",
"owner": username,
"content": "Error fetching notes!"}];
}
res.send(notes);
}
if (username) {
notesCollection.find({owner: username}).toArray(renderNotes);
} else {
res.send([{"title": "Not Logged In",
"owner": "None",
"content": "Nobody seems to be logged in!"}]);
}
});
router.post('/updateNote', function(req, res) {
var username = req.session.username;
var id = req.body.id;
var title = req.body.title;
var content = req.body.content;
var checkUpdate = function(err, result) {
if (err) {
res.send("ERROR: update failed");
} else {
res.send("update succeeded");
}
}
if (username) {
if (id && title && content) {
notesCollection.update({_id: ObjectID(id)},
{$set: {title: title,
content: content}},
checkUpdate);
} else {
res.send("ERROR: bad parameters");
}
} else {
res.send("ERROR: not logged in");
}
});
router.post('/newNote', function(req, res) {
var username = req.session.username;
var newNote;
var reportInserted = function(err, notesInserted) {
if (err) {
res.send("ERROR: Could not create a new note");
} else {
res.send(notesInserted[0]._id);
}
}
if (username) {
newNote = {title: "Untitled",
owner: username,
content: "No content"};
notesCollection.insert(newNote, reportInserted);
} else {
res.send("ERROR: Not Logged In");
}
});
module.exports = router;
public/javascripts/register.js
$(function(){
$("#register").on("click",function(){
var $form = $("form");
$form.attr("action", "/register");
$form.submit();
});
});
public/javascripts/notes.js
$(function() {
var insertNotesIntoDOM = function(userNotes) {
var i, theNote;
$(".notes").remove();
if (userNotes.length < 1) {
$("#notesList").append('<div class="notes">No notes!</div>');
return;
}
for (i=0; i < userNotes.length; i++) {
console.log("Adding note " + i);
theNote = userNotes[i];
$("#notesList").append('<div class="notes list-group-item ' +
'list-group-item-default"> ' +
'<a href="#" ' +
'class="notes list-group-item-heading" ' +
'id="edit' + i + '">' +
'<h4>' + theNote.title + '</h4></a> ' +
'<p class="list-group-item-text">' +
theNote.content + '</p>' +
'</div>');
$("#edit" + i).click(userNotes[i], editNote);
}
}
var getAndListNotes = function() {
$.getJSON("/getNotes", insertNotesIntoDOM);
}
var updateNoteOnServer = function(event) {
var theNote = event.data;
theNote.title = $("#noteTitle").val();
theNote.content = $("#noteContent").val();
noteListing();
$.post("/updateNote",
{"id": theNote._id,
"title": theNote.title,
"content": theNote.content},
getAndListNotes);
}
var editNote = function(event) {
var theNote = event.data;
$(".notesArea").replaceWith('<div class="notesArea" ' +
'id="editNoteDiv"></div>');
$("#editNoteDiv").append('<h2>Edit Note</h2>');
$("#editNoteDiv").append('<div><input type="text" ' +
'id="noteTitle"></input></div>');
$("#noteTitle").val(theNote.title);
$("#editNoteDiv").append('<div>' +
'<textarea cols="40" rows="5" ' +
'id="noteContent" wrap="virtual">' +
'</textarea></div>');
$("#noteContent").val(theNote.content);
$("#editNoteDiv").append('<button type="button" ' +
'class="btn btn-success" ' +
'id="updateNote">' +
'Update</button>')
$("#updateNote").click(theNote, updateNoteOnServer);
}
var editNewNote = function(result) {
var theNote = {"title": "",
"content": ""};
if (result.indexOf("ERROR") === -1) {
theNote._id = result;
editNote({data: theNote});
} else {
noteListing();
}
}
var newNote = function() {
$.post("/newNote", editNewNote);
}
var noteListing = function() {
$(".notesArea").replaceWith('<div class="notesArea" ' +
'id="listNotesDiv"></div>');
$("#listNotesDiv").append('<h2>Notes</h2>');
$("#listNotesDiv").append('<div id="notesList" class="list-group well">' +
'<a class="notes list-group-item">Loading Notes...</a>' +
'</div>');
$("#listNotesDiv").append('<button id="newNote"' +
' class="btn btn-primary"' +
' type="button">' +
'New Note</button>');
$("#newNote").click(newNote);
getAndListNotes();
}
noteListing();
});
views/layout.jade
doctype html
html
head
title= title
link(rel='stylesheet', href='/libs/bootstrap/css/bootstrap.css')
link(rel='stylesheet', href='/libs/bootstrap/css/bootstrap-theme.css')
link(rel='stylesheet', href='/stylesheets/style.css')
script(src='/libs/jquery.js')
script(src='/libs/bootstrap/js/bootstrap.js')
block header
body(role="document")
block content
views/index.jade
extends layout
block header
script(src="javascripts/register.js")
block content
h1= title
p Welcome to #{title}
- if(error)
div.error #{error}
div
form(action="/login", method="post")
div.form-group
label(for="username") Username
input.form-control.limitwidth(type="text", name="username")
div.form-group
label(for="password") Password
input.form-control.limitwidth(type="password", name="password")
button.btn.btn-default(type="submit") Login
button#register.btn.btn-warning(type="button") Register
views/notes.jade
extends layout
block header
script(src="javascripts/notes.js")
block content
div.page-header
h1#pageTitle #{username}'s Account
p#pageWelcome Welcome #{username}
form(action="/logout", method="post")
button.btn.btn-info(type="submit") Logout
div.notesArea
views/error.jade
extends layout
block content
h1= message
h2= error.status
pre #{error.stack}