Creating a Tiny Web Framework, Due Monday, Feb 26th by 11PM Wednesday, Feb 28th by 11PM
⚠️⚠️⚠️NO GRACE PERIOD⚠️⚠️⚠️
Extended due .
Overview
Description
Create a site the collects and displays complaints about the New York City subway. Call it: "The Complaining Commuter". In this homework you'll be working with:
- serving static files
- middleware
- handling forms, both GET and POST
- sessions
You'll be creating 3 pages:
- home -
/
: displays a list of all of the complaints submitted on the site; can be filtered by subway line - complain -
/complain
: a page that allows a user to submit a new complaint - stats -
/stats
: displays the number of times the user has submitted a complaint during this browsing session
Example Interaction
Submission Process
- You will be given access to a private repository on GitHub
- The final version of your assignment should be in GitHub
- Push your changes to the homework repository on GitHub by the due date.
Make at Least 4 Commits
- Commit multiple times throughout your development process.
- Make at least 3 separate commits - (for example, one option may be to make one commit per part in the homework).
Part 1 - Setup
Installing Dependencies
- create a
package.json
- install the following dependencies (make sure you use the
--save
option), and no others:express
hbs
express-session
.gitignore
- create a
.gitignore
- ignore the following files:
node_modules
- any other files that aren't relevant to the project… for example
.DS_Store
if you're on OSX.swp
if you use vim as your editor- etc.
linting
- an eslint configuration file (for example
.eslintrc.json
) should be in the root directory - make sure that any global linting tools are installed (
eslint
) - periodically lint your program as you work
Part 2 - Homepage and Static Files
Enabling Static Files
First, let's make sure you can serve up static content, like css and images.
- create the following directory structure in your project's root directory
public
public/css
public/img
- add a blank css file in
public/css/base.css
- add a subway related image in
public/img/subway.jpg
- create a basic express application called
app.js
; you don't have to define any routes yet…- make sure that your application is served over port 3000
- just add the appropriate requires and middleware to enable static file serving:
- check out the slides on serving static files with Express
- or see page 26 in Chapter 3 of
- test that both the css files and image work
- for example, try to curl
http://localhost:3000/img/subway.jpg
- or go that url in your browser
- for example, try to curl
Creating a Home Page
Now that static files are set, create a homepage.
- for the home page, your app should accept
GET
requests on the path,/
- set up handlebars - these slides may help… (it's just one line!)
- get all the requirements and config setup
- create the appropriate views folder, along with an initial layout file:
views
views/layout.hbs
- in your
layout.hbs
, drop in the surrounding html that will go on every page- pull in your
base.css
stylesheet - include a header containing both your
subway.jpg
image and the title of your site, The Complaining Commuter - additionally, add a footer that links to all 3 pages in your site:
- a link to the home / list of complaints page (/)
- a link to a page to add a complaint page (/complain)
- a link to a stats page (/stats)
- don't forget
body
, surrounded by triple curly braces!
- pull in your
- in your template for your homepage (you can name this template whatever you want… just make sure you can pull it up later), add the following:
- an
h3
header that says "Complaints List"
- an
- create the appropriate route so that a
GET
request pulls up the rendered template - add some css to change some styles, (for example change the color of the text, change the font, etc.)
Here's an example of what the page could look like (you don't have to use the same exact styles, but add enough styles so that you can see that the style sheet is integrated correctly):
Part 3 - List of Complaints, Filtering List of Complaints
The homepage should also have a list of all of the complaints submitted to the site. By default, this list will start with the following content:
- G - The person sitting next to me was eating hard-boiled eggs in the subway car (???!!!)
- F - There was a possum loose on the platform
- A - The train was an hour late!, A Line
These complaints can be filtered so that your application only shows complaints for a particular subway line.
Middleware and Logging
First, get some logging together so that you can troubleshoot. Log out the request that you receive, including the request's query string and body.
- require the
body-parser
middleware and use it; this will allow you to access the content of the request's body - set up some logging using your own middleware function; it should include
- the request method, path
- followed by the contents of the request's query string
- followed by the contents of the request body
Complaint List
Now for some actual content. This page will display the complaints and the subway line associated with the complaint.
Bootstrap the list with some data.
- store all of the complaint data in a global Array of objects…
- each object has two properties:
- the actual complaint (just text)
- the subway line
- it should start off with:
- G - The person sitting next to me was eating hard-boiled eggs in the subway car (???!!!)
- F - There was a possum loose on the platform
- A - The train was an hour late!
- (storing this data in a global variable isn't typical, of course, but we'll have to store the data somewhere for now!)
Create the actual page…
- modify your route for your home page (
/
) so that you render the template with the correct context object (that is, the list of complaints to display) - in the template, you can iterate through the list of complaints using the
#each
helper - display the complaints in reverse order - the last element on the list should be on top
- put each complaint/subway line pair in a list item (
li
) - additionally, make the subway line a different style (such as a different font-weight or background-color or … any other style that's different from the complaint)
Test your page.
- it should look a little like the image below
- again, the styles don't have to match exactly - just add enough styling to distinguish between the subway line and the actual message
- (ignore the form for now… you'll set that up next)
Filter by Subway Line
Once you have your list of complaints working… add a form that allows you to filter by subway line. →
- create a form in your
index.hbs
template- the form should issue a
GET
request - the request should go to the same URL that it's on (still home,
/
) - the form should also have a text field and a submit button
- remember to give you text field a name!
- the form should issue a
- on the server side, modify your route for your home page (
/
) so that it sends filtered data if the form is submitted- how does your route know if the form was submitted?
- how does the route extract the data from the
GET
request / form submission? - find some way to filter the data
- send that data to the template
- if the filter submitted is blank or if there is no filter, display all of the complaints
- here's what the filter interaction should look like:
The log should look something like this:
GET
the home page
GET /
=====
req.query: {}
req.body: {}
GET
to submit your filter
GET /
=====
req.query: { filter: 'G' }
req.body: {}
Part 4 - Adding a Complaint
Create a Complaint Form
- in app.js create a new route handler and template for
/complain
- add a form in your template
- it should have 2
inputs
(choose whatever form elements you like, they can both be text if you want to keep things simple) - with appropriate name attributes… you'll see that name in the request body!- the text of the complaint
- …and the subway line
- …as well as a submit
input
- the form's method should be
POST
- the action should be empty string
""
or/complain
(it'sPOST
ing to itself) - modify app.js again… by adding a new route so that it accepts
POST
requests on/complain
- in your callback function for this route…
- create an object for this new complaint (with the actual complaint text and the subway line) and add it to your global list of complaint objects
- …after that, redirect to home
/
with aGET
request
- here's what the filter interaction should look like:
The logs should look something like this for the POST, Redirect and GET:
GET
the list page.
GET /complain
=====
req.query: {}
req.body: {}
POST
the form (notice the body).
POST /complain
=====
req.query: {}
req.body: { complaint: 'Blah blah blah!', line: 'Q' }
GET
the home page (/)…
GET /
=====
req.query: {}
req.body: {}
SKIP THIS PART
(We did not cover it in class yet)
Part 5 - Stats Page / Using a Session Value
Create a page that shows how many complaints that a user has submitted during their browsing session.
Session Setup
First, setup and configure sessions:
- bring in the session module by requiring
express-session
- set up a some options for your session:
var sessionOptions = {
secret: 'secret cookie thang',
resave: true,
saveUninitialized: true
};
- then use those options for session handling middleware:
app.use(session(sessionOptions));
Modify your add route (/complain
) so that every time a user adds a new complaint, it's counted in their session.
- in the add (
/complain
) route, count how many times a person has complained for their session by adding a property to thereq.session
object - increment the count if there's already a value there
- otherwise, the count should start at 0
The Stats Page
- create a route handler for
/stats
- create a template for it
- display the session variable that represents the current count of the user's complaint submssions
- the page should look like:
Test the session management.
- open your app with one browser… and add some complaints
- the stats page should show the count of complaints
- open your app in another browser or in private browsing / incognito mode
- check that the count is 0 for this other browser session
- (and of course, make sure that the previous count in your other session was maintained)