Creating an Economic Dashboard Using OpenShift PaaS, Node.js, and Google Charts (Part II)

Picking up where I left off in Part I, I have a JSON data service created. Now I want to create a dashboard to display that data.

Creating a Jade Template

To create the page that holds the dashboard data, I decided to try out the Jade template engine for Node.js. I really dig the slimmed down HTML syntax in Jade. All the normal HTML markup built around opening and closing HTML tags like this:

<ul>
  <li class="first">
    <a href="#">foo</a>
  </li>
  <li>
    <a href="#">bar</a>
  </li>
  <li class="last">
    <a href="#">baz</a>
  </li>
</ul>

is shortened to this:

ul
  li.first
    a(href='#') foo
  li
    a(href='#') bar
  li.last
    a(href='#') baz

A div with an id of “whatever” is to simply #whatever. Not bad. Plus it’s got all the usual template engine features like variables, conditionals, iteration, and template includes.

Here is the source code for the Jade template for my dashboard page:

html
    head
        script(src='http://documentcloud.github.com/underscore/underscore-min.js')
        script(src='https://www.google.com/jsapi')
        script(type='text/javascript')
            var blsData = !{blsData}
        script(src='js/googleCharts.js')
        link(rel='stylesheet', href='css/main.css')
	body
        title U.S. Economic Dashboard
        h1 U.S. Economic Dashboard
        #unempChart.chart
        #chart2.chart
            div.questionMark ?
        #chart3.chart
            div.questionMark ?
        #chart4.chart
            div.questionMark ?

Pretty simple. There are a few script imports at the top, including the JavaScript utility library Underscore.js and of course the Google API. The one script block for var blsData shows where I am populating a JavaScript variable with the content of an escaped Jade variable of the same name. I’ll show where this variable is passed to the template in a sec.

The page layout is basic. Four divs, three of which have question marks to represent placeholders for future content. The only div with chart content is unempChart, which will be used by the Google Charts script.

There are a couple changes that need to be made to handle the dashboard page in server.js. First, I need to set up Express to serve my static JavaScript and CSS content. This is done by adding the following two non-route URLs:

// Expose the static resources on two non-route URLs
app.use("/js", express.static(__dirname + '/js'));
app.use("/css", express.static(__dirname + '/css'));

Next I create the route to the dashboard itself, passing in the unemployment data scraped from the BLS site (as described in Part I):

// Route: GET /dashboard -> Jade template
app.get("/dashboard", function(req, res) {
    retrieveUnemployment(function(unemploymentData) {
        res.render("index.jade", {
            blsData : JSON.stringify(unemploymentData)
        });
    });
});

Google Charts

Lastly, there is the JavaScript that creates the Google Chart out of the JSON data and drops it into the div container.

google.load("visualization", "1", {
    packages : [ "corechart" ]
});
google.setOnLoadCallback(drawChart);
function drawChart() {
    var data = new google.visualization.DataTable();
    data.addColumn('date', 'Month');
    data.addColumn('number', 'Unemployment');

    // Parsed blsData
    var parsedBLSData = [];
    _.each(blsData, function(blsDataItem) {
        var parsedBLSDataItem = [
                new Date(blsDataItem.year, blsDataItem.month, 1),
                blsDataItem.rate 
        ];
        parsedBLSData.push(parsedBLSDataItem);
    }, this);

    data.addRows(parsedBLSData);

    var options = {
        title : 'U.S. Unemployment Rate',
        chartArea : {
            width : '90%',
            height : '75%'
        },
        vAxis : {
            maxValue : 11.0,
            minValue : 0.0
        },
        legend : {
            position : "none"
        }
    };

    var chart = new google.visualization.LineChart(document
            .getElementById('unempChart'));
    chart.draw(data, options);
}

I create a google.visualization.DataTable object and populate it with a two-dimensional array, converting the JSON month and year properties into JavaScript date objects as I go. Chart visualization options (of which there are many) are supplied in the options var and a LineChart object is created with the target div id. Calling chart.draw with the converted data and options object displays the chart on the screen.

Partial dashboard running on OpenShift

Next steps

Well, obviously the dashboard needs more charts. One thing it could use is a metric that better controls for the number people who have stopped looking for employment or otherwise dropped out of the labor market. Something like total nonfarm payroll. Then there are other common measures like quarterly GDP changes.

From a technical standpoint, it’s not a great idea to pull the source data with every request for the dashboard. There needs to be a caching mechanism, so the data’s pulled at a more sensible interval (no more than once a day). That might be a good excuse to explore the MongoDB cartridge.

All of the source code is up on Github. Have a look: https://github.com/trevorquinn/econstats