CS396: Spring 2022

Intro to Web Development

CS396: Spring 2022

Assignments > HW4. PhotoApp: Client-Side Templating with JavaScript

Due on Fri, 05/20 @ 11:59PM. 40 Points.

Update (Monday, 5/16 @8:30PM)

I just made a (pretty rough) video that may or may not be helpful.

Keep in mind that you should feel free to do it your way. And this is certainly not a production quality video, so forgive the meandering (long day :).

1. Introduction

In this assignment, you will be exploring an alternate strategy for creating front-end interfaces. Specifically, instead of rendering your HTML code on the server-side (using Jinja and Flask), you will be asking your Browser to build your UI for you using JavaScript. Within this design paradigm, the browser will load a very simple HTML “skeleton,” and then execute some “client-side” JavaScript (that you will write) to build the DOM.

You will also be implementing some event handlers to interact with the REST API that you made – in order to like, bookmark, and comment on posts; and to follow new users. And finally, you’ll continue your work to ensure that your interface is accessible.

A few notes and guidelines

  • You will be working on the follow / unfollow functionality during Lab 7 this week.
  • You will be working on some of the “post” and “modal” functionality in class during the week of 5/9. Please come to class with your files set up because it will be easier to follow along.
  • HW4 assignment is designed to take approximately 5-10 hours (depending on your level of experience). We encourage you to do a little at a time during class and in lab, so that you have enough time to engage with the concepts and complete the exercises without intense stress at the end.
  • You may NOT use any outside CSS or JavaScript libraries (other than Font Awesome). Everything should be done by writing your own “vanilla” HTML, CSS, and JavaScript.

2. Set Up

Please make the following changes to your code to get ready to make your client-side web interface:

1. Configure your local git repo

  1. On your terminal or command line, navigate to your photo-app folder.
  2. Make sure that hw03 is still your active branch by typing git branch.
  3. Next, create a branch called hw04 as follows: git checkout -b hw04. Since you created your hw04 branch from your hw03 branch, your hw04 branch should be currently be identical to your hw03 branch.
  4. Type git branch to ensure that you are indeed on the hw04 branch (it should be green with an asterik next to it).
  5. Push your hw04 branch to GitHub as follows: git push -u origin hw04
  6. Open GitHub in your web browser and verify that your hw04 branch is there.

2. Integrate the new files

Download hw04.zip and unzip it.

hw04.zip

You should see a directory structure that looks like this:

├── app.py
├── models
│   └── comment.py
├── static
│   ├── css
│   │   └── starter-client.css
│   └── js
│       └── hw04.js
└── templates
    ├── includes
    │   └── navbar.html
    └── starter-client.html

Please integrate the starter files as follows:

  1. Replace photo-app/models/comment.py file with hw04/models/comment.py (minor bugfix).
  2. Replace photo-app/app.py file with hw04/app.py.
  3. Copy the css and js folders from hw04/static into photo-app/static.
  4. Copy the includes and starter-client.html fromhw04/templates into photo-app/templates.

3. Update the views/post.py View (Read Carefully)

Please update both of your get methods in the views/post.py file by passing self.current_user as an argument to the post’s to_dict() method (see code below):

PostListEndpoint

def get(self):
    # your code above
    ...
    # updated to_dict method call:
    data = [
        post.to_dict(user=self.current_user) for post in posts
    ]
    return Response(json.dumps(data), mimetype="application/json", status=200)

PostDetailEndpoint

def get(self):
    # your code above
    ...
    # updated to_dict method call:
    return Response(json.dumps(post.to_dict(user=self.current_user)), mimetype="application/json", status=200)

By making this change to the Post object’s to_dict() method, the Post JSON object will include two new entries:

4. Verify Your Installation

Navigate to photo-app on your command line, and run flask (flask run). You should see the following screens when navigating to the following two pages (respectively):

Homepage:

This is the page you will be modifying for this homework: screen shot of the stories panel

API Tester:

This page may help you formulate your fetch requests using JavaScript: screen shot of the stories panel

