Up to now, and maybe without realizing it, you have been developing the server side (backend) of a web application. In this checkpoint, you will give your project a frontend (AKA - a client side implementation)! A frontend allows for an end user to access your project through a user interface (UI). The previous two checkpoints (C1 and C2) built the backend of your application and although your tests can access your methods, it would be hard for a user (like a parent or friend) to use them. In C3, you will complete your application by building a frontend to allow easy access to your backend methods (addDataset, removeDataset, listDataset and performQuery).
In this checkpoint, there are two phases. Phase 1 involves designing and writing the user stories of your frontend, while Phase 2 involves actually implementing them. Your frontend should also use REST API calls to communicate with your backend, and so Phase 2 also includes the task of implementing a REST API server.
Note, you can and may want to work on elements of Phase 2 during Phase 1. For example, you can begin implementation of the REST API user story and initialize your chosen frontend. If choosing a frontend that you are less familiar with it might be worth doing a proof of concept to make sure implementation will go smoothly.
Choose the type of frontend you will build
Write and submit two user stories (graded)
We will use the acceptance criteria of these users stories to grade your C3 frontend implementation.
Implement the Web server. (graded by AutoTest, smoke tests provided)
Implement your two frontend user stories.
Demo your application to your TA during your final lab (graded)
ATTENDANCE TO YOUR FINAL LAB IS NECESSARY TO RECEIVE A C3 GRADE.
The schedule contains the due dates for Phase 1 (User Story Submission) and for Phase 2 (Demo).
You can choose any frontend for your project! Have some fun, go a little wild! The only requirement is that all frontend code resides in a /frontend directory in your project_teamXXX repository. We will be providing starter code for a basic Web frontend and Braxton has built starter code for a Discord frontend. Both frontends require installing new node packages and similarly, you can install additional packages as needed by your own frontend of choice! You can also choose any language for your frontend.
You should select your frontend before writing your frontend user stories, as it will provide context for how your end-user will interact with your application.
If you select the Web as your frontend and choose to use our bootstrap, you will build a website using HTML, CSS and plain JavaScript which will send REST API calls to your server. You can demo your website locally, by starting the server and clicking elements in the UI to perform a task for your end user. If you select Discord as your frontend, your end user will interact with your server via Discord! They can send messages, which will be listened for by your Discord bot and then forwarded to your backend. There will be more implementation details on both of these frontends in the Implementation section.
Disclaimer! TAs are most likely only familiar with the Web frontend, as that has been used in previous semesters. The TAs will not be able to provide the same level of support for alternate frontends.
During the first phase of C3, you will write user stories that outline how your end-user can use your frontend application to achieve desired outcomes. In the second phase, you will then design and implement the code to realize your user stories.
You are required to provide a minimum of two user stories involving the frontend UI. Though you're free to write and implement more than two user stories, you will be graded based on just two of them.
A user story should describe the type of user, what the user wants to do with your application, and for what benefit.
Note: A user story should be in general be agnostic of your frontend of choice. It should encode "what" the user can do with your application, not "how". The "how" belongs to the Definitions of Done (more about this in next section). Simply put, if you find yourself describing your UI in a user story, be aware!
You should use the Role, Goal, Benefit framework:
As a [role], I want to [goal], so that [benefit].
[role]: Who is using this?
[goal]: What is the user trying to achieve?
[benefit]: Why does the user want to achieve this?
For each user story, you will write definitions of dones (DoD) that define the conditions your application must meet before it is accepted by the user of the story. In other words, DoDs are agreement between you and your user about when an application feature is considered “done”. For each user story, the DoDs should describe "how" your frontend application supports the user in achieving the said goal. Please think of both the successful and failure cases.
Your DoD should follow the Given/When/Then framework:
Scenario: The name for the behaviour that will be described
Given: Some initial application state (precondition)
When: The user do some series of action
Then: Some outcome state is expected (post-condition)
You will write two frontend user stories which will be implemented and demo-ed at the end of the semester. When demo-ing your user stories during the final lab, we will use the exact DoDs you've submitted to judge whether you have completed them. We will provide feedback on your user stories and it is important that you take that feedback into consideration for your implementation in Phase 2.
The scope of a user story is subjective, but to receive full marks your user story + DoDs must:
Follow the format outlined in the above section: Role, Goal, Benefit and Given/When/Then.
Solve a use case for the user. For example, a user that loves sushi would like to see the best sushi restaurants in Vancouver.
Be end-to-end. It must involve both your frontend and backend to provide feedback to the user. A user story must be evoked by a user interacting with your UI, which causes a request to the backend. The backend then responds and the UI updates with visual feedback. For example, when I click “search” in Google, I expect to see a list of search results compiled by some backend servers running at Google.
Follow the INVEST principles! (Independent, Negotiable, Valuable, Estimable , Small, Testable)
NOT be a recreation of the Campus Explorer UI (ie. JSON query input with a table output)
Note: We are not marking the aesthetics of your frontend (rounded corners, pretty colours). The marks will be based on satisfying your DoDs.
There will be a pull request made with a template markdown file, which you are required to use. Before the user stories submission deadline, please make a commit to the master branch of your team's repository with this file containing your stories + DoDs. During your respective labs of the week following Phase 1 deadline, you and your TA will be going through the user stories together for you to receive feedback.
As an example, for a user story, “As an online bank user, I want to be able to log into my account, so that I can access my banking information online,” you may have these DoDs:
Scenario 1: Correct credential
Given: The user is on the login page
When: The user enters a valid card number and password pair and clicks “Log in”
Then: The application logs the user in and presents the dashboard page
Scenario 2: Incorrect credential
Given: The user is on the login page
When: The user enters an incorrect card number and password pair and clicks “Log in”
Then: The application remains on the login page and shows an error in red telling the user to try again
In order to respond to requests from your frontend UI, you will complement your backend with a Web server that surfaces your InsightFacade methods. This means adapting your existing InsightFacade to also be accessed by any potential frontend, using REST endpoints. Both InsightFacade and the REST endpoints must continue to work independently.
Your Web server will need to provide the following REST endpoints exactly as they are specified, because your client (ie. AutoTest) will leverage on these endpoints to access your InsightFacade methods.
PUT /dataset/:id/:kind allows one to submit a zip file that will be parsed and used for future queries. The zip file content will be sent 'raw' as a buffer in the PUT's body, and you will need to convert it to base64 server side.
Response Codes:
200: When InsightFacade.addDataset() resolves.
400: When InsightFacade.addDataset() rejects.
Response Body:
{result: arr}: Where arr is the array returned by a resolved addDataset.
{error: err}: Where err is a string error message from a rejected addDataset. The specific string is not tested.
DELETE /dataset/:id deletes the existing dataset stored. This will delete both disk and memory caches for the dataset for the id meaning that subsequent queries for that id should fail unless a new PUT happens first.
Response Codes:
200: When InsightFacade.removeDataset() resolves.
400: When InsightFacade.removeDataset() rejects with InsightError.
404: When InsightFacade.removeDataset() rejects with NotFoundError.
Response Body:
{result: str}: Where str is the string returned by a resolved removeDataset.
{error: err}: Where err is a string error message from a rejected removeDataset. The specific string is not tested.
POST /query sends the query to the application. The query will be in JSON format in the POST's body.
NOTE: the server may be shutdown between the PUT and the POST. This endpoint should always check for a persisted data structure on disk before returning a missing dataset error.
Response Codes:
200: When InsightFacade.performQuery() resolves.
400: When InsightFacade.performQuery() rejects.
Response Body:
{result: arr}: Where arr is the array returned by a resolved performQuery.
{error: err}: Where err is a string error message from a rejected performQuery. The specific string is not tested.
GET /datasets returns a list of datasets that were added.
Response Codes:
200: When InsightFacade.listDatasets() resolves.
Response Body:
{result: arr}: Where arr is the array returned by a resolved listDataset
The :id and :kind portions above represent variable names that are extracted from the endpoint URL. For the PUT example URL http://localhost:4321/dataset/mycourses/courses, mycourses would be the id and courses would be the kind.
In addition to the above endpoints, you’re free to add more as you need to implement your two frontend user stories.
Note: Those of you paying attention in lecture may notice that this is not a very RESTful API. As an exercise, consider how you could modify one of the endpoints to make a more RESTful API! (But please don't actually modify, as AutoTest depends on this exact specification)
You will implement the two user stories you have written and received feedback for in Phase 1. Please make sure to review and closely follow the corresponding DoDs for each story, as you will be expected to demo the workflows in the DoDs during your final demo.
Below is a list of things you CAN do when implementing your frontend user stories:
Use all/some of the REST endpoints provided by the REST API user story. For example, you can use the endpoint to list the results of a general or specific query.
Create a new backend REST endpoint.
Create a new backend controller to add a new method for a new endpoint. However, you cannot alter the IInsightFacade interface in any way. You must create a new class/file if you'd like to add a new method for an endpoint.
This is by no-means exhaustive however. If you have an idea but unsure of whether it is acceptable, check-in with your mentor TA for advice!
We are providing a few starter codes, some required, some optional.
Once you merge this pull request from Autobot, you'll have three new files in your project associated with the implementation of a Web server:
src/App.ts contains the source code for starting the application and initializing the server. This will be given to you for free.
src/rest/Server.ts contains the logic for your server.
test/rest/Server.spec.ts contains the tests for your server.
Both the Server.ts and Server.spec.ts files will contain some sample code to point you in the right direction. We will use express as a REST server library. Please refer to its documentation first whenever questions arise.
There will be an optional pull request from Autobot for the web frontend. We’ve provided a simple implementation that contains a button that when clicked shows an alert.
You will also need to uncomment the following line in your Server.ts file:
this.express.use(express.static("./frontend/public"))
This line is what servers your frontend UI sources to the root of your application.
The subdirectory /public contains the static sources that will be hosted by your Web app:
index.html contains the starter HTML code for the UI. This file is hosted by the GET/ endpoint of your REST server. This will already be implemented in the bootstrap as well.
style.css contains the styles for the UI.
frontend.js will contain the logic to listen to the button click event and show an alert.
There are two new aspects to the Web frontend that you haven't seen in early checkpoints:
Plain JavaScript. While it is theoretically possible to develop in TypeScript on the frontend as well, using plain JavaScript has the advantage that you won't have to build/compile your project when you work on the frontend.
Browser. You will dive into the world of browsers with your frontend implementation. Your frontend code will be run client-side in the browser and will communicate with your Web server via REST/Ajax calls. This means also that you will have the global window, document and XMLHttpRequest objects from the browser available anywhere in your code.
Please checkout the starter code in this repository: https://github.com/braxtonhall/bot-starter.
It may also be useful to view the discord.js package: https://www.npmjs.com/package/discord.js
A new yarn command yarn start will be available in your project through a change to package.json (included in Web Server bootstrap). It will essentially run App.js as a node application. Once you have started the server, you'll be able to access the app in the browser at http://localhost:4321. Please note that your datasets must be available in priori for the UI to work. There are a couple of ways of ensuring this. You could find a way to call addDataset by hitting one of your REST endpoints from a client, or keep a cached copy of your data around and just paste it into your ./data folder so the server can load it from disk.
The same libraries and frameworks as before (Mocha, Chai) will be used for testing. This time, however, your tests will have to send requests to your backend and check the received responses for validity.
Note: The response formats for the 2XX and 4XX cases may look slightly different. You should use the debugger to inspect the responses to determine where to find the values you want to test.
To run the smoke tests, you can call AutoTest with @autobot #c3 on the commit of interest on the master branch.
As with before, @autobot #c0 is updated to accommodate C3 server tests against the reference implementation.
Your final project grade consists of 1. Client check-in test score at Final Project Deadline, 2. User stories & demo.
This is the AutoTest-tested portion of your project grade, which evaluates C1, C2 functionalities cumulatively. For C3, the required story's implementation (Web server and REST APIs) is tested by AutoTest and will also contribute to this portion.
Phase 1: User Story Submission (4%)
Frontend user story one (2%)
Frontend user story two (2%)
You will receive a 0, 0.5 or 1 for each user story. 0 = no effort, 0.5 = missing key element, 1 = wahoo!
We will not be accepting LATE submissions. You will not get feedback from your TA or a grade if you submit late.
Phase 2: Demo (16%)
Frontend user story one (8%)
Frontend user story two (8%)
You will receive a 0, 0.5, or 1 for each user story. 0 = no effort, 0.5 = some DoDs not met, or major bug, 1 = wahoo!
There is no best way to get started, but a few hints may help you:
Create the big picture of your project in your mind. Use pencil and paper and draw some diagrams. Where is what component and how do they interact with each other? What's on the client and what's on the server?
For selecting a frontend - what frontends are both yourself and your partner familiar with? If choosing a frontend other than web, it may be worth doing a small proof of concept to ensure you can successfully complete C3.
The two parts in this checkpoint (server, frontend) should be implemented and tested independent from each other. They are only hooked together with Ajax requests going from the frontend to the server but all parts are designed to be implemented and tested independently.
Good luck and we sincerely hope you'll also have some fun implementing this checkpoint!
Q. How can I make sure my backend already has datasets that my frontend can query?
You could of course implement the ability for an end user to add a dataset from the frontend UI, but this is sometimes complex (and may not be one of your user stories). For all frontends it is not necessary to provide a way to upload a dataset. Instead you can start your server with pre-existing datasets in your /data directory to load it into your InsightFacade instance.
Q. I'm still working to finish C1/C2, how would these checkpoints affect my C3?
C3 is can be almost entirely independent from C1 and C2, except for the required REST endpoint user story. Here, in order to test your endpoints, the client can use functionalities from C1/C2 to interact with your backend. However, your two custom user stories can be designed such that only pre-implemented parts of your C1/C2 will be used.