Skip to content

Instantly share code, notes, and snippets.

@ericf
Created December 9, 2011 05:00
Show Gist options
  • Select an option

  • Save ericf/1450249 to your computer and use it in GitHub Desktop.

Select an option

Save ericf/1450249 to your computer and use it in GitHub Desktop.
YUI().use('app', 'handlebars', 'jsonp', function (Y) {
var GithubSync,
Contributor, ContributorList, Repo, RepoList, User,
ContributorListView, RepoView, RepoListView, UserView,
HomePageView, UserPageView, RepoPageView,
ContributorsApp;
// -- GithubSync ---------------------------------------------------------------
GithubSync = function () {};
GithubSync.API_ORIGIN = 'https://api.github.com';
GithubSync.prototype = {
githubURL: '/',
buildURL: function () {
return this.githubURL;
},
sync: function (action, options, callback) {
Y.Lang.isFunction(callback) || (callback = function () {});
if (action !== 'read') {
return callback('Read-only');
}
var url = this.buildURL() + '?per_page=100&callback={callback}';
Y.jsonp(GithubSync.API_ORIGIN + url, function (res) {
var meta = res.meta,
data = res.data;
if (meta.status >= 200 && meta.status < 300) {
callback(null, res);
} else {
callback(data.message, res);
}
});
},
parse: function (res) {
return res.data;
}
};
// -- User ---------------------------------------------------------------------
User = Y.Base.create('user', Y.Model, [GithubSync], {
idAttribute: 'login',
githubURL : '/users/{id}',
buildURL: function () {
return Y.Lang.sub(this.githubURL, {
id: this.getAsURL('id')
});
}
}, {
ATTRS: {
login : {value: null},
name : {value: null},
html_url : {value: null},
avatar_url : {value: null},
public_repos : {value: 0},
followers : {value: 0}
}
});
// -- Repo ---------------------------------------------------------------------
Repo = Y.Base.create('repo', Y.Model, [], {
idAttribute: 'name'
}, {
ATTRS: {
name : {value: null},
html_url : {value: null},
description: {value: null},
watchers : {value: 0},
forks : {value: 0},
language : {value: null},
owner : {value: null}
}
});
// -- RepoList -----------------------------------------------------------------
RepoList = Y.Base.create('repoList', Y.ModelList, [GithubSync], {
model : Repo,
githubURL: '/users/{user}/repos',
buildURL: function () {
return Y.Lang.sub(this.githubURL, {
user: this.get('user').getAsURL('id')
});
},
comparator: function (repo) {
return -repo.get('watchers');
}
}, {
ATTRS: {
user: {value: null}
}
});
// -- Contributor --------------------------------------------------------------
Contributor = Y.Base.create('contributor', User, [], {}, {
ATTRS: {
contributions: {value: 0}
}
});
// -- ContributorList ----------------------------------------------------------
ContributorList = Y.Base.create('contributorList', Y.ModelList, [GithubSync], {
model : Contributor,
githubURL: '/repos/{user}/{repo}/contributors',
buildURL: function () {
var repo = this.get('repo');
return Y.Lang.sub(this.githubURL, {
user: repo.getAsURL('owner.login'),
repo: repo.getAsURL('name')
});
},
comparator: function (contributor) {
return -contributor.get('contributions');
}
}, {
ATTRS: {
repo: {value: null}
}
});
// -- HomePageView -------------------------------------------------------------
HomePageView = Y.Base.create('homePageView', Y.View, [], {
template: Y.Handlebars.compile(Y.one('#t-home').getContent()),
events: {
'button': {
click: 'changeUser'
},
'input': {
keypress: 'enter'
}
},
initializer: function () {
this.publish('changeUser', {preventable: false});
},
render: function () {
var content = this.template(this.get('model').getAttrs(['login']));
this.get('container').setContent(content);
return this;
},
changeUser: function () {
var user = this.get('container').one('input').get('value');
if (user) {
this.fire('changeUser', {user: user});
}
},
enter: function (e) {
// Check for 'enter' keypress.
if (e.keyCode === 13) {
this.changeUser();
}
}
});
// -- UserView -----------------------------------------------------------------
UserView = Y.Base.create('userView', Y.View, [], {
template: Y.Handlebars.compile(Y.one('#t-user').getContent()),
render: function () {
var user = this.get('model'),
content;
content = this.template(user.getAttrs(['login', 'name', 'avatar_url']));
this.get('container').setContent(content);
return this;
}
});
// -- RepoList View ------------------------------------------------------------
RepoListView = Y.Base.create('repoListView', Y.View, [], {
template : Y.Handlebars.compile(Y.one('#t-repo-list').getContent()),
urlTemplate: '#/github/{user}/{repo}/',
render: function () {
var urlTemplate = this.urlTemplate,
content, reposData;
reposData = this.get('modelList').map(function (repo) {
var data = repo.getAttrs(['name', 'description', 'language', 'watchers', 'forks']);
data.url = Y.Lang.sub(urlTemplate, {
user: repo.getAsURL('owner.login'),
repo: repo.getAsURL('name')
});
return data;
});
content = this.template({repos: reposData});
this.get('container').setContent(content);
return this;
}
});
// -- UserPageView -------------------------------------------------------------
UserPageView = Y.Base.create('userPageView', Y.View, [], {
initializer: function () {
this.userView = new UserView({model: this.get('model')});
this.repoListView = new RepoListView({modelList: this.get('modelList')});
},
render: function () {
var content = Y.one(Y.config.doc.createDocumentFragment());
content.append(this.userView.render().get('container'));
content.append(this.repoListView.render().get('container'));
this.get('container').setContent(content);
return this;
}
});
// -- RepoView -----------------------------------------------------------------
RepoView = Y.Base.create('repoView', Y.View, [], {
template : Y.Handlebars.compile(Y.one('#t-repo').getContent()),
urlTemplate: '#/github/{user}/',
render: function () {
var repo = this.get('model'),
content;
content = this.template({
login : repo.get('owner.login'),
avatar_url: repo.get('owner.avatar_url'),
user_url : Y.Lang.sub(this.urlTemplate, {user: repo.getAsURL('owner.login')}),
name : repo.get('name')
});
this.get('container').setContent(content);
return this;
}
});
// -- ContributorListView ------------------------------------------------------
ContributorListView = Y.Base.create('contributorListView', Y.View, [], {
template : Y.Handlebars.compile(Y.one('#t-contributor-list').getContent()),
urlTemplate: '#/github/{user}/',
render: function () {
var urlTemplate = this.urlTemplate,
content, contributorsData;
contributorsData = this.get('modelList').map(function (contributor) {
var data = contributor.getAttrs(['login', 'avatar_url']);
data.url = Y.Lang.sub(urlTemplate, {
user: contributor.getAsURL('login')
});
return data;
});
content = this.template({contributors: contributorsData});
this.get('container').setContent(content);
return this;
}
});
// -- RepoPageView -------------------------------------------------------------
RepoPageView = Y.Base.create('repoPageView', Y.View, [], {
initializer: function () {
this.repoView = new RepoView({model: this.get('model')});
this.contributorListView = new ContributorListView({modelList: this.get('modelList')});
},
render: function () {
var content = Y.one(Y.config.doc.createDocumentFragment());
content.append(this.repoView.render().get('container'));
content.append(this.contributorListView.render().get('container'));
this.get('container').setContent(content);
return this;
}
});
// -- ContributorsApp ----------------------------------------------------------
ContributorsApp = new Y.Base.create('contributorsApp', Y.App, [], {
views: {
homePage: {
type: HomePageView
},
userPage: {
type : UserPageView,
parent: 'homePage'
},
repoPage: {
type : RepoPageView,
parent: 'userPage'
}
},
initializer: function () {
this.on('homePageView:changeUser', function (e) {
this.navigate('/github/' + e.user + '/');
});
},
handleUser: function (req, res, next) {
var userId = req.params.user,
user = this.get('user'),
self = this;
if (userId === user.get('id')) {
req.user = user;
next();
} else {
user = new User({id: userId});
user.load(function () {
self.set('user', user);
req.user = user;
next();
});
}
},
handleRepos: function (req, res, next) {
var user = req.user,
repos = this.get('repos');
req.repos = repos;
if (user === repos.get('user')) {
next();
} else {
repos.set('user', user).load(function () {
next();
});
}
},
handleRepo: function (req, res, next) {
var repoId = req.params.repo;
repos = req.repos,
repo = repos.getById(repoId),
contributors = this.get('contributors');
if (!repo) {
return next('GitHub repository was not found.');
}
req.repo = repo;
req.contributors = contributors;
if (repo === contributors.get('repo')) {
next();
} else {
contributors.set('repo', repo).load(function () {
next();
});
}
},
showHomePage: function () {
this.showView('homePage', {
model: this.get('user')
});
},
showUserPage: function (req) {
this.showView('userPage', {
model : req.user,
modelList: req.repos
});
},
showRepoPage: function (req) {
this.showView('repoPage', {
model : req.repo,
modelList: req.contributors
});
}
}, {
ATTRS: {
user : {value: new User()},
repos : {value: new RepoList()},
contributors: {value: new ContributorList()},
routes: {
value: [
{path: '/', callback: 'showHomePage'},
{path: '/github/:user/*', callback: 'handleUser'},
{path: '/github/:user/*', callback: 'handleRepos'},
{path: '/github/:user/', callback: 'showUserPage'},
{path: '/github/:user/:repo/', callback: 'handleRepo'},
{path: '/github/:user/:repo/', callback: 'showRepoPage'}
]
}
}
});
// -- Go-go-gadget App! --------------------------------------------------------
new ContributorsApp({
serverRouting: false,
container : '.example',
linkSelector : '.example a',
on: {
ready: function () {
if (!this.hasRoute(this.getPath())) {
this.replace('/');
}
}
}
}).dispatch().render();
});
<script id="t-home" type="text/x-handlebars-template">
<h2 class="no-toc">Contributors of Github Projects</h2>
<div>
{{#if login}}
<input type="text" name="user" placeholder="Github Username" value="{{login}}" />
{{else}}
<input type="text" name="user" placeholder="Github Username" value="yui" />
{{/if}}
<button>Show User »</button>
</div>
</script>
<script id="t-user" type="text/x-handlebars-template">
<h2 class="no-toc">
<img src="{{avatar_url}}" alt="{{login}}'s avatar" />
{{login}} <span>({{name}})</span>
</h2>
<p>
<a href="#/">« Choose Github User</a>
</p>
</script>
<script id="t-repo-list" type="text/x-handlebars-template">
<h3>Repos</h3>
<ul>
{{#each repos}}
<li><a href="{{url}}">{{name}}</a></li>
{{/each}}
</ul>
</script>
<script id="t-repo" type="text/x-handlebars-template">
<h2 class="no-toc">
<img src="{{avatar_url}}" alt="{{login}}'s avatar" />
{{login}} / {{name}}
</h2>
<p>
<a href="{{user_url}}">« Select Repo</a>
</p>
</script>
<script id="t-contributor-list" type="text/x-handlebars-template">
<h3>Contributors</h3>
<ul>
{{#each contributors}}
<li>
<a href="{{url}}" title="{{login}}">
<img alt="{{login}}'s avatar" src="{{avatar_url}}" />
</a>
</li>
{{/each}}
</ul>
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment