StatusHub

This page contains codes and samples for how we're consuming the RSS feed from servicestatus.msu.edu in various websites and applications. Please see the knowledgebase article for more information.

Samples

The below samples are pulling D2l-related information from the StatusHub RSS feeds and rendering the results in the web page.


Service Alerts

Checking for service alerts...

Scheduled Maintenance

Checking for scheduled maintenance...

The Code

HTML

The HTML code we're using can be found below. You'll need to edits the Service IDs and/or Group IDs.

<div class="service_status" data-title="Sample Service Alerts"
        data-feed="incidents"
        data-empty="There have been no recent service alerts."
        data-serviceids="7217,7224,7201,7199,7225,7198"
        data-groupids="">
    <h3 class="feed-header">Service Alerts</h3>
    Checking for service alerts...
</div>

<div class="service_status" data-title="Sample Scheduled Maintenance"
        data-feed="maintenances"
        data-empty="There has been no recent scheduled maintenance."
        data-serviceids="7217,7224,7201,7199,7225,7198"
        data-groupids="">
    <h3 class="feed-header">Scheduled Maintenance</h3>
    Checking for scheduled maintenance...
</div>

JavaScript

The JavaScript code we're using can be found here: /_js/statushub.js. You should be able to use it in your site with minimal, if any, customization.

NOTE: the code uses jQuery, so you'll need to make sure that jquery is loaded in your page before this file.

Show/Hide JavaScript Source Code

var STATUSHUB = STATUSHUB || {};

STATUSHUB.start = function() {
    STATUSHUB.make_css();
    $("div[data-feed]").each(function () {
        STATUSHUB.requestRSS($(this),
            $(this).attr("data-feed"),
            $(this).attr("data-title"),
            $(this).attr("data-empty"),
            $(this).attr("data-serviceids"),
            $(this).attr("data-groupids")
        );
    });
}
/*
    * REQUEST RSS
    * ---
    * Arguments: obj - the object where we're going to insert the information.
    *             feed = either incidents or maintenances, depending on which feed you want
    *              header - the header text that will spawn above the generated data.
    *              _empty - a string to be used if there are no results
    */
