diff --git a/Gruntfile.coffee b/Gruntfile.coffee index c45cd0f..ca1abd3 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -34,6 +34,8 @@ module.exports = (grunt) -> 'vendor/firebase/firebase.js' 'vendor/firebase-simple-login/firebase-simple-login.js' 'vendor/grapnel/src/grapnel.js' + 'vendor/github/lib/base64.js' + 'vendor/github/github.js' # Our app. 'public/js/app.js' ] diff --git a/README.md b/README.md index 1d454e1..10339b0 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,20 @@ charcoal, charriot [ ] rotate between percentage progress and points left [ ] Send notifications to people like Codeship or have our own delivery system perhaps like Github or just show a notification icon and onclick ask people to upgrade +### The 20% + +[ ] Do not show login/logged-in state when we are still fetching that information from Firebase +[ ] Handle 404 on routes; from catch all check if '/' or go 404 controller +[ ] Variable document.title on different pages +[ ] In add a project form autocomplete on my username, orgs I am member of and repos I have access to +[ ] Someone might create a public repo, add it to the system and switch it to private; need to check repo priviledges at runtime; or when asking for auth, one would choose either public OR public/private, but this could get confusign. +[ ] Make sure the padding fits throughout the interface; we have user-select on elements. +[ ] Validate repo input and show a loading sign of sorts +[ ] When fetching repo say if no perms to access or does not exist +[ ] Check location.hash is supported +[ ] Have an app wide of triggering a URL and have named routes too +[ ] Check that we have not run out of requests to make + ### Extras [ ] choose your own strategy for naming issues, e.g. all issues are one size @@ -44,11 +58,6 @@ charcoal, charriot [ ] show velocity number for each member of the team in the corner of the layout [ ] show velocity for all team members and how it progresses through time [ ] points collector - give medals for 1st 3 spots in terms of velocity -[ ] Do not show login/logged-in state when we are still fetching that information from Firebase -[ ] Handle 404 on routes; from catch all check if '/' or go 404 controller -[ ] Variable document.title on different pages -[ ] In add a project form autocomplete on my username, orgs I am member of and repos I have access to -[ ] Someone might create a public repo, add it to the system and switch it to private; need to check repo priviledges at runtime; or when asking for auth, one would choose either public OR public/private, but this could get confusign. ## Notes diff --git a/bower.json b/bower.json index 623ba7c..d77c19b 100644 --- a/bower.json +++ b/bower.json @@ -8,6 +8,7 @@ "ractive-adaptor": "radekstepan/ractive-adaptor-ractive", "firebase": "~1.0.21", "firebase-simple-login": "~1.6.3", - "grapnel": "~0.4.2" + "grapnel": "~0.4.2", + "github": "~0.9.0" } } diff --git a/public/js/app.bundle.js b/public/js/app.bundle.js index 945b9a1..d61d3e7 100644 --- a/public/js/app.bundle.js +++ b/public/js/app.bundle.js @@ -21477,6 +21477,848 @@ goog.exportProperty(FirebaseSimpleLogin,"onOpen",FirebaseSimpleLogin.onOpen);Fir } }).call({}, window); +;// This code was written by Tyler Akins and has been placed in the +// public domain. It would be nice if you left this header intact. +// Base64 code from Tyler Akins -- http://rumkin.com + +var Base64 = (function () { + var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + + var obj = { + /** + * Encodes a string in base64 + * @param {String} input The string to encode in base64. + */ + encode: function (input) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + do { + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + + keyStr.charAt(enc3) + keyStr.charAt(enc4); + } while (i < input.length); + + return output; + }, + + /** + * Decodes a base64 string. + * @param {String} input The string to decode. + */ + decode: function (input) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + // remove all characters that are not A-Z, a-z, 0-9, +, /, or = + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + do { + enc1 = keyStr.indexOf(input.charAt(i++)); + enc2 = keyStr.indexOf(input.charAt(i++)); + enc3 = keyStr.indexOf(input.charAt(i++)); + enc4 = keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) { + output = output + String.fromCharCode(chr3); + } + } while (i < input.length); + + return output; + } + }; + + return obj; +})(); +if (typeof exports !== 'undefined') { + // Github = exports; + module.exports = Base64; +} else { + window.Base64 = Base64; +} + +;// Github.js 0.9.0 +// (c) 2013 Michael Aufreiter, Development Seed +// Github.js is freely distributable under the MIT license. +// For all details and documentation: +// http://substance.io/michael/github + +(function() { + + // Initial Setup + // ------------- + + var XMLHttpRequest, Base64, _; + if (typeof exports !== 'undefined') { + XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; + _ = require('underscore'); + Base64 = require('./lib/base64.js'); + }else{ + _ = window._; + Base64 = window.Base64; + } + //prefer native XMLHttpRequest always + if (typeof window !== 'undefined' && typeof window.XMLHttpRequest !== 'undefined'){ + XMLHttpRequest = window.XMLHttpRequest; + } + + + var API_URL = 'https://api.github.com'; + + var Github = function(options) { + + // HTTP Request Abstraction + // ======= + // + // I'm not proud of this and neither should you be if you were responsible for the XMLHttpRequest spec. + + function _request(method, path, data, cb, raw, sync) { + function getURL() { + var url = path.indexOf('//') >= 0 ? path : API_URL + path; + return url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime(); + } + + var xhr = new XMLHttpRequest(); + if (!raw) {xhr.dataType = "json";} + + xhr.open(method, getURL(), !sync); + if (!sync) { + xhr.onreadystatechange = function () { + if (this.readyState == 4) { + if (this.status >= 200 && this.status < 300 || this.status === 304) { + cb(null, raw ? this.responseText : this.responseText ? JSON.parse(this.responseText) : true, this); + } else { + cb({path: path, request: this, error: this.status}); + } + } + } + }; + xhr.setRequestHeader('Accept','application/vnd.github.raw+json'); + xhr.setRequestHeader('Content-Type','application/json;charset=UTF-8'); + if ((options.token) || (options.username && options.password)) { + xhr.setRequestHeader('Authorization', options.token + ? 'token '+ options.token + : 'Basic ' + Base64.encode(options.username + ':' + options.password) + ); + } + data ? xhr.send(JSON.stringify(data)) : xhr.send(); + if (sync) return xhr.response; + } + + function _requestAllPages(path, cb) { + var results = []; + (function iterate() { + _request("GET", path, null, function(err, res, xhr) { + if (err) { + return cb(err); + } + + results.push.apply(results, res); + + var links = (xhr.getResponseHeader('link') || '').split(/\s*,\s*/g), + next = _.find(links, function(link) { return /rel="next"/.test(link); }); + + if (next) { + next = (/<(.*)>/.exec(next) || [])[1]; + } + + if (!next) { + cb(err, results); + } else { + path = next; + iterate(); + } + }); + })(); + } + + + + // User API + // ======= + + Github.User = function() { + this.repos = function(cb) { + // Github does not always honor the 1000 limit so we want to iterate over the data set. + _requestAllPages("/user/repos?type=all&per_page=1000&sort=updated", function(err, res) { + cb(err, res); + }); + }; + + // List user organizations + // ------- + + this.orgs = function(cb) { + _request("GET", "/user/orgs", null, function(err, res) { + cb(err, res); + }); + }; + + // List authenticated user's gists + // ------- + + this.gists = function(cb) { + _request("GET", "/gists", null, function(err, res) { + cb(err,res); + }); + }; + + // List authenticated user's unread notifications + // ------- + + this.notifications = function(cb) { + _request("GET", "/notifications", null, function(err, res) { + cb(err,res); + }); + }; + + // Show user information + // ------- + + this.show = function(username, cb) { + var command = username ? "/users/"+username : "/user"; + + _request("GET", command, null, function(err, res) { + cb(err, res); + }); + }; + + // List user repositories + // ------- + + this.userRepos = function(username, cb) { + // Github does not always honor the 1000 limit so we want to iterate over the data set. + _requestAllPages("/users/"+username+"/repos?type=all&per_page=1000&sort=updated", function(err, res) { + cb(err, res); + }); + }; + + // List a user's gists + // ------- + + this.userGists = function(username, cb) { + _request("GET", "/users/"+username+"/gists", null, function(err, res) { + cb(err,res); + }); + }; + + // List organization repositories + // ------- + + this.orgRepos = function(orgname, cb) { + // Github does not always honor the 1000 limit so we want to iterate over the data set. + _requestAllPages("/orgs/"+orgname+"/repos?type=all&&page_num=1000&sort=updated&direction=desc", function(err, res) { + cb(err, res); + }); + }; + + // Follow user + // ------- + + this.follow = function(username, cb) { + _request("PUT", "/user/following/"+username, null, function(err, res) { + cb(err, res); + }); + }; + + // Unfollow user + // ------- + + this.unfollow = function(username, cb) { + _request("DELETE", "/user/following/"+username, null, function(err, res) { + cb(err, res); + }); + }; + }; + + + // Repository API + // ======= + + Github.Repository = function(options) { + var repo = options.name; + var user = options.user; + + var that = this; + var repoPath = "/repos/" + user + "/" + repo; + + var currentTree = { + "branch": null, + "sha": null + }; + + // Uses the cache if branch has not been changed + // ------- + + function updateTree(branch, cb) { + if (branch === currentTree.branch && currentTree.sha) return cb(null, currentTree.sha); + that.getRef("heads/"+branch, function(err, sha) { + currentTree.branch = branch; + currentTree.sha = sha; + cb(err, sha); + }); + } + + // Get a particular reference + // ------- + + this.getRef = function(ref, cb) { + _request("GET", repoPath + "/git/refs/" + ref, null, function(err, res) { + if (err) return cb(err); + cb(null, res.object.sha); + }); + }; + + // Create a new reference + // -------- + // + // { + // "ref": "refs/heads/my-new-branch-name", + // "sha": "827efc6d56897b048c772eb4087f854f46256132" + // } + + this.createRef = function(options, cb) { + _request("POST", repoPath + "/git/refs", options, cb); + }; + + // Delete a reference + // -------- + // + // repo.deleteRef('heads/gh-pages') + // repo.deleteRef('tags/v1.0') + + this.deleteRef = function(ref, cb) { + _request("DELETE", repoPath + "/git/refs/"+ref, options, cb); + }; + + // Create a repo + // ------- + + this.createRepo = function(options, cb) { + _request("POST", "/user/repos", options, cb); + }; + + // Delete a repo + // -------- + + this.deleteRepo = function(cb) { + _request("DELETE", repoPath, options, cb); + }; + + // List all tags of a repository + // ------- + + this.listTags = function(cb) { + _request("GET", repoPath + "/tags", null, function(err, tags) { + if (err) return cb(err); + cb(null, tags); + }); + }; + + // List all pull requests of a respository + // ------- + + this.listPulls = function(state, cb) { + _request("GET", repoPath + "/pulls" + (state ? '?state=' + state : ''), null, function(err, pulls) { + if (err) return cb(err); + cb(null, pulls); + }); + }; + + // Gets details for a specific pull request + // ------- + + this.getPull = function(number, cb) { + _request("GET", repoPath + "/pulls/" + number, null, function(err, pull) { + if (err) return cb(err); + cb(null, pull); + }); + }; + + // Retrieve the changes made between base and head + // ------- + + this.compare = function(base, head, cb) { + _request("GET", repoPath + "/compare/" + base + "..." + head, null, function(err, diff) { + if (err) return cb(err); + cb(null, diff); + }); + }; + + // List all branches of a repository + // ------- + + this.listBranches = function(cb) { + _request("GET", repoPath + "/git/refs/heads", null, function(err, heads) { + if (err) return cb(err); + cb(null, _.map(heads, function(head) { return _.last(head.ref.split('/')); })); + }); + }; + + // Retrieve the contents of a blob + // ------- + + this.getBlob = function(sha, cb) { + _request("GET", repoPath + "/git/blobs/" + sha, null, cb, 'raw'); + }; + + // For a given file path, get the corresponding sha (blob for files, tree for dirs) + // ------- + + this.getSha = function(branch, path, cb) { + // Just use head if path is empty + if (path === "") return that.getRef("heads/"+branch, cb); + that.getTree(branch+"?recursive=true", function(err, tree) { + if (err) return cb(err); + var file = _.select(tree, function(file) { + return file.path === path; + })[0]; + cb(null, file ? file.sha : null); + }); + }; + + // Retrieve the tree a commit points to + // ------- + + this.getTree = function(tree, cb) { + _request("GET", repoPath + "/git/trees/"+tree, null, function(err, res) { + if (err) return cb(err); + cb(null, res.tree); + }); + }; + + // Post a new blob object, getting a blob SHA back + // ------- + + this.postBlob = function(content, cb) { + if (typeof(content) === "string") { + content = { + "content": content, + "encoding": "utf-8" + }; + } + + _request("POST", repoPath + "/git/blobs", content, function(err, res) { + if (err) return cb(err); + cb(null, res.sha); + }); + }; + + // Update an existing tree adding a new blob object getting a tree SHA back + // ------- + + this.updateTree = function(baseTree, path, blob, cb) { + var data = { + "base_tree": baseTree, + "tree": [ + { + "path": path, + "mode": "100644", + "type": "blob", + "sha": blob + } + ] + }; + _request("POST", repoPath + "/git/trees", data, function(err, res) { + if (err) return cb(err); + cb(null, res.sha); + }); + }; + + // Post a new tree object having a file path pointer replaced + // with a new blob SHA getting a tree SHA back + // ------- + + this.postTree = function(tree, cb) { + _request("POST", repoPath + "/git/trees", { "tree": tree }, function(err, res) { + if (err) return cb(err); + cb(null, res.sha); + }); + }; + + // Create a new commit object with the current commit SHA as the parent + // and the new tree SHA, getting a commit SHA back + // ------- + + this.commit = function(parent, tree, message, cb) { + var data = { + "message": message, + "author": { + "name": options.username + }, + "parents": [ + parent + ], + "tree": tree + }; + + _request("POST", repoPath + "/git/commits", data, function(err, res) { + currentTree.sha = res.sha; // update latest commit + if (err) return cb(err); + cb(null, res.sha); + }); + }; + + // Update the reference of your head to point to the new commit SHA + // ------- + + this.updateHead = function(head, commit, cb) { + _request("PATCH", repoPath + "/git/refs/heads/" + head, { "sha": commit }, function(err, res) { + cb(err); + }); + }; + + // Show repository information + // ------- + + this.show = function(cb) { + _request("GET", repoPath, null, cb); + }; + + // Get contents + // -------- + + this.contents = function(branch, path, cb, sync) { + return _request("GET", repoPath + "/contents?ref=" + branch + (path ? "&path=" + path : ""), null, cb, 'raw', sync); + }; + + // Fork repository + // ------- + + this.fork = function(cb) { + _request("POST", repoPath + "/forks", null, cb); + }; + + // Branch repository + // -------- + + this.branch = function(oldBranch,newBranch,cb) { + if(arguments.length === 2 && typeof arguments[1] === "function") { + cb = newBranch; + newBranch = oldBranch; + oldBranch = "master"; + } + this.getRef("heads/" + oldBranch, function(err,ref) { + if(err && cb) return cb(err); + that.createRef({ + ref: "refs/heads/" + newBranch, + sha: ref + },cb); + }); + } + + // Create pull request + // -------- + + this.createPullRequest = function(options, cb) { + _request("POST", repoPath + "/pulls", options, cb); + }; + + // List hooks + // -------- + + this.listHooks = function(cb) { + _request("GET", repoPath + "/hooks", null, cb); + }; + + // Get a hook + // -------- + + this.getHook = function(id, cb) { + _request("GET", repoPath + "/hooks/" + id, null, cb); + }; + + // Create a hook + // -------- + + this.createHook = function(options, cb) { + _request("POST", repoPath + "/hooks", options, cb); + }; + + // Edit a hook + // -------- + + this.editHook = function(id, options, cb) { + _request("PATCH", repoPath + "/hooks/" + id, options, cb); + }; + + // Delete a hook + // -------- + + this.deleteHook = function(id, cb) { + _request("DELETE", repoPath + "/hooks/" + id, null, cb); + }; + + // Read file at given path + // ------- + + this.read = function(branch, path, cb) { + that.getSha(branch, path, function(err, sha) { + if (!sha) return cb("not found", null); + that.getBlob(sha, function(err, content) { + cb(err, content, sha); + }); + }); + }; + + // Remove a file from the tree + // ------- + + this.remove = function(branch, path, cb) { + updateTree(branch, function(err, latestCommit) { + that.getTree(latestCommit+"?recursive=true", function(err, tree) { + // Update Tree + var newTree = _.reject(tree, function(ref) { return ref.path === path; }); + _.each(newTree, function(ref) { + if (ref.type === "tree") delete ref.sha; + }); + + that.postTree(newTree, function(err, rootTree) { + that.commit(latestCommit, rootTree, 'Deleted '+path , function(err, commit) { + that.updateHead(branch, commit, function(err) { + cb(err); + }); + }); + }); + }); + }); + }; + + // Move a file to a new location + // ------- + + this.move = function(branch, path, newPath, cb) { + updateTree(branch, function(err, latestCommit) { + that.getTree(latestCommit+"?recursive=true", function(err, tree) { + // Update Tree + _.each(tree, function(ref) { + if (ref.path === path) ref.path = newPath; + if (ref.type === "tree") delete ref.sha; + }); + + that.postTree(tree, function(err, rootTree) { + that.commit(latestCommit, rootTree, 'Deleted '+path , function(err, commit) { + that.updateHead(branch, commit, function(err) { + cb(err); + }); + }); + }); + }); + }); + }; + + // Write file contents to a given branch and path + // ------- + + this.write = function(branch, path, content, message, cb) { + updateTree(branch, function(err, latestCommit) { + if (err) return cb(err); + that.postBlob(content, function(err, blob) { + if (err) return cb(err); + that.updateTree(latestCommit, path, blob, function(err, tree) { + if (err) return cb(err); + that.commit(latestCommit, tree, message, function(err, commit) { + if (err) return cb(err); + that.updateHead(branch, commit, cb); + }); + }); + }); + }); + }; + + // List commits on a repository. Takes an object of optional paramaters: + // sha: SHA or branch to start listing commits from + // path: Only commits containing this file path will be returned + // since: ISO 8601 date - only commits after this date will be returned + // until: ISO 8601 date - only commits before this date will be returned + // ------- + + this.getCommits = function(options, cb) { + options = options || {}; + var url = repoPath + "/commits"; + var params = []; + if (options.sha) { + params.push("sha=" + encodeURIComponent(options.sha)); + } + if (options.path) { + params.push("path=" + encodeURIComponent(options.path)); + } + if (options.since) { + var since = options.since; + if (since.constructor === Date) { + since = since.toISOString(); + } + params.push("since=" + encodeURIComponent(since)); + } + if (options.until) { + var until = options.until; + if (until.constructor === Date) { + until = until.toISOString(); + } + params.push("until=" + encodeURIComponent(until)); + } + if (params.length > 0) { + url += "?" + params.join("&"); + } + _request("GET", url, null, cb); + }; + }; + + // Gists API + // ======= + + Github.Gist = function(options) { + var id = options.id; + var gistPath = "/gists/"+id; + + // Read the gist + // -------- + + this.read = function(cb) { + _request("GET", gistPath, null, function(err, gist) { + cb(err, gist); + }); + }; + + // Create the gist + // -------- + // { + // "description": "the description for this gist", + // "public": true, + // "files": { + // "file1.txt": { + // "content": "String file contents" + // } + // } + // } + + this.create = function(options, cb){ + _request("POST","/gists", options, cb); + }; + + // Delete the gist + // -------- + + this.delete = function(cb) { + _request("DELETE", gistPath, null, function(err,res) { + cb(err,res); + }); + }; + + // Fork a gist + // -------- + + this.fork = function(cb) { + _request("POST", gistPath+"/fork", null, function(err,res) { + cb(err,res); + }); + }; + + // Update a gist with the new stuff + // -------- + + this.update = function(options, cb) { + _request("PATCH", gistPath, options, function(err,res) { + cb(err,res); + }); + }; + + // Star a gist + // -------- + + this.star = function(cb) { + _request("PUT", gistPath+"/star", null, function(err,res) { + cb(err,res); + }); + }; + + // Untar a gist + // -------- + + this.unstar = function(cb) { + _request("DELETE", gistPath+"/star", null, function(err,res) { + cb(err,res); + }); + }; + + // Check if a gist is starred + // -------- + + this.isStarred = function(cb) { + _request("GET", gistPath+"/star", null, function(err,res) { + cb(err,res); + }); + }; + }; + + // Issues API + // ========== + + Github.Issue = function(options) { + var path = "/repos/" + options.user + "/" + options.repo + "/issues"; + + this.list = function(options, cb) { + _request("GET", path, options, function(err, res) { + cb(err,res) + }); + }; + }; + + // Top Level API + // ------- + + this.getIssues = function(user, repo) { + return new Github.Issue({user: user, repo: repo}); + }; + + this.getRepo = function(user, repo) { + return new Github.Repository({user: user, name: repo}); + }; + + this.getUser = function() { + return new Github.User(); + }; + + this.getGist = function(id) { + return new Github.Gist({id: id}); + }; + }; + + + if (typeof exports !== 'undefined') { + // Github = exports; + module.exports = Github; + } else { + window.Github = Github; + } +}).call(this); ;// Concat modules and export them as an app. (function(root) { @@ -21525,7 +22367,7 @@ goog.exportProperty(FirebaseSimpleLogin,"onOpen",FirebaseSimpleLogin.onOpen);Fir // addProjectForm.coffee root.require.register('burnchart/src/components/addProjectForm.js', function(exports, require, module) { - var firebase, mediator, user; + var firebase, github, mediator, user; firebase = require('../modules/firebase'); @@ -21533,6 +22375,8 @@ goog.exportProperty(FirebaseSimpleLogin,"onOpen",FirebaseSimpleLogin.onOpen);Fir mediator = require('../modules/mediator'); + github = require('../modules/github'); + module.exports = Ractive.extend({ 'template': require('../templates/addProjectForm'), 'data': { @@ -21549,7 +22393,15 @@ goog.exportProperty(FirebaseSimpleLogin,"onOpen",FirebaseSimpleLogin.onOpen);Fir 'init': false }); return this.on('submit', function() { - return console.log('Submit the form with', this.get('value')); + var repo, reponame, username, _ref; + _ref = this.get('value').split('/'), username = _ref[0], reponame = _ref[1]; + repo = github.getRepo(username, reponame); + return repo.show(function(err, repo, xhr) { + if (err) { + throw err; + } + return window.location.hash = '#'; + }); }); } }); @@ -21644,6 +22496,30 @@ goog.exportProperty(FirebaseSimpleLogin,"onOpen",FirebaseSimpleLogin.onOpen);Fir }); + // github.coffee + root.require.register('burnchart/src/modules/github.js', function(exports, require, module) { + + var auth, github, setToken, user; + + user = require('./user'); + + auth = 'oauth'; + + github = null; + + (setToken = function(token) { + return github = new Github({ + token: token, + auth: auth + }); + })(null); + + user.observe('accessToken', setToken); + + module.exports = github; + + }); + // mediator.coffee root.require.register('burnchart/src/modules/mediator.js', function(exports, require, module) { diff --git a/public/js/app.js b/public/js/app.js index 0850b90..c39bd05 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -46,7 +46,7 @@ // addProjectForm.coffee root.require.register('burnchart/src/components/addProjectForm.js', function(exports, require, module) { - var firebase, mediator, user; + var firebase, github, mediator, user; firebase = require('../modules/firebase'); @@ -54,6 +54,8 @@ mediator = require('../modules/mediator'); + github = require('../modules/github'); + module.exports = Ractive.extend({ 'template': require('../templates/addProjectForm'), 'data': { @@ -70,7 +72,15 @@ 'init': false }); return this.on('submit', function() { - return console.log('Submit the form with', this.get('value')); + var repo, reponame, username, _ref; + _ref = this.get('value').split('/'), username = _ref[0], reponame = _ref[1]; + repo = github.getRepo(username, reponame); + return repo.show(function(err, repo, xhr) { + if (err) { + throw err; + } + return window.location.hash = '#'; + }); }); } }); @@ -165,6 +175,30 @@ }); + // github.coffee + root.require.register('burnchart/src/modules/github.js', function(exports, require, module) { + + var auth, github, setToken, user; + + user = require('./user'); + + auth = 'oauth'; + + github = null; + + (setToken = function(token) { + return github = new Github({ + token: token, + auth: auth + }); + })(null); + + user.observe('accessToken', setToken); + + module.exports = github; + + }); + // mediator.coffee root.require.register('burnchart/src/modules/mediator.js', function(exports, require, module) { diff --git a/src/components/addProjectForm.coffee b/src/components/addProjectForm.coffee index 8f7fa36..15d85ef 100644 --- a/src/components/addProjectForm.coffee +++ b/src/components/addProjectForm.coffee @@ -1,6 +1,7 @@ firebase = require '../modules/firebase' user = require '../modules/user' mediator = require '../modules/mediator' +github = require '../modules/github' module.exports = Ractive.extend @@ -19,4 +20,11 @@ module.exports = Ractive.extend @observe 'value', _.debounce(autocomplete, 200), { 'init': no } @on 'submit', -> - console.log 'Submit the form with', @get('value') \ No newline at end of file + [ username, reponame ] = @get('value').split('/') + repo = github.getRepo username, reponame + repo.show (err, repo, xhr) -> + throw err if err + # TODO: save repo to us & Firebase. + # Redirect to the dashboard. + # TODO: trigger a named route + window.location.hash = '#' \ No newline at end of file diff --git a/src/modules/github.coffee b/src/modules/github.coffee new file mode 100644 index 0000000..f6bc424 --- /dev/null +++ b/src/modules/github.coffee @@ -0,0 +1,13 @@ +user = require './user' + +auth = 'oauth' + +github = null + +do setToken = (token=null) -> + github = new Github { token, auth } + +# Set token when we have one (otherwise init to null). +user.observe 'accessToken', setToken + +module.exports = github \ No newline at end of file