CAB230 Web Computing Assignment 1 Specification
The ‘Happiness’ Client Application
Release Date: Monday, April 12 2021 (Week 6) Submission Date: Monday, May 10 2021 (Week 10)
Weighting: 45% of Unit Assessment
Task: Individual Project
[Note that there were no changes from the early-release version.]
Introduction
This assignment requires that you develop a React-based web application to allow users to view and analyse ‘happiness survey’ data drawn from a database that we have created for this purpose and exposed via a REST API. We will talk about this API in detail below, and you will implement a version of this backend as your task for the second assignment.
The aims of this assignment are to:
• Allow you to build a sophisticated client web application using modern approaches
• Provide experience in querying REST APIs and presenting the results for your users
• Provide experience with modern web technologies including React and node.js
We will now introduce the data and the API. We will then tell you what you have to do. Pay particular attention to the task highlights. We will give examples of API usage, and show some screenshots from a React app that implements some of the desired functionality, but pays no attention to styling. This app is a guide only, and you are free to design the UI to be quite different in structure as long as the same level of functionality is supported.
Task highlight: This specification is not very prescriptive, and you should feel free to exceed it
if you wish to explore the technologies. But the assignment is best completed in stages, with
each new step allowing you to look at a higher grade level. Each feature requires a base level
of functionality and a component – often a form or a table – to support it. Some more
advanced features like graphs are not required for a passing grade. We discuss these choices
in the final sections of this specification.
The Data:
The dataset is based on publicly available data released as part of the World Happiness Report (https://en.wikipedia.org/wiki/World_Happiness_Report), an initiative of the United Nations. The report provides extensive information on societies and sustainable development, but we
are concerned with their country rankings data set. In the survey, as many as 157 countries are ranked according to an overall ‘happiness score’, with ratings also provided on a range of related factors. This is explained as follows in the Wikipedia article:
Data is collected from people in over 150 countries. Each variable measured reveals a population- weighted average score on a scale running from 0 to 10 that is tracked over time and compared against other countries. These variables currently include:
• real GDP per capita
• social support
• healthy life expectancy
• freedom to make life choices
• generosity
• perceptions of corruption
The table of data as released has the following form (the example is a screenshot from the Wikpedia article for the 2020 data):
The database to be used for this unit – for both Assignment 1 and Assignment 2 – contains the 935 records for the survey rankings for the six years from 2015 to 2020. We have summarised the factors to allow shorter column names as shown in the image on the next page (using the MySQL client). However, in Assignment 1 you will not work with the database directly. All interactions will take place via our published API. You will be able to retrieve records from the database using HTTP GET operations. We will talk about these in more detail below. Some of these will be available to everyone, some will require authentication – i.e. the user will have
to register and login to the site. You will need to handle the registration and login process from your application through appropriate HTTP POST requests.
Most of your work will focus on the data. You will display the results from queries over the data set. If the expected response is a single record, you should tailor your display component to suit. If the result is an array of records – as will often be the case – then obviously we will expect that your application will include some use of a table display. The Week 6 prac is based on ag-grid react. This component readily supports advanced features such as filtering and sorting. You may also wish to consider the use of charting to help your users understand the trends in the data – we will consider that further below.
The REST API
We now consider the REST API in more detail.
Accessing the Documentation:
The REST API is documented on the page at: http://131.181.190.87:3000/. These docs use the Swagger (https://swagger.io/) documentation tools. We will teach you how to use these as part of the server side pracs. If, like most of the class, you have never seen Swagger before, please have a brief look here: https://swagger.io/docs/specification/about/. Essentially Open API allows very professional documentation to be generated quickly and painlessly. It is really, really helpful.
The Swagger Docs are your primary source for anything to do with the API during Assignment 1 and Assignment 2. They will be maintained more regularly than any written assignment specification, and they have executable examples. If there is any conflict in the information we provide, or something is unclear, the Swagger Docs win.
The server is behind the QUT firewall. If you are off-campus, you will need the QUT VPN:
https://qutvirtual4.qut.edu.au/group/student/it-and-printing/wi-fi-and-internet- access/accessing-resources-off-campus.
This link is also available in the Assignment 1 Folder on BB.
The Structure of the Endpoints:
As noted above, the endpoints include a mix of open and authenticated routes. The best way to think of this is to assume some difference between ‘free’ content and content which is only available to members. Once the user is registered, they can log in and access the ‘members only’ content. I’m not sure many people would actually pay for the members content we are offering here, but that is the way the site is organised. The example app screenshot below shows a simple registration form below the main navigation menu:
Task highlight: Your application must allow the user to navigate cleanly between data queries
and user registration and login functions. The precise organisation will depend on your design,
but these must be clearly separated in a menu. The example above should give you a good
starting point, but it obviously lacks a bit of styling. Please see the Styling React Components
worksheet for very good navigation examples using React.
The task highlight above talks about a split in the client side functionality. There is a similar (and related) split in the types of API endpoints: Data and Authentication, as seen in the screenshot above. The Data routes are further split into those available to all users (/rankings and /countries) and one requiring authorization (/factors).
Users wanting to access the members-only content must interact with the Authentication endpoints. New users may register to become members of the site (/user/register) and they can then login to the system (relying on /user/login) to gain access to the
authenticated route. In the screenshot above, the /factors endpoint shows an open lock icon, indicating that authorization is required but has yet to be provided. In the paragraphs below, we will talk about how to do make this work.
Task highlight: Your application must handle registration and login on the client side. This
basically requires that you implement two POST operations that interact with the register
and login endpoints. These requests will have a very similar format. You should design and
use a form component – like the one shown above for registration – to handle these, though
the responses from the server will be different.
We will discuss authentication properly below and in week 71, but for now we will work with the Swagger examples, and you can implement authentication when you are better equipped to do so.
When you login via the /user/login endpoint, the server will send you a response TOKEN, which is just a long random string. Your application will store it, and you will use it to prove that you are an authorized user when you are trying to access an authenticated route. In our case, the system will send it to you as a JSON Web Token (https://jwt.io/). The JSON will look a lot like the image below, excepting that the token itself will be much longer and far more random (I have edited a real one for space reasons). When the system needs it for the ‘members only’ content, you will include this JSON in the parameters to a fetch() call.
We will show you how to work with JWT tokens in the Week 7 prac sheet. This is all straightforward, but it would be too much in one go. However, you can follow this process by using the Swagger doc examples to first register and then login using the same credentials. The response from the login will be very similar to the example above, and you can now grab the actual token and use it in the authenticated route on the Swagger. If you take a look at the Swagger image above, you will see a green button with an open lock icon as shown below:
Click on this button and you will see the Authorization dialogue:
1 None of the material on authentication or JWT will make any sense until you have a better idea of the structure of a server side application. We will get to that quickly in Week 7.
Copy the token from your version of JSON above and paste it where I have my fake `myJWTTokenHere` in the image. Click on the green button and close the dialogue and you will see that the locks are now shut and the grey icon is now black. You are now able to use the authenticated route in Swagger.
The API Endpoints in Detail:
We now consider the Data routes in turn. Each of them is a GET, and the first two are not authenticated. The error conditions and precise usage you can discover by playing with the Swagger docs. Here we are concerned with the types of data that come back and what we will expect you to do on the client side.
This first route returns happiness rankings in descending rank order, year by year. In the view below I have edited the results to show a manageable list of 10 countries for 2020. In reality, the raw request yields the full ranking lists back to 2015, some 935 records in total.
[
{“rank”:1,”country”:”Finland”,”score”:”7.809″,”year”:2020}, {“rank”:2,”country”:”Denmark”,”score”:”7.646″,”year”:2020}, {“rank”:3,”country”:”Switzerland”,”score”:”7.560″,”year”:2020}, {“rank”:4,”country”:”Iceland”,”score”:”7.504″,”year”:2020}, {“rank”:5,”country”:”Norway”,”score”:”7.488″,”year”:2020}, {“rank”:6,”country”:”Netherlands”,”score”:”7.449″,”year”:2020}, {“rank”:7,”country”:”Sweden”,”score”:”7.353″,”year”:2020}, {“rank”:8,”country”:”New Zealand”,”score”:”7.300″,”year”:2020}, {“rank”:9,”country”:”Austria”,”score”:”7.294″,”year”:2020}, {“rank”:10,”country”:”Luxembourg”,”score”:”7.238″,”year”:2020}
]
The selection may be filtered using the query parameters year and country, allowing you to return, say, a JSON array of the results for Norway: /rankings?country=Norway
[
{
},
—- records for 2019, 2018, 2017 and 2016 deleted for space reasons —- {
“rank”: 4, “country”: “Norway”, “score”: “7.522”, “year”: 2015
} ]
“rank”: 5, “country”: “Norway”, “score”: “7.488”, “year”: 2020
Alternatively, you can grab the results for the year 2016: /rankings?year=2016
Obviously, there are a lot of them. You may also combine the two query parameters. Here we will look at Norway in 2017: /rankings?country=Norway&year=2017
Note carefully please that this still returns an array of records (JSON objects) – this is often a problem for people who are new to working with API calls: make sure that you understand the return types you are dealing with.
[{“rank”:1,”country”:”Denmark”,”score”:”7.526″,”year”:2016}, {“rank”:2,”country”:”Switzerland”,”score”:”7.509″,”year”:2016},
—- Lots of entries deleted for space reasons —-
{“rank”:156,”country”:”Syria”,”score”:”3.069″,”year”:2016},
{“rank”:157,”country”:”Burundi”,”score”:”2.905″,”year”:2016} ]
[ {“rank”:1,”country”:”Norway”,”score”:”7.537″,”year”:2017}
]
Task highlight: Dealing with data records of this type is a core part of the client side task. The
obvious display for this response will be some sort of formatted table. In designing this part of
your application you will need to consider the inputs needed to support this query to the server
– hitting this route in response to a button click for example – and the appropriate way to
specify the text for people using the country filter. Could you use a drop down box to specify
the year? How are you going to handle data once it reaches the application? What about
pagination, sorting by column, filtering by column – does it make sense to have filtering based
on free text? What about styling, handling error conditions? What if the call to the server fails
to return any data? Can you make all of this look clean to the user?
This simple table display from the example app relies on ag-grid react – as covered in the Week 6 prac sheet. This component provides a lot of functionality out of the box. The screen shot shows pagination, but sorting and filtering are also readily implemented:
This is a very simple unauthenticated route which just returns a list of countries to help you manage querying the API. There are a lot of them, and this endpoint gives you the exact strings as used in the database. Hitting this endpoint just returns a simple JSON array of the country names. You can see this in the view below.
[ “Afghanistan”,”Albania”,”Algeria”,”Angola”,”Argentina”,”Armenia”,”Australia”,
—- lots of countries deleted here —-
“Uruguay”,”Uzbekistan”,”Venezuela”,”Vietnam”,”Yemen”,”Zambia”,”Zimbabwe” ]
Task highlight: Working with this endpoint requires that you think about how the user is going
to get information from the API. How will your client side application use the /rankings
and /factors endpoints? There are a range of options here. I will explore some of them
now, but you have to design your UI and make these choices. Does it make sense for you to
have all of the countries in single drop down? Can you organise the UI so that the 150+
countries are grouped by region? So, could you have two drop downs? The user could choose
from a list of continents – Asia, Europe, North America, South America, Africa, Oceania – and
your country drop down can include only those countries in the selected continent. Could you
use a search box instead or as well? Could people enter the beginning of a country name, like
‘Aus’ and get a table of results which would allow us to click through to the individual country
data? Could you integrate the search into the country drop down? Could you provide type
ahead support? Some of these ideas are easy, some are hard. Work with the easy ones to start
with and get something working. Then you can think about what to do next.
The screenshots below should give you some ideas on how to work with this for the data that come back from the /rankings endpoint. Remember, if we query by country, we get an array of JSON records of that country’s rank and score over the years 2015-2020.
Note that the search option indicated here does not in this form handle the /factors endpoint. And as we will discuss below, graphing is only required for higher grade levels.
The final endpoint requires authorisation, which means that your users have to login before using it. The /factors endpoint provides full details of the overall happiness score and the six ‘happiness factors’ for each country organised according to the year. For this route, the year is given as a path parameter. So if I want the full list of happiness factors for the year 2019, I need to run with /factors/2019. The route also supports a query parameter called limit which limits the number of records returned, and so if I use /factors/2019?limit=10 I get the results shown below:
[
{
“rank”: 1,
“country”: “Finland”, “score”: “7.769”, “economy”: “1.340”, “family”: “1.587”, “health”: “0.986”, “freedom”: “0.596”, “generosity”: “0.153”, “trust”: “0.393”
},
—- ranks 2 to 9 deleted for space reasons —- {
“rank”: 10, “country”: “Austria”, “score”: “7.246”, “economy”: “1.376”, “family”: “1.475”, “health”: “1.016”, “freedom”: “0.532”, “generosity”: “0.244”, “trust”: “0.226”
} ]
While we will not consider it in detail here, there is also another query parameter called country which allows you to return the record for a single country for the specified year. Please see the Swagger docs for more details of the call and the format of the response.
Task highlight: Here a table is again the obvious basic approach, but you will need to think
about the number of records that might come back and how to limit them. You don’t really
want to be grabbing 150 or more records each time you come to this page. Once you have
them in a table, you can take advantage of the usual facilities of the table component. But
there is also a chance to show some comparisons across the list for the happiness factors. In
the screenshot below, we see the use of bar charts for each of these factors, which is an
appropriate way of displaying the data. (Again, note that there should be some styling applied
here – we have used none). There are three other points to note here:
• If you are graphing the data, be aware that it is hard to see what is going on if the
number of bars gets larger than 10 or 15, so think carefully about the display.
• Don’t ever use pie charts for something like this. Pie charts are terrible at any time, but
especially as the number of alternatives increases.
• If you are restricting results to a single country, then the graphs will look pretty silly.
So maybe think about turning the graphs off when you only have one record?
The Formal Requirements:
This assignment requires that you make a lot of choices. These decisions are obvious after you have done a few apps, but they are harder if you are doing this for the first time. At the most basic level, you must develop a client side web application that allows the user to work with each of the endpoints, but without the user ever really being aware of the underlying work. The user doesn’t want to know anything about the underlying calls to the API. In the task highlights above I have given you some guidance on what we need to see, and you should think very carefully about the forms that allow us to enter the data and the components that
display the responses, and the ways in which we move between them. We expect that you should be able to successfully process all of the endpoints. You should choose suitable interface elements to display and interact with the information. We will give you some latitude in this, and you can also get some ideas from the images above and the discussion below.
Some Guidance on Design:
Landing Page:
What will your users see when they first launch your app? Often there will be a hero image and a welcome message? Or sometimes people decide on a default view – like a table of some subset of the data. Whatever your choices, you should make sure that the navigation remains clear to the user. The image below was thrown together in 5 minutes in Powerpoint. As a design, it is awful, but as an initial exercise in working out where things should go, it is fine.
Your layout should be chosen to facilitate the information that will come when we hit the endpoints and use the display components you are developing. You should think about how you intend to present the information together as it changes from screen to screen. Sketch the screens on paper or in a slide deck, and think about the transitions between them.
Routing:
For each route in this client side application you should think about how you are going to handle it – have a look at the React Router examples in the lectures and in the Styling Components worksheet. You may use a basic HTML menu but the use of React routing will attract much more credit.
Choice of Widgets:
Some of the endpoints need parameters and you will need to choose how to specify them. Have a look at the screenshot examples above. Are you going to use drop downs? Text boxes? Radio buttons? What makes sense for the choices you are making? Are you making consistent choices across the app? Draw some screens on paper or in a drawing tool and see what they look like.
Table Components:
As discussed in the Task Highlights, the table structures are crucial to the successful display of the data from the server. Using a sophisticated table component like ag-Grid react means that we can do a lot of things in the client application without going back to the server. Pay particular attention to the Week 6 prac which walks you through this material.
Charting:
For more sophisticated endpoints which offer a lot of data, line or bar charting or some other mechanism for showing the data will be very well received. You may use standard chart libraries to produce these, and as shown in the earlier screenshots there may well be a mix of table and chart displays.
For charting we recommend the use of chartJS (https://www.chartjs.org/), especially via the widely used React wrapper you can find here: https://www.npmjs.com/package/react-chartjs- 2. d3 (https://d3js.org/) is also a popular choice, but it is an advanced library and you shouldn’t attempt it unless you have prior experience.
Client Side Filtering:
We will in general look favourably on applications which allow the user to select or filter on the client side and have the table and the charting update in response to these changes. However, we will not look favourably on apps which load the entire collection from the server each time. You should strike a balance between client side filtering and proper use of the API endpoints. Sometimes there is just too much data on the server to grab it all at once.
The Report:
We will expect a short report and user guide, generally running to 10 pages or so, including a lot of screenshots. Mostly this is just to help us better understand your application, but this time we will also require you to assess critically the quality of your UI design, and to analyse it from the perspective of accessibility and the changes that would be needed for the application to be compliant. We will give more guidance on this in a separate report guide and template, but to make one thing clear, you can be as brutal and self-critical as you like in these sections without noticeably affecting your actual UI marks. In fact, this is very much encouraged.
The report will also help us get your thoughts on the process, the bits that worked and the bits that didn’t, and the usability and correctness of the application. The report will include:
1. Introduction – telling us what was implemented and what wasn’t, showing a few screenshots to illustrate the functionality.
2. Use of Endpoints. How you used the API endpoints and their relationship to the functionality described.
3. A List of any external components used, such as ag-grid react.
4. Application Design and Usability. This section is a discussion of the choices you made in designing the app, and some frank assessments of its usability and the changes that would be needed to comply with accessibility requirements. This section attracts a lot of the marks allocated for the report and is noted separately in the CRA.
5. Technical Description of the Application. The architecture, test plan, results and technical limitations and compromises. We do not expect automated testing. We do expect you to verify that the application works for each of the use cases. Screen shots are your friend. This section is especially important if something doesn’t actually work.
6. References
7. Appendix: brief user guide
The marking for this assignment will be governed by the CRA rubric, and this will take account of a number of aspects of the assignment process. These will include:
The report should be saved as a PDF and submitted as report.pdf (see below).
Grading:
1. The overall level of functionality successfully implemented
2. The usability of the application
3. The robustness of the application
4. Evidence of a professional approach to design
5. Evidence of a professional approach to development and code quality
6. The quality of the professional report – including your assessment of your UI design and
analysis of changes needed for accessibility (see above).
Full details of this split will be found in the separate CRA document in the assessment section of BB. Here we are concerned only with the marks for functionality, application usability and robustness. The precise marks awarded may be reduced as a result of features which are only partially implemented or error-prone or components which are poorly chosen and so on. But as an approximate guide, these are our expectations at each grade level:
• [Grade of 4 level]: A simple React app with limited styling which uses the unauthenticated Data endpoints and presents the data cleanly using table components. Some basic navigation is required. User endpoints and the authenticated data queries may not have been implemented successfully and the client side processing in the table components is very limited. A react-strap table component or other simple alternative would suffice here.
• [Grade of 5 level]: At this level we would expect successful implementation of the user registration and login endpoints and the authenticated Data route. Table component usage and client side processing would be expected to use the standard functionality provided
by a component such as ag-Grid react, and there should not be excessive querying
of the server.
• [Grade of 6 and 7 level]: Here the expectation is that you have exceeded the grade of 5
level in that all of the basics are there and working smoothly. Navigation is handled using React Router, React forms are used for the data entry and there is evidence of close alignment between between your components and the services that they are using. We would expect some use of charting or other information graphics to show how the scores vary over time. Some client side filtering and support for partial match search is expected. So, to qualify for grade 6 or 7 level functionality marks, you need all the basics plus charting and/or infographics plus some advanced client side filtering and search. The split between the grade of 6 and grade of 7 will involve a tradeoff between the features and the quality of the execution. Please talk to your tutor about your proposed application and we will tell you whether it qualifies.
A reminder that the mark levels are based on successful implementation of the features mentioned. If they don’t work or are substandard, then of course the grade level may be reduced.
Submission:
The submission instructions for this assignment cannot be finalised at the time of release. It is our practice to assess these assignments via a face to face or virtual demo. This is our intended approach for assignment 1, but in the event of a lockdown we may change our approach to instead require a video submission. We will make a final decision on this at the beginning of Week 9.
Your submission will definitely include the following components: The Code:
The code archive should be based on the React application structure that you inherit from create- react-app or codesandbox. We will not be impressed if this has been disrupted badly or there are additional folders with a seemingly random purpose and organisation.
Above all, however, we will need you to pay close attention to your node_modules:
Node apps involve installation of packages, and this leads to the installation of node_modules, and eventually these take up rather a lot of space. Please delete them. And then look around through the directory structures again, and delete any others that you missed the first time. We don’t want to see them, we don’t want to store them, and you don’t want to wait while they upload.
And in case you missed it the first time, please delete your node_modules.
Report:
The report will be as discussed above and as specified in more detail in the report template. We will get you to submit it as a PDF called report.pdf within the submission zip. The precise details will be included in the submission guide, which we will release in Week 9.
Final Submission:
Prior to upload to Blackboard, we will require that you create a directory called assign which should include:
• The client application code directory
• The report
• Any supporting documentation needed (this is mainly for extension approvals and so
on).
You should then zip up assign and uploaded to blackboard. We will mark the last attempt received and we will ignore all the others. Full details and screenshots will be provided in the submission guide.