WebFund 2015W Final Exam Review: Difference between revisions
No edit summary |
|||
Line 1: | Line 1: | ||
==Audio== | |||
The audio from the exam review given on April 10, 2015 [http://homeostasis.scs.carleton.ca/~soma/webfund-2015w/lectures/comp2406-2015w-examreview-10Apr2015.m4a is now available]. | |||
==Notes== | ==Notes== |
Revision as of 19:54, 10 April 2015
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}