In addition, your API Endpoints (from HW3) should all still work.

4. Tips

While we’ve provided some starter HTML and CSS…

…you are encouraged to use the HTML and CSS that you made in HW1 & HW2. If the starter code doesn’t help, feel free to do it your way.

3. Your Tasks

Working Demo

If you want to see a working demo of the completed HW4 interface (ignore the login screen), take a look here (username: webdev, password: password)

Please complete the following tasks by making modifications to:

You’re more than welcome to add more CSS & JS files as needed (though this is not necessary).

1. Page Initialization Tasks (8 Points)

The functionality in this section must be invoked when the page first loads (so that the user sees each of these panels right away).

Points Task Description Figure
0pts Stories Panel ALREADY DONE FOR YOU. Render an HTML representation of stories from the user's network using data from the /api/stories endpoint. Figure 4
1pt Right Panel: User Profile Inside of the right panel at the top, render an HTML representation of the current user's profile using data from the /api/profile endpoint. Figure 2
2pts Right Panel: Suggested Accounts Inside of the right panel (underneath the user profile), render an HTML representation of suggested user accounts using data from the /api/suggestions endpoint. Figure 3
5pts Posts Panel Underneath the stories panel, renter an HTML representation of the first 10 posts from the user's network using data from the /api/posts endpoint. Please ensure that the following rules are honored:
  • (Same as HW2) If there is more than one comment associated with the post, display a “view all n comments” button and the first post below it (replace n by the actual number of comments). Otherwise, display a single comment below the title of the post (if one exists).
  • If the current user has already liked the post, the heart icon should be red . Otherwise it should be hollow . Consider using the new current_user_like_id attribute included in the post object.
  • If the current user has already bookmarked the post, the bookmark icon should be black . Otherwise it should be hollow . Consider using the new current_user_bookmark_id attribute included in the post object.
Figure 5

Note that the content from each box should be generated from the API data (no hard-coding).

Figure 2: User Profile
screen shot of the stories panel
Figure 3: Suggestions
screen shot of the stories panel
Figure 4: Stories
screen shot of the stories panel
Figure 5: Post
screen shot of the post panel

2. Create / Delete Data with Event Handlers (15 Points)

Points Task Description Figure
2pts Like Post
  • When the user clicks the heart of "unliked" post, a POST request is issued to the /api/posts/likes/ endpoint.
  • If the POST response indicates success, redraw the post to indicate that the post has been liked. Ensure that the number of likes is updated.
Figure 6
2pts Unlike Post
  • When the user clicks the heart of "liked" post, a DELETE request is issued to the /api/posts/likes/<id> endpoint.
  • If the DELETE response indicates success, redraw the post to indicate that the post has been unliked. Ensure that the number of likes is updated.
Figure 6
2pts Bookmark Post
  • When the user clicks the bookmark button of "unbookmarked" post, a POST request is issued to the /api/bookmarks/ endpoint.
  • If the POST response indicates success, redraw the post to indicate that the post has been bookmarked.
Figure 7
2pts Unbookmark Post
  • When the user clicks the bookmark button of an "unbookmarked" post, a DELETE request is issued to the /api/bookmarks/<id> endpoint.
  • If the DELETE response indicates success, redraw the post to indicate that the post has been unbookmarked.
Figure 7
2pts Follow Account
  • When the user clicks the follow button of an "unfollowed" account, a POST request is issued to the /api/following endpoint.
  • If the POST response indicates success, redraw the button to indicate that you are now following the account.
Figure 8
2pts Unfollow Account
  • When the user clicks the unfollow button of an "followed" account, a DELETE request is issued to the /api/following/<id> endpoint.
  • If the DELETE response indicates success, redraw the button to indicate that you are no longer following the account.
Figure 8
3pt Add a Comment
  • When the user types a comment into the textbox and clicks the adjacent "post" button, a POST request is issued to the /api/comments endpoint.
  • If the POST response indicates success, redraw the entire post to display the new comment.
  • Ensure that the new comment is rendered to the screen and that the comment count increases to reflect the # of comments associated with the post.
