CS396: Spring 2022

Intro to Web Development

CS396: Spring 2022

Assignments > HW6. PhotoApp: Various Extensions

Due on Wed, 06/08 @ 11:59PM. 40 Points.

Overview

For your last homework assignment, you will re-implement your HW4 code in way that follows React conventions. A few ground rules:

  1. You can use functional or class components (What’s the difference?). Sarah used class components in her demos, but go with what you prefer. We have no preference.
  2. You can use third-party libraries if you want (but it’s not required).
  3. There is some starter code for this homework in Lab 10 that you are welcome to use. That said, you are also welcome to code this assignment from scratch – up to you.
  4. We won’t be grading you on CSS, but please do make it look nice. You’re also welcome to customize the look and feel to make it your own.
  5. We’ve implemented a react version of the PhotoApp here: https://photo-app-secured.herokuapp.com/. Yours should function similarly.

Tips

If you’re running into any errors with fetch requests, you may have a few minor bugs in your REST API Endpoint. To verify (Is the bug in my React code or in my API?), try running your code using the course API by updating your React app’s proxy url address in package.json to: https://photo-app-secured.herokuapp.com/.

Tasks

In the section below, we’ve mapped out a suggested implementation strategy. If you implement your React functionality differently, that’s fine, but we will be verifying that you did indeed make a series of components (versus just copying your HW4 file into a React folder and only making minor changes).

An example of the implemented react app can be found here.

Points Component / Task Description
2pts NavBar.js
Displays the Header
Create a NavBar component that displays the username of the logged in user, a logout button, and a link to the API tester as shown in the demo. Notes:
  • This task requires that you fetch data from the /api/profile endpoint.
  • It's OK that the /logout and /api links don't work right now.
2pts Profile.js
Display Profile
Create a Profile component that displays the current user's profile (inside of the right panel) using data from the /api/profile endpoint.
  • Hint: Since both Profile and NavBar require you to fetch data from /api/profile, you may want to put your fetch functionality in App, and then pass the requisite user information to the child components as properties.
2pts Stories.js
Display Stories
Create a Stories component that displays stories from the user's network. This component will both fetch the stories from /api/stories, and draw the stories.
2pts Suggestions.js
Display All Suggestions
Create a Suggestions component that displays suggested user accounts. This component will both fetch the suggestions from /api/suggestions, and draw the suggested users with the help of the Suggestion.js child component (see below).
5pts Suggestion.js
Display Individual Suggestion
Create a Suggestion component that will:
  • Render a representation fo each user
  • Handle the follow/unfollow fetch requests to the /api/following and /api/following/<id> endpoints.
  • Redraw the HTML after a follow / unfollow requests is successfully issued.
2pts Posts.js
Display All Posts
Create a Posts component that displays all of the posts user accounts. This component will both fetch the posts from /api/posts, and draw each post users with the help of the Post.js child component (see below).
3pts Post.js
Display Individual Post
Create a Post component so that it looks like the post from HW4. To do this:
  • The Like/Unlike functionality should be handled by a LikeButton child component (details below).
  • The Bookmark/Unbookmark functionality should be handled by a BookmarkButton child component (details below).
  • The "add comment" functionality should be handled by a AddComment child component (details below).
  • You can handle the display of the "comment button" and "last comment" any way you like. You could create a Comments and/or Comment child component, or you could render comments directly in your Post's render method.
2pts Post.js
Fetch and Redraw Post
Within your Post component, you will also have to write some code to redraw a post after its structure is modified (liked/unliked, bookmarked/unbookmarked, etc.). We recommend that you create a function called requeryPost that:
  • Re-queries the post from /api/posts/<id>
  • Updates the state of your component to reflect that the post data has changed (which will in turn re-render the component).
