SWE 432, Fall 2018, Homework 3, Due Oct 29, 10 am

Please post questions on Piazza

Project Overview

This semester, while you learn the key concepts of web application development, you will apply these skills to build a meme generator, which we will refer to as the Memebase. A meme is a cultural phenomenon that combines some popular graphic (for example, a cat or TV/movie character) with large-block text. As an example, here is a meme generated by combining a graphic called “news cat” with some text relevant to this project:

You will build the Memebase in four different components; each assignment will be one component. Each component will conform to a common interface, allowing them to be independently developed and tested. The final result will be a working website that allows users to generate memes, create accounts to share and track their memes.

This Assignment

For the third component, you will build a frontend service that lets users generate memes from a pre-defined set of templates.

Getting Started

You’ll need to install Node.js on your computer — version 8 or higher. You can follow the instructions on the Node.js installation page for the “LTS” version to get it installed.

It is  not required that you use an IDE, but it’s a really really really really good idea. JetBrains’ IntelliJ/WebStorm is a great choice — if you already have IntelliJ you can add the NodeJS component to it, or simply download WebStorm. You can get a free license to use any of the JetBrains IDEs by filling out this simple form.

Then, you are ready to get started. Download the handout, extract it, and then open a terminal in the handout directory. Run the command  npm install, which will download all of the JavaScript modules that the assignment will use.

Important note: DO NOT MAKE CHANGES TO PACKAGE.JSON; DO NOT INSTALL NEW PACKAGES. When we grade your project, we will grade it using the original package.json file!

Overview

You’ll be building a single-page React application that interacts with our backend to create memes in the browser. Here’s a screenshot of what it will look like when it’s done:

You will implement two react components –  MemeGeneratorApp and  MemeCustomizer, step by step.

This assignment does not have any automated tests – you’ll test it yourself in the browser, and have to judge for yourself when it’s done.

For your reference, here’s an overview of the key react components that make up this page:

We’ve intentionally written up this assignment so that it starts off like a tutorial (in Part 1), and decreases in guidance as you progress.

All of your implementation will be in the file MemeGenerator.js

You can compare your implementation to our reference implementation, available at: http://reference.thememebase.com/

Helpful Links:

JavaScript reference book – Free access on campus or on VPN

React-Bootstrap documentation

React documentation

Part 1 (20 points): The template selector

Adding a dropdown, with no options in it: Start off this assignment by adding the “Choose a template” dropdown menu. You should use a React-Bootstrap FormControl. Add this FormControl in the  render method of your  MemeGenerator.  The template selector will be populated with a list of templates collected from our web service – we’ve provided you with a simple client client that implements this functionality. First we’ll fetch the templates from the service and store them in our  MemeGenerator’s state, and then we will update the render method to render that state.

Check your progress: When you view your app, you should see an empty dropdown menu.

Fetching the options, adding to state: The state of this component will include two properties:  selectedTemplate and  availableTemplates. We’ll populate this in the  componentDidMount React Lifecycle event. You can call  client.getTemplate() to get a list of all of the template objects (they will be in the exact same format as HW2), which will return a Promise. After you get the list of available templates, you should call this.setState, setting  availableTemplates to be the entire list of templates, and  selectedTemplate to be the first template that’s returned.

Check your progress: When you view your app using the React developer tools (in Chrome or Firefox), after a moment you should see the  state of your  MemeGenerator component updated to include the list of available templates.

Add a loading message: In your  render method for the  MemeGenerator component, add a check at the start: if the two state variables that you’ve now configured are undefined, then your MemeGenerator should simply display the text “Loading…”. Otherwise, show your dropdown menu.

Check your progress: When you view your app, it should first show Loading (briefly) and then it will disappear and show your empty dropdown menu.

Update your render method to include the list of available templates: Inside of your  FormControl, add a loop over all of the available templates (the keys in  this.state.availableTemplates). For each template, add an  option element, with its value being the name of the template, its key also being the name of the template, and its contents also being the name of the template.

Check your progress: When you view your app, your dropdown menu should now have the templates listed in it.

Turn the template selector into a controlled component: Set the  value parameter for your  FormControl to  {this.state.selectedTemplate}, causing it to become a controlled component. Create an  onChange handler that will update the  MemeGenerator component’s state to reflect the newly selected template.

Check your progress: When you view your app and change the selected template, you should see the state update to reflect this change in the React developer tools panel.

Part 2 (20 points) Rendering text fields for the template

