GitHub Issues Exporter

Provides a simple UI for accessing a given users GitHub repository and exporting issues as a spreadsheet.

by jamesdh

HTML

<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css">
<div id="wrap">
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="navbar-inner">
            <div class="container"> <a class="brand" href="#">GitHub Issue Exporter</a>

                <div id="userView"
                class="pull-right"></div>
                <!-- UserView Templates -->
                <script type="text/template" id="userlogin_template">
                    <div class="navbar-form"><input id="username" class="span2" type="text" placeholder="GitHub Username"> 
                      <input id="password" class="span2" type="password" placeholder="GitHub Password"> 
                      <button id="login" type="submit" class="btn">Go!</button>
                    </div >
                </script>
                <script type="text/template" id="loggedin_template">
                    <div>
                      <ul class="nav">
                        <li><a target="_blank" href="<%= html_url %>"><%= name %></a></li>
                        <li><a id="rate" target="_blank" href="http://developer.github.com/v3/#rate-limiting"></a></li>
                      </ul>
                      <button id="logout" type="submit" class="btn">Logout</button>
                    </div>
                </script>
            </div>
        </div>
    </div>
    <div class="container">
        <div id="errorView"></div>
        <!-- ALERT MESSAGE TEMPLATES -->
        <script type="text/template" id="error_template">
            <div class="alert alert-error">
              <button id="alert-close" type="button" class="close" data-dismiss="alert">&times;</button>
            <strong>Error:...

CSS

/* Sticky footer styles
-------------------------------------------------- */
 html, body {
    height: 100%;
    /* The html and body elements cannot have any padding or margin. */
}
/* Wrapper for page content to push down footer */
 #wrap {
    min-height: 100%;
    height: auto !important;
    height: 100%;
    /* Negative indent footer by it's height */
    margin: 0 auto -30px;
}
/* Set the fixed height of the footer here */
 #push, #footer {
    height: 50px;
}
#footer {
    background-color: #eee/*#f5f5f5;*/
}
/* Lastly, apply responsive CSS fixes as necessary */
 @media (max-width: 767px) {
    #footer {
        margin-left: -20px;
        margin-right: -20px;
        padding-left: 20px;
        padding-right: 20px;
    }
}
.container .credit {
    margin: 15px 0;
    text-align: center;
}

JavaScript

var apiRoot = "https://api.github.com"

// ############## MODELS ##############
var User = Backbone.Model.extend({
    url: apiRoot + "/user", 
    initialize: function () {
	  this.on("change:username change:password", this.authEncode);
      this.on("sync", this.extractRateLimit);
    },
    authEncode: function () {
        var that = this;
        $.ajaxSetup({
            dataType: "jsonp",
            beforeSend: function (xhr) {
              	var b64auth = window.btoa(that.get("username") + ":" + that.get("password"));
                xhr.setRequestHeader('Authorization', "Basic " + b64auth);
            }
        });
    },
    extractRateLimit: function (model, resp, options) {
      var rateLimit = options.xhr.getResponseHeader("X-RateLimit-Remaining");
      this.set({rate_limit: rateLimit});
    }
});

var Org = Backbone.Model.extend({
   	 
});

var Milestone = Backbone.Model.extend({
    title: null,
    number: null
});

var Repo = Backbone.Model.extend({
    name: null
});

var Collaborator = Backbone.Model.extend({
    login: null
});

var Label = Backbone.Model.extend({
    name: null,
    color: null
});

var Issue = Backbone.Model.extend({
    html_url: null,
    number: null,
    title: null,
    assignee: null, // User
    labels: [], // Labels
    milestone: null, // Milestone
    createdAt: null, // "2011-04-22T13:33:48Z"
    closedAt: null
});

// ############## COLLECTIONS ##############
var Orgs = Backbone.Collection.extend({
    model: Org,
    url: "/user/orgs"    
});

var Milestones = Backbone.Collection.extend({
    model: Milestone,
    url: "/repos/:owner/:repo/milestones"
});

var Repos = Backbone.Collection.extend({
    model: Repo,
    url: "/user/repos"
});

var Collaborators = Backbone.Collection.extend({
    model: Collaborator,
    url: "/repos/:owner/:repo/collaborators"
});

var Labels = Backbone.Collection.extend({
    model: Label,
    url: "/repos/:owner/:repo/labels" // OR...