You will also want to give some of your child components access to this function (e.g., LikeButton, BookmarkButton, etc.) by passing a reference to this function as a property. This way, the child components can also trigger a post redraw by invoking its parent's requeryPost function.
4pts LikeButton.js
Like / Unlike Post
Create a LikeButton component that will:
  • Render a solid / filled in heart (depending on whether the post is liked / unliked by the current user).
  • Handle the like / unlike fetch requests to the /api/posts/<post_id>/likes and /api/posts/<post_id>/likes/<id> endpoints.
  • Redraw the Post if the like / unlike requests is successful (hint: use the Post's requeryPost function).
4pts BookmarkButton.js
Bookmark / Un-Bookmark Post
Create a BookmarkButton component that will:
  • Render a solid / filled in bookmark (depending on whether the post is bookmarked / un-bookmarked by the current user).
  • Handle the bookmark / un-bookmark fetch requests to the /api/posts/bookmarks and /api/bookmarks/<id> endpoints.
  • Redraw the Post if the bookmark / un-bookmark request is successful (hint: use the Post's requeryPost function).
5pts AddComment.js
Add a Comment
Create an AddComment component that will:
  • Render an "Add comment" textbox and button.
  • Handle the add comment fetch request to the /api/comments endpoint.
  • Redraw the Post (parent component) after if the "add comment" request is successful (hint: use the Post's requeryPost function).
1pt Keyboard Navigation
  • Ensure that all of the buttons are tabbable
  • Ensure that all the event handlers can be triggered using the "spacebar" or "enter / return" keys.
2pts Aria attributes Use the "aria-label" and "aria-checked" attributes (in conjunction with the role="switch" attribute) to indicate to the screen reader whether the following buttons are turned on or off:
  • Like / Unlike button
  • Bookmark / Unbookmark button
  • Follow / Unfollow button
2pts Form Accessibility
Extra handling for "Add Comment"
  • After a comment is submitted by the user, ensure that the focus is set back to the input. Hint: use a "ref".
  • Add an event handler to the input control so that it submits when the user presses the "Enter/Return" key. Here is a hint.
2pts Accessibility Questions In a text file, please answer the following accessibility questions:
  • Were React’s compilation warning/error messages helpful?
  • Did React’s compilation warning/error messages prompt you to consider making your site more accessible?
  • Did you consider conducting accessibility testing on your lab assignment? Why or why not?
  • If you tested your site for accessibility and found issues, were you able to solve them? What did you do to try to solve them? What stopped you from successfully resolving or trying to resolve the issues?

Extra Credit

You may earn up to 5 points extra credit. If you are working in partners, your extra credit will be split between the two of you (i.e. you will have to implement 10 points worth of extra credit to earn 5 points each).

Points Component / Task Description
5pts Deploy
Deploy your React App to Heroku
See deployment instructions below
5pts Modal Implement the "show modal" functionality using a react component. This will involve making a Modal component (and not just copying your old modal code into your react app).
5pts Stylize your Photo App Modify the HTML / CSS / JavaScript to make the look-and-feel of the app your own. If you were the UX/UI designer for Instagram, how would you design the app? What colors and fonts would you use? Would the layout be different? Show us!

Deployment Instructions (for Extra Credit)

In order to deploy your React code, you have two options.

1. Create a Stand-Alone React App

  1. Create a git repository that has your react app as a top-level directory (see suggested file structure below).
  2. Create a .gitignore file that excludes the node_modules and build directories (see below).
  3. Update all of your API urls (the ones that issue fetch requests) to point to your production REST API (or the class API if your HW5 deployment is broken).
  4. Modify your package.json file (which should be at the root of your git repo) and delete the “proxy” entry ("proxy": "http://127.0.0.1:5000",). Note that you can’t comment out entries in a JSON file, so you’ll have to actually delete it.
  5. Commit and push your new repo.
  6. Deploy to Heroku

Suggested File Structure:

your-react-app
├── .git
├── .gitignore
├── build               # build should be excluded from the repo
├── node_modules        # node_modules should be excluded from the repo
├── package-lock.json
├── package.json
├── public
└── src

.gitignore file

node_modules
build

2. Integrate with Flask

  1. Create a hw06 branch: git checkout -b hw06
  2. Paste your react client folder (I called mine react-client) at the root of your Flask app (see suggested dile structure below). Just for simplicity, rename that folder to react-client.
  3. Create a package.json file at the root of your Flask app (note that this is in addition to the package.json file inside of your react-client directory) that has the JSON format shown below.
    • This file tells Heroku to compile your react app from within the react-client subdirectory.
  4. Update your requirements.txt to include the following: flask-multistatic==1.0
    • You will also need to install this library on your local machine: pip3 install flask-multistatic.
  5. Modify your app.py as shown below.
  6. Ensure that your react-client/node_modules and react-client/build folders are excluded from git via your .gitignore file.
  7. Commit and push your changes to GitHub.
  8. Deploy to Heroku (see instructions below).

Suggested File Structure:

photo-app
├── .env
├── .git
├── .gitignore
├── Procfile
├── README.md
├── app.py
├── decorators.py
├── models
├── package-lock.json
├── package.json
├── populate.py
├── react-client
├── requirements.txt
├── sql
├── static
├── templates
├── tests
└── views

package.json file at the root of your Flask app (not the one in your react-client folder):

{
    "name": "photo-app-heroku-react-build-file",
    "version": "1.0.0",
    "description": "",
    "scripts": {
      "build": "cd react-client && npm install && npm run build"
    },
    "dependencies": {
        "cross-env": "^7.0.3"
    }
}  

app.py updates:

from flask_multistatic import MultiStaticFlask as Flask   # at the top
from flask import send_from_directory                     # at the top


# place the following after: app = Flask(__name__)
app.static_folder = [
    os.path.join(app.root_path, 'react-client', 'build', 'static'),
    os.path.join(app.root_path, 'static')
]

# modify the root path to point to your React App:
@app.route('/')
@decorators.jwt_or_login
def home():
    # https://medium.com/swlh/how-to-deploy-a-react-python-flask-project-on-heroku-edb99309311
    return send_from_directory(app.root_path + '/react-client/build', 'index.html')

Reminder of how to deploy to Heroku (optional)

  1. Create a new app on Heroku (like you did for HW5), including setting the JWT and DB_URL environment variables.
  2. Navigate to your folder (using the command line).
  3. Connect your local git repo to your newly created Heroku app (you will only have to do this once):
    heroku git:remote -a name-of-the-app-you-just-made
    • You may have to login first: heroku login -i
  4. Push your repo to Heroku: git push heroku your-branch-name:main, where your-branch-name is the name of your local branch, and main is the name of the destination branch on Heroku.
    • Note that Herou will automatically read your package.json file, install the dependencies, and create a production React build for you.
  5. Test your web server.
  6. Don’t forget to also push your repo to GitHub
  7. That should be it!

Accessibility Reflection

Accessibility Questionnaire

This quarter, we assigned a few accessibility activities – to encourage you to think about how people might interact with your applications without mouse or using a screen reader. To reflect on this process, please fill out the Accessibility Questionnaire if you didn’t complete it during Lab 10.

Accessibility Research Study

We also wanted to invite you to participate in a research study – to examine and reflect on how to better teach students about accessibility within the software development process. Please fill out this Consent to participate in research form to let us know whether or not you are willing participate in this study. Participation is optional.

Appreciations

And while you’re at it, please take a moment to thank / write a note to a peer mentor who helped you in some way (even if you just take 30 seconds to do it). Peer mentors are students too, and most of them do waaaay more than what is officially asked of them in order to support you. This form is completely anonymous.

https://forms.gle/zXdxaBik4suPifCA9

What to Turn In

Please review the requirements above and ensure you have met them. When you’re done, please submit a zip file that includes the following files: