Assignments > HW6. PhotoApp: Various Extensions
Due on Fri, 03/18 @ 11:59PM. 40 Points.
For your last homework assignment, you have two options:
- Implementing a React version of your Photo App
- Implementing a chat interface to interact with users with whom you have a mutual following relationship (you follow them AND they follow you).
Option 1: React Re-Implementation
Overview
At a high level, we want you to re-implement your HW4 code in way that follows React conventions. A few ground rules:
- 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.
- You can use third-party libraries if you want (but it’s not required).
- 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.
- 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 inpackage.json
to: https://photo-app-secured.herokuapp.com/.- If you’re switching between the course API and your API to debug, note that you’ll either have to clear out your
access_token_cookie
manually (by physically deleting it using the Application panel of your browswer’s developer tools) or else use the same JWT_SECRET as the course application (set in your.env
file), which is MY_SECRET (e.g.,JWT_SECRET=MY_SECRET
).- By default, your JWT token will time out every 15 minutes. To make your life easier, consider extending the life of your JWT token by adding the code below to your
app.py
file:
# Import timedelta at the top:
from datetime import timedelta
# Put this setting with all of your other JWT settings:
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(days=30)
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:
|
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.
|
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:
|
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:
|
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:
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.
|
5pts |
LikeButton.js Like / Unlike Post |
Create a LikeButton component that will:
|
5pts |
BookmarkButton.js Bookmark / Un-Bookmark Post |
Create a BookmarkButton component that will:
|
5pts |
AddComment.js Add a Comment |
Create an AddComment component that will:
|
1pt | Keyboard Navigation |
|
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:
|
2pts |
Form Accessibility Extra handling for "Add Comment" |
|
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).
|
Deployment Instructions (Optional)
In order to deploy your React code, you have two options.
1. Create a Stand-Alone React App
- Create a git repository that has your react app as a top-level directory (see suggested file structure below).
- Create a
.gitignore
file that excludes thenode_modules
andbuild
directories (see below). - 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).
- 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. - Commit and push your new repo.
- Create a new Heroku instance and connect it to your new GitHub repo.
- Deploy (just like you did in previous homeworks).
- Note that you don’t need to configure any environment variables – Herou will automatically read your
package.json
file, install the dependencies, and create a production build for you.
- That should be it!
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
- 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 toreact-client
. - Create a
package.json
file at the root of your Flask app (note that this is in addition to thepackage.json
file inside of yourreact-client
directory) that has the JSON format shown below.- This file tells Heroku to compile your react app from within the
react-client
subdirectory.
- This file tells Heroku to compile your react app from within the
- 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
.
- You will also need to install this library on your local machine:
- Modify your
app.py
as shown below. - Ensure that your
react-client/node_modules
andreact-client/build
folders are excluded from git via your.gitignore file
. - Commit and push your changes to GitHub.
- Create a new Heroku instance and connect it to your new GitHub repo.
- Install the Node buildpack (Settings Tab > “Add Buildpack” button > nodejs)
- Deploy (just like you did in previous homeworks).
- Herou will automatically read your
package.json
file, install the dependencies, and create a production React build for you.
- That should be it!
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')
Option 2: Chat Interface
Introduction
In order to build a chat interface, you will:
- Extend the flask code (both the client and the server functionality) from HW5. Recall: the Flask server’s job is to serve data (via the REST API) and the HTML/CSS/JavaScript files that control the user interface.
- Extend the web socket server you created for Lab 8. The web socket server’s job is to ensure that authenticated users can relay messages to their contacts.
Both servers will need to be run simultaneously (Flask on port 5000, Web Sockets Server on port 8081) in order to complete the assignment.
Set Up
- In your
photo-app
codebase, please create a new branch for your HW6 updates. See previous homeworks for instructions for creating a new branch. - Download the Lab 8 solutions from Canvas and save them somewhere that makes sense. You will be modifying and running the
server/app.py
file, which will be the basis for your chat server.
Please complete the following tasks:
Points | Location | Task | Description |
---|---|---|---|
5pts | Flask Server |
REST API Endpoint/api/contacts
|
Create a new REST API Endpoint, /api/contacts , that returns a list of the user's contacts. A contact is a reciprocal relationship. Given two users A and B: A follows B and B follows A.
|
5pts | Chat Server |
Authentication JWT Validation |
Instead of letting anyone use your chat server, you will now only allow authenticated users to use the chat server. Users will authenticate by including a valid JWT token (issued by your Flask app) in their chat messages. To enable this:
|
5pts | Chat Server |
Fetching Contacts Track the user's network |
If the message "type" is "login":
|
5pts | Chat Server |
Relaying Messages Make sure that messages only go to the intended recipient |
|
5pts | JavaScript Client |
User Interface Chat Server Login |
|
10pts | JavaScript Client |
User Interface Chat Box |
|
5pts | Accessibility |
User Interface Chat Box and Contacts |
Chat interfaces dynamically inject new elements into the DOM as messages are broadcasted from the web sockets server. To make a screen reader aware of these changes, please complete the following tasks:
|
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 | Chat Interface | Implement the chat interface using React instead of vanilla JavaScript. |
3pts | Chat Interface | Modify the list of contacts in the right-hand panel such that the contacts who are logged in are displayed before the contacts who are not logged in. |
5pts | General | Enhance your code so that you can include more than one of your contacts in the chat. |
Accessibility Reflection
If you already completed this in Lab 9, you can skip it. But in case you missed it…
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.
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 totally 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.
What to Turn In
Please review the requirements above and ensure you have met them. When you’re done, please submit the following to Canvas:
- A zip file of your code
- If you completed the chat interface, be sure to zip both your Web Socket Server code and your Flask Server code.
- A comment that includes the following:
- A link to your most recent Heroku app (even if you didn’t deploy your HW6, which was optional)
- The name of your partner (if applicable)
- Which option you pursued (React re-implementation or chat interface)
- Which extra credit options you attempted (if any)