Homework #4

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

  1. You will be given access to a private repository on GitHub
  2. The final version of your assignment should be in GitHub
  3. 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:
  • 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

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!
  • 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"
  • 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!
  • 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's POSTing 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 a GET 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 the req.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)