STATUSHUB.requestRSS = function (obj, feed, header, _empty, service_ids, group_ids) {
    //console.log("requestRSS");
    var $ = jQuery, dataUrl;
    if(feed == 'incidents') {
        dataUrl = "https://servicestatus.msu.edu/atom/incidents?limit=50&days_after=2&days_before=5";
    } else {
        dataUrl = "https://servicestatus.msu.edu/atom/maintenances?limit=50&days_after=30&days_before=1";
    }
    $.ajax({
        url: dataUrl,
        dataType: "xml",
        async: true,
        data: {group_ids:group_ids, service_ids:service_ids},
        cache: false,
        success: function (xml) {
            var f_date, found_one = false;
            var block = $("<div class='feed-block'><h3 class='feed-header' onclick='STATUSHUB.toggle_me(this)'>" + header + "<span class='toggler'></span></h3><div class='feed-body'></div></div>").insertAfter(obj);
            var weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
            var month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
            obj.remove();
            $(xml).find("feed entry").each(function () {
                //console.log(this);
                // This section is done differently because namespace selection with \\: doesn't work in Edge
                var c = this.childNodes, i, startdate_str = '', enddate_str = '', status = '';
                for (i = 0; i < c.length; i++) {
                        if(c[i].nodeName=="status:start-time") {
                                startdate_str = c[i].childNodes[0].nodeValue;
                        } else if(c[i].nodeName=="status:end-time") {
                                enddate_str = c[i].childNodes[0].nodeValue;
                        } else if(c[i].nodeName=="status:incident-type") {
                                status = c[i].childNodes[0].nodeValue;
                        }
                }
                var id = $(this).find("id").text(), 
                    url = $(this).find("link").attr("href"), 
                    it,
                    //startdate_str = $(this).find("status\\:start-time").text(),  // this doesn't work in Edge
                    //enddate_str = $(this).find("status\\:end-time").text(),  // this doesn't work in Edge
                    //status = $(this).find("status\\:incident-type").text(),  // this doesn't work in Edge
                    title = $(this).find('title').text(),
                    start_am_or_pm = "am", 
                    end_am_or_pm = "am",
                    startdate = new Date(startdate_str),
                    enddate = new Date(enddate_str);
                title = STATUSHUB.removeTitleFlag(title);
                id = STATUSHUB.eventid_from_urlid(id);
                it = $("<div class='item' id='item"+id+"'><div class='item-title'></div><div class='item-body'></div><div class='item-date'></div></div>");

                if($("#item"+id).size()===0) { // filters out multiple entries for single incident

                    if(status) {
                        status = "<span class='status " + status + "'>" + status + "</span> ";
                    }
                    $(".feed-body", block).append(it);
                    $(".item-title", it).html(status + title + " <span class='link'>(<a target='_blank' href='" + url + "'>Details</a>)</span>");

                    if (startdate == 'Invalid Date' || startdate == 'NaN') { // browsers don't handle date the same
                        startdate_str = STATUSHUB.format_date(startdate_str);
                        startdate = new Date(startdate_str);
                    }

                    if (enddate == 'Invalid Date' || enddate == 'NaN') { // browsers don't handle date the same
                        enddate_str = STATUSHUB.format_date(enddate_str);
                        enddate = new Date(enddate_str);
                    }

                    var start_day_of_week = weekday[startdate.getDay()];
                    var end_day_of_week = weekday[enddate.getDay()];

                    var startmonth = month[startdate.getMonth()];
                    var endmonth = month[enddate.getMonth()];

                    var start_day_of_mo = startdate.getDate();
                    var end_day_of_mo = enddate.getDate();

                    var start_hour = startdate.getHours();
                    var end_hour = enddate.getHours();

                    if (start_hour > 12) {
                        start_hour = start_hour - 12;
                        start_am_or_pm = "pm";
                    }
                    if (start_hour === 0) {
                        start_hour = 12;
                        start_am_or_pm = "am";
                    }
                    if (end_hour > 12) {
                        end_hour = end_hour - 12;
                        end_am_or_pm = "pm";
                    }
                    if (end_hour === 0) {
                        end_hour = 12;
                        end_am_or_pm = "am";
                    }

                    var start_minute = startdate.getMinutes();
                    var end_minute = enddate.getMinutes();
                    if (start_minute < 10) {
                        start_minute = "0" + start_minute;
                    }
                    if (end_minute < 10) {
                        end_minute = "0" + end_minute;
                    }

                    f_date = start_day_of_week + ", " + startmonth + " " + start_day_of_mo +
                        " " + start_hour + ":" + start_minute + start_am_or_pm;
                    if (enddate_str != '') {
                        if (startmonth === endmonth && start_day_of_mo === end_day_of_mo) {
                            // event starts and ends same day
                            if (!(start_hour === end_hour && start_minute === end_minute && start_am_or_pm === end_am_or_pm)) {
                                f_date = f_date + " - ";
                            }
                        } else {
                            f_date = f_date + " - " + end_day_of_week + ", " + endmonth + " " + end_day_of_mo + " ";
                        }

                        if (!(
                                startmonth === endmonth &&
                                start_day_of_mo === end_day_of_mo &&
                                start_hour === end_hour &&
                                start_minute === end_minute &&
                                start_am_or_pm === end_am_or_pm
                            )) {
                            f_date = f_date + end_hour + ":" + end_minute + end_am_or_pm;
                        }
                    }
                    $(".item-date", it).text(f_date);
                }

                found_one = true;
                
            });
            if (found_one === false) {
                if (_empty) {
                    $(".feed-body", block).html("<span class='no-events'>" + _empty + "</span>");
                } else {
                    $(".feed-body", block).html("<span class='no-events'>There have been no recent items.</span>");
                }
            }
        },
        error: function () {
            obj.html("<div class='error'>Error: unable to retrieve " + header + " info.</div>");
        }
    });
};

STATUSHUB.format_date = function (str) {
    str = str.replace(/\-/g, '\/').replace(/[T|Z]/g, ' ').substring(0, 19);
    return str;
};

STATUSHUB.eventid_from_urlid = function (urlid) {
    var arr = urlid.split("://");
    var no_protocol = arr[1];
    return no_protocol.split('/')[2];
}

STATUSHUB.removeTitleFlag = function(title) {
    var title_arr = title.split("] - ");
    if(title_arr.length > 1) {
        return title_arr[1];
    } else {
        return title
    }
}

STATUSHUB.make_css = function() {
    "use strict";
    var rules = ".feed-block span.status { background-color:#000; border-radius:5px; color:#fff; display:inline-block; font-size:85%; font-weight:normal; padding:0 5px; text-transform:capitalize; }\
    .feed-block span.status.resolved { background-color:#669e02; }\
    .feed-block span.status.monitoring,\
    .feed-block span.status.investigating { background-color:#e6841b; }\
    .feed-block span.identified { background-color:#ff0000; }\
    .feed-body .item-date { color:#666666; font-size:10px; font-style:italic; padding-bottom:5px; padding-top:3px; }";
    var css = document.createElement('STYLE');
    css.type = 'text/css';
    if(css.styleSheet) {
        css.styleSheet.cssText = rules;
    } else {
        css.appendChild(document.createTextNode(rules));
    }
    var target = document.getElementsByTagName("head")[0];
    if(target) {
        target.appendChild(css);
    } else {
        document.body.appendChild(css);
    }
    
}

STATUSHUB.format_date = function(str) {
    str = str.replace(/\-/g,'\/').replace(/[EDT|EST]/g,' ').substring(0, 21);
    return str;
}
$(document).ready(function() {
    STATUSHUB.start();
})