CMPUT 404

Web Applications and Architecture

Flask and AJAX Lab

Description

Your task is to build a live, collaborative outline editing service.

Getting Started

  1. Get the github classroom link from eClass and clone it.
  2. Use virtualenv/pip to install flask.
  3. Create an appropriate .gitignore file to prevent unwanted files from being added to your repository.
  4. Follow the first steps of the Flask Quickstart guide: "A Minimal Application".
    • Name your app outliner.py.

In order to connect to your flask server inside WSL or another VM from outside WSL/VM, use flask --app outliner run --host 0.0.0.0 --debug.

User Stories

Lab Instructions

Have Flask Serve Files

You will need to send the correct Content-Type with each file. In flask you can do this by from flask import Response then returning from your handler like:

    return Response(icon_bytes, mimetype='image/x-icon')

After this step is complete you should be able to view the HTML in the browser, without getting errors in the browser. Check the console to make sure you don't have any errors.

Create Model Classes

Create model class(es) to represent the state of the outline. Think about what you learned in CMPUT 301.

Your class for outline items must be nestable (a tree) so that any item in the outline can have items inside of it. Each item needs to be able to store some text and sub-items. Your code must remember which items go inside of other items and the order of the items.

It does not need to save this to a database or file, it's fine to just keep it in memory.

Create API for Model

Each item in the outline needs a URL in the Flask backend that is accessible by the JS frontend.

In the JSON representation of the outline items, there must be an id key that gives the URL for the outline item. For example, GET /outline/8/9/ should return some JSON like:

{
    url: '/outline/8/9`,
    text: 'text of the item',
    children: [
        '/outline/8/9/0',
        '/outline/8/9/1'
    ]
}

You can use UUIDs instead of integers if you want, just as long as each outline item has a unique URL.

Do not have the API send the entire tree at once, it should only send the URLs for each child item.

Create the UI in JS

Create JS code to:

  1. Remove the "Loading...".
    • Hint: Use window.addEventListener('load', someFunction) to run a function once the page has loaded.
  2. Fill in the page.

There are at least three different ways to do this. Using document.createElement, appendChild, and remove to manipulate the DOM directly is probably the easiest. You can also use innerHTML to add multiple elements at the same time to the DOM. Using innerHTML creates potential security problems that we will discuss during the lectures on security later in the semester. A third approach is to register custom elements and add them to the DOM, or even using Web Components & Templates in combination with one of the two previous approaches.

Hint: Using proper OOAD will save you a lot of work. Apply the skills you learned in CMPUT 301. I suggest making model proxy classes that are responsible for synchronizing with the model objects in the Flask backend, by making calls using the Fetch API. If you only use "own properties" for things the server sends, you can serialize the model proxy objects to JSON for sending, and apply updates directly to the model proxy objects from deserialized JSON when receiving.

Hint: Using the "event.preventDefault();" on form submit events will prevent the browser from trying to submit the form, so you can handle form submission in your custom JS code instead.

Hint: A single DOM object can only be added to the DOM once.

Call the backend

Add polling

Add polling in your code to get live updates. Use fetch() and promises, not the old XMLHttpRequest.

Each browser window that has the outline open should be able to see all the changes that the other browser windows make in a reasonable amount of time (less than a few seconds).

Make sure that the updates don't "clobber" or overwrite or reset whatever the user is typing. The easiest way to do that is to remember what the server sent previously for an item, and not update the HTML DOM unless the server sends something different from what it sent the last time.

For simplicity, you can ignore the conflict problem when two people are editing the same outline item at the same time.

Use Fetch API, not XMLHttpRequest.

Hint: The input event of a text type <input> will happen every time the text changes at all (every keypress if the user istyping.) The change event only happens when the user changes their focus to a different element.

Optimize Communications

Optimize communications so that the frontend doesn't have to ask the backend for the details of unchanged items.

Optional: Also consider adding code to make sure the frontend doesn't make another request to the same endpoint while the first request is still in progress. You can do this by using the finally() method on a promise to run code whether or not the promise resolves or rejects.

Optional: Also consider adding code to batch updates to the backend, e.g. instead of every keypress while typing, limit PUT requests to one update per second while typing.

Make it look nice

Add CSS to make your outline look nice. You should give it your own personal style, but it should be pleasing and easy-to-use.

Restrictions

Violation of the restrictions will result in a mark of zero.

Requirements

Submission Instructions

Make sure you push to GitHub classroom BEFORE 4PM on the due date! You will not be able to push after that!

Submit a link to your repo in the form https://github.com/uofa-cmput404/w24-h0x-labsignment-flask-yourgithubname. Do not submit a link to a branch, a file, or the clone URL. If you do not do this we will not know which GitHub submission is yours.

If you do not submit a link to your repo on eClass on time using the correct format above, you will get a zero.

Collaboration