Figure 9
Figure 6: Liking and Unliking

Note that each button click is issuing a request to your API and redrawing the screen (console messages just used for demonstration purposes).

screen shot of the post panel
Figure 7: Bookmarking and Unbookmarking

Note that each button click is issuing a request to your API and redrawing the screen (console messages just used for demonstration purposes).

screen shot of the post panel
Figure 8: Following and Unfollowing

Note that each button click is issuing a request to your API and redrawing the screen (console messages just used for demonstration purposes).

screen shot of the post panel
Figure 9: Add Comment

Note that each button click is issuing a request to your API and redrawing the screen (console messages just used for demonstration purposes).

screen shot of the post panel

3. Post Detail Modal (5 Points)

Finally, you will make a modal window that displays a more detailed representation of the post.

Points Task Description
2pts "View all X comments" Button Click
  • Modal box opens
  • Close button in top, right-hand corner
  • The rest of the page is blocked behind a panel so that you can't interact with the rest of the page
2pts Modal Body
  • The featured image is displayed on the and all of the comments on the right (as pictured)
  • All of the comments are displayed
  • The comment box scrolls
1pt Close Button Click
  • Clicking the close button will close the modal window
Figure 10: Post Detail in Modal Box

Note: in this example, the picture changes because of the way that picsum.photos works. Just ignore that for now.

screen shot of the post panel

4. Accessibility Features (6 points)

Accessibility can be tricky when you’re relying on the fetch API, because a screen reader doesn’t always know that content has changed on the page. In addition, you don’t want to be over-reliant on the mouse. Please take a look at the Accessibility Resources, and specifically the resources pertaining to aria roles and attributes.

Points Task Description
2pts 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.
  • Hint: if you use the HTML <button></button> element for all of your buttons, you get this functionality for free.
2pts Aria attributes Use the 'aria-label' and 'aria-checked' attributes 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 Modal Box (Post Detail) Please ensure that the following accessibility features have been implemented. See lecture 14 code samples and this online resource
  • When the modal opens, the close control should have the focus.
  • When the modal closes, the "View all X comments" button that triggered the modal to open should have the focus.
  • When the modal is visible / hidden, ensure that the aria-hidden attribute reflects the state of the modal.
  • Ensure that the modal has the appropriate role set (role="dialog")
  • Extra credit (2 points): When the user tabs from within the modal, ensure that the focus does not leave the modal.
  • Extra credit (2 points): make the "Escape" key close the modal (in addition to the close button), and make sure the focus still returns to the "View all X comments" button.

5. Accessibility Reflection (3 Points)

  1. In a brief reflective response (about 4-8 sentences total), please consider the following questions:
    • Why, and to whom, is accessibility important?
    • How might you make a site (or app) like Instagram more accessible?
  2. What resources did you consult as you implemented the accessibility features? Were there any that you found useful that aren’t on the Accessibility Resources page?
  3. Reflect on the work that went into making your website accessible.
    • Was it a lot of additional work?
    • What was the most challenging part?
    • Do you think that designing for accessibility also improves the usability of the site for all users? Why or why not?

6. Deploy to Heroku (1 Point)

Please commit all of your changes / additional files to git. When you’re done, create a NEW Heroku app for your hw04 branch. You will follow the same process as you did for the HW3 Heroku deployment, with two differences:

  1. Instead of creating a brand new Heroku Postgres database, just use the same DB_URL environment variable that you used in HW3. In other words, your HW3 and HW4 Heroku deployments will share a database.
  2. Make sure you push your hw04 branch to Heroku: git push heroku hw04:main

4. What to Turn In

Please review the requirements above and ensure you have met them. Specifically:

Points Category
8 points Page initialization
15 points POST / DELETE functionality
5 points post detail modal 
6 points Accessibility features 
3 points Accessibility reflection 
1 point Heroku deployment 
2 points Composition and CSS (the UI looks like the screenshots provided) 

Canvas Submission

When you’re done, please submit the following to Canvas: