Skip to main content

Assignment 4: Concentrator - Chatroom: Backend

Due Wednesday, March 12th 11:59pm

Setup

Accept this GitHub Classroom assignment and clone this repo that contains the stencil code for Assignment 4

In the stencil code, you will find a file named package.json , in which it contains all default modules and dependencies to get you started. You need to run npm install before coding. When the installation, you should see a node_modules directory within the current project directory listing all the modules you've installed.

Every time you need to install a new Node module, you can use the command npm install module_name . This will list the module as a dependency in the package.json file so that later on you or someone else can install all the required modules at once using the command npm install .

Make sure to delete node_modules before submission. If you use provided Github repo to upload, this directory should already be ignored; if you use manual upload, you may need to delete this directory yourself.

We used nodemon to enable hot reloading. It wil watch the files in the directory and restart the server when observing changings. You can use npm run start to start your server.

This project requires to use Express as the web framework for Node.js. Look at NodeJS prelab and lab if you need more information.

Folder Structure

  • controllers directory should contain all route controller used in this project.
  • public directory should contain static assets like your Javascript file and Stylesheet files, you can refer to these files with relative link like: <link rel="stylesheet" href="css/style.css">
  • util directory contains roomIdGenerator.js which provided an implementation of generateRoomIdentifier
  • views directory contains
    • a layouts directory containing layout.hbd , the base HTML layout shared for all pages. If you have scripts or stylesheets (Bootstrap, FontAwesome) that you want to be imported in all the pages, you should put the link here.
    • files like home.hbs , room.hbs which contains the HTML markup for individual pages' body segment

    This directory provides a basic setup for handlebars , an templating engine that builds your page in backend. You can modify this directory if you use other template engines or no template engines at all.

Introduction

In this assignment, we will utilize some popular Node modules in order to create a simple chatroom.

Inside provided stencil, we include:

  • handlebars ( npm package , documentation ) to generate web page templates efficiently in the server side
  • moment( npm package , documentation ) to handle dates and times
  • These are the modules that TAs find useful for this project, but feel free to investigate and use other ones as well!

    For this assignment, you will use HTTP methods to implement the messaging features.

    Requirements

    Accessibility Requirements

    In this assignment we also ask you to do some light reading on chat rooms and moderation as well as to answer a few questions:

    • You will be required to read Building a Better Chat Room and answer the following question in your README:

      Give two possible chatroom moderation features and the reasons that you should implement each one

    • A highly recommended article on content moderation is THE TRAUMA FLOOR , however there will be no questions asked on this reading.

    You need to meet all accessibility requirements from Assignment 2 and Lab 2. As a recap, these are:

    • declare the language
    • include alt text (though this may not be applicable if you have no images!)
    • use a logical page hierarchy: appropriate header structure and semantic HTML5 elements. e.g. if it’s a button, it should be a <button> , not a generic <div> with a handler
    • ARIA landmarks
    • Dynamic Text Sizing: (see lab 2 for hints!)
      • If you want to make this look ~elegant~, try scaling your wrapper div along with the text!
    • keyboard Only Navigation (see Assignment 2 for hints!)
    • properly-styled skip links (see Assignment 2 for hints!)
    • Good Color Contrast (at least a ratio of 4.5:1, except large scale text and large scale images should be at least 3:1, as specified here )

    Functionality Requirements

    Frontend

    • Create a messaging application that communicates with your backend
    • Allow users to create a new chatroom
    • Have pages for the following routes
      • The homepage ( / ) should be an interface that allows user(s) to see a list of existing chatrooms and be able to enter a new or existing chatroom, characterized by an ID generated by the server (e.g., ABC123).
      • Routes like ( /ABC123 ) should display the respective chatroom to the user
    • Prompt user for nickname before they can post in a chatroom
    • Any previous messages should be displayed to an entering user with most recent messages at the bottom
    • When in a chatroom, periodically refresh messages (should be a relatively short interval like every 3 seconds)
    • Each message should show the nickname, text, and datetime it was posted
    • Allow users to post messages to a chatroom

    Backend

  • Run an Express web server listening on port 8080. Document if you run on another port.
  • Create API calls for routes (the design and naming is up to you as long as you can satisfy the requirements, but below are some that you might have)
    • GET / : used for homepage, returns a webpage with all created chatrooms
    • POST /create : creates a chatroom with roomName , roomName can either be something user provides or randomly generated.
    • GET /:roomName/messages : Returns all messages for a given chatroom (you can make these messages whatever you want).

    As an example, our implementation has the server send the room.html template on the /:roomName route, and then the Javascript for room.html makes a GET request which the server handles with app.get('/:roomname/messages', ...) .

  • Each generated chatroom should be specified by a unique 6-character alphanumeric identifier.
  • Hints

    In this section, you will find useful guides for getting started with implementing your Chatroom.

    Prompting The User for a Nickname

    Once in the chatroom, the user should be instructed to choose a nickname. Feel free to use the prompt(...) function for that. If you want to be more creative, Bootstrap's Modal could be something you find handy!

    Refreshing a Message List

    Recall from TwitterFeed how we were able to refresh the tweet being displayed every 5 seconds? We can use the same setInterval function in this project to refresh our messages in a chatroom.

    In frontend, setup a request using Fetch , or other equivalent to request periodically to a server endpoint that returns a JSON dictionary of messages.

    In backend, Express makes it easy to send JSON in a response, using res.json(...) :
        
    function handleMessageRequest(req,res) 
    {
        // fetch all of the messages for this room
        // below is a placeholder for the messages you need to fetch
       let messages = [{nickname: 'Herbert', body: 'Enjoy it before I destroy it!'}, ...];
    
        // encode the messages object as JSON and send it back
       res.json(messages); 
    } 
    
    app.get(‘/:roomName/messages’,handleMessageRequest);
    
        

    res.json(messages) is equivalent to res.send(JSON.stringify(messages)).

    Templating

    When it comes time to send HTML back to the browser, there are two most popular approaches: client-side-rendering and server-side-rendering .

    For assignment3, you have mainly used client-side-rendering where your TwitterFeed page is initially empty and then built by Javascript from an empty page. There are cases where you want to send a fully-formed page directly to the client, like what you did in assignment1. Therefore, for this assignment, we will introduce the alternative: server-side-rendering with template engines.

    We included express-handlebars which is an implementation of handlebars syntax with express. Feel free to use other template engines like pug , ejs , and express-hogan .

    Handlebars

    • In server.js , we already include the setup for handlebars, which includes:
      • importing the package as hbs : const hbs = require('express-handlebars');
      • specifying the view engine and the layout directory:
                                                
        // view engine setup {@link https://github.com/ericf/express-handlebars#api}
        // registering an engine called 'hbs' which is based on the imported hbs engine
        // the configuration object entails that
        // 1. It recognizes the files with .hbs extension
        // {@link https://github.com/ericf/express-handlebars#extnamehandlebars}
        // 2. It will find its base HTML template from  a file called 'layout.hbs'
        // {@link https://github.com/ericf/express-handlebars#defaultlayout}
        // 3. It will tell the view engine to look for layouts at ./views/layouts directory
        // {@link https://github.com/ericf/express-handlebars#layoutsdir}
        app.engine('hbs', hbs({extname: 'hbs', defaultLayout: 'layout', layoutsDir: __dirname + '/views/layouts/'}));
        // setting where directory contains the views for handlebars
        app.set('views', path.join(__dirname, 'views'));
        app.set('view engine', 'hbs');
                                                
                                            
    • Then, in the stencil code, a directory called views is mainly responsible for rendering the content. The structure of the views is like below. Feel free to design your own structure as long as you also change the configuration above.

                                      
      views
          ├── home.hbs
          ├── room.hbs
          └── layouts
              └── layout.hbs
                                      

      • views/layouts/layout.hbs : The main layout is the HTML page wrapper which can be reused for the different views of the app. {{{body}}} is used as a placeholder for where the main content should be rendered.
      • views/home.hbs and views/room.hbs : The content for the app's home/room view which will be rendered into the layout's {{{body}}} .
    • In contollers , use response.render(...) to serve it as a response:
          
      function getHome(request, response){
        // do any work you need to do, then
        response.render('home', {title: 'home'});
      }
                                  

      The second argument is a object containing mappings that can be used by the handlebars template: for example, title is used as a variable inside home.hbs This is the {{ title }} page .

    Refer to the official guide for more information on the usage of handlebars.

    General Notes

    As with the previous assignment, you should do one of the following

    • run your HTML and CSS syntax through validators. Validators might report a lot of errors related to Vue syntax and CSS functions that you can ignore. Refer to Piazza for what errors you can ignore.
    • use the extensions we recommended in Setup
    • choose other tools you find appropriate though you will be held to the same standards

    You should also be using an accessibility checker such as WAVE. For errors that you choose not to fix, make sure to explain your rationale in README.

    It is now also recommended that you run your JavaScript code through a linter such as ESLint (we provided a default configuration for ESLint in the Git repo, but feel free to refer to the beginning of lab2 for more details on custom setup).

    We also highly encourage you document your code with the use of JSDoc ( simple JSDoc function header annotations would suffice) especially for any code you write whose purpose may not be immediately obvious to the reader.

    While we won’t check that you used ESLint or JSDoc directly in this assignment, we will also not hesitate to deduct points if your code is hard to read which could have easily been fixed by the use of such tools.

    Troubleshooting

    As with assignment 1, it is recommended that you take advantage of all the online resources we have provided so far. If you get stuck, we would be happy to troubleshoot with you at TA hours!

    Handin

    To hand in your code for Assignment 4, upload your code to Gradescope via Github repository upload (ensure that you have pushed your changes and that you are handing in the most recent version of your code!).