I publish our electric usage information for visualizations. I recently prepared this in accordance with a rate increase.
I wanted to display:
- A sortable table of the data.
- A simple cost over time visualization of the data.
This is comprised of a few things:
- HTML rendering of the page itself.
- Usage of Google Visualization libraries to render the table and chart.
- Simplified API endpoints to return the resource as is needed in different representations.
I wanted the data to be available even if JavaScript was disabled. You can disable JavaScript and see the data in a raw HTML table as well as links to view the data as a CSV file.
The interface is separated into different concerns:
- HTML that includes the necessary data and links
- JavaScript applied. Using Google's Visualization libraries, we can inspect the DOM and pass corresponding
Accept
headers to retrieve the data necessary asDataTable
or other needs for the sortable table and charts. The client side code does not construct any models out of data. It requests the data as necessary and passes it to thegoogle.visualization.DataTable
. The only rules declared are UI related, in terms of height, width, formats, legends, etc. - API endpoints that respond as necessary. The use cases here are very specific, but could be altered to take query string or body parameters and return different data sets. For example, the endpoints could be modified to support sorting, filtering, or grouping.
There is a loose coupling of these layers and they can easily be replaced or re-used.
The data used in this page is readily available via some endpoints.
Some things to note:
- The data set was small enough that I didn't include pagination.
- I only needed to work with a single endpoint, so I didn't embed links to support navigation.
- The data is returned and a response code of
200 Successful
. - If you try and request a representation that is not supported, you will retrieve a
406 Not Acceptable
- Each of these endpoints could easily be hidden behind HTTP
Authorization
schemes likeBasic
orBearer
token.
We have a single resource, http://utilities.theklaibers.com/historical/billing
that has 4 different representations.
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: text/csv'
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: text/csv' -H 'Accept-Encoding: gzip'
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: text/csv' -o usage.csv
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: text/csv' -H 'Accept-Encoding: gzip' -o usage.csv.gz
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json'
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json' -H 'Accept-Encoding: gzip'
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json' -o usage.json
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json' -H 'Accept-Encoding: gzip' -o usage.json.gz
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json+table'
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json+table' -H 'Accept-Encoding: gzip'
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json+table' -o usage.json
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json+table' -H 'Accept-Encoding: gzip' -o usage.json.gz
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json+chart'
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json+chart' -H 'Accept-Encoding: gzip'
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json+chart' -o usage.json
curl 'http://utilities.theklaibers.com/historical/billing' -H 'Accept: application/json+chart' -H 'Accept-Encoding: gzip' -o usage.json.gz