Create the MemeCustomizer component: As you can see in the annotated version of the app above, the  MemeCustomizer component contains most of the magic for the app. This component will be a sub-component of your  MemeGenerator, and you’ll need to pass it two properties from the  MemeGenerator’s state – the selected template’s name and the entire template description for that selected template.

Define MemeCustomizer state: The MemeCustomizer will keep track of the new meme that the user is creating as  state variables. We’ll create a state variable called  text to store the values of each of the text fields for the meme template. Initialize this  text state variable so that it has one property for each text field, with the value of each property the name of that field. For instance, if the meme template has only the text fields  top and  bottom then your state should look like  this.state = {text: { top: "top", bottom:"bottom"}}. Note that this will only handle the starting state of the component: when the selected template is changed, your component won’t refresh (until the last step part 2).

Add the text fields in a form: Start to implement your  render method for the MemeCustomizer by adding a  form, within which you can add a FormGroup (it’s not necessary that every form element is in a form, but doing so allows the browser to know what to do when the user presses “return” inside of a form field). Loop over the text fields for the selected meme template, and emit a  FormControl of type  text for each one. Make sure to add a unique key attribute to each control.

Bind the text fields to the state, add an event handler to update it: Set the  value of each of these text fields to be the appropriate  state variable. Add an  onChange event handler for each text field to update the state of that text field as the user types in it. Your onChange handler might need to know which text box is being updated – you can solve this by referencing the control’s key, or by creating a new handler for each control that captures the text element ID in a closure (like in the editable todo example).

Add a lifecycle listener to refresh your state when the selected meme template changes: Add a componentDidUpdate(prevProps) method to your  MemeCustomizer. This will be called every time that the properties of the component are updated, allowing you to see what changed by comparing  prevProps with  this.props. When the selected template is changed, you should update the state of the  MemeCustomizer so that the text fields reflect those of the new template (e.g. when switching to Gru, you’ll get steps 1-4, with new default text in each).

When you finish part 2, it should look something like this:


Part 3 (30 points) Generating template graphics

Fetching the demo image: When the  MemeCustomizer is rendered, we want to show a preview of the meme that is being generated. For instance, when initially loaded, if Doge is selected, the app will look like this:

To do so, we’ll call  client.generateMeme, which takes two parameters: the name of the template, and a  text object that is of the format:  let text = { textFieldName: "textFieldValue", otherTextFieldName: "otherTextFieldValue"}client.generateMeme returns a promise for the image data — when you get the data back, store the image in a state field called imgData.

Rendering the image: Add a  LoadedImage component to your  MemeCustomizer’s render method, setting the  src property to be  this.state.imgData.

If you’ve completed these steps correctly, you should see the image as it appears above.

Regenerating the demo image when the selected template changes: As part of your  componentDidUpdate implementation, also ensure that you regenerate the image to match the new template when a new template is selected. Since we are storing the image data as part of the component’s state, when you get the refreshed image, calling  setState with the updated state should then update the image that’s displayed.

Part 4 (30 points) Generating the actual memes

Adding and wiring the regenerate button: Add a Button of type submit to your  MemeCustomizer inside of the Form called “Regenerate” and use an onSubmit handler for the  form so that when the user submits the form (which will happen either clicking the button or pressing return in one of the text fields), the meme that is displayed is regenerated (using the same  client.generateMeme used in part 4), but using the text that the user has now entered.

Locking out the MemeCustomizer component while update is pending: While there is a pending request to generate a new meme (e.g. from a prior submission), the text fields should become disabled and the submit button should become disabled. You should keep track of whether these components are disabled or not using a single state variable.

Grading

Your meme generator will be graded by hand (as described in each section above). When you submit to Autolab, it will not grade your submission at all. We will grade for correctness on the above points — and you should test your functionality by hand as well.

Hand In Instructions

You must turn in your assignment using Autolab (You MUST be on the campus network, or connected to the GMU VPN to connect to Autolab). If you did not receive a confirmation email from Autolab to set a password, enter your @gmu.edu (NOT @masonlive) email, and click “forgot password” to get a new password.

To prepare your code to be submitted, run npm pack in the assignment directory. This will create an archive  thememebase-3.0.0.tgz – this is what you will submit to Autolab. Do not try and generate this archive without using  npm; it’s highly likely to cause Autolab to reject it.

You can resubmit your assignment an unlimited number of times before the deadline. Note the course late-submission policy: assignments will be accepted up until 24 hours past the deadline at a penalty of 10%; after 24 hours, no late assignments will be accepted, no exceptions.

Questions

Please post questions on Piazza

 

Contact