Permalink
Browse files

adding a comment / issue mostly works now

  • Loading branch information...
1 parent 3deee46 commit b80992e07e1f41599998a292dccb30275e063990 @pgte pgte committed Apr 26, 2012
View
7 public/assets/discussions/comment.html
@@ -0,0 +1,7 @@
+<article class="comment">
+ <img src="" class="avatar" />
+ <div class="meta">
+ <span class="author value"></span> replied at <span class="created value"></span>
+ </div>
+ <p class="body"></p>
+</article>
View
18 public/assets/discussions/discussion.html
@@ -1,9 +1,15 @@
-<article class="discussion" data-url="">
+<article class="discussion clearfix" data-url="">
<img src="" class="avatar" />
- <h3 class="title"></h3>
- <p class="body"></p>
- <div class="meta">
- Posted at <span class="created value"></span>,
- <a href="">Reply</a>
+ <div class="bubble">
+ <div class="meta">
+ <span class="author value"></span> posted at <span class="created value"></span>
+ </div>
+ <h3 class="title"></h3>
+ <p class="body"></p>
+ <div class="meta">
+ <a class="reply" href="#">Reply</a>
+ </div>
+ </div>
+ <div class="comments">
</div>
</article>
View
3 public/assets/discussions/index.html
@@ -1,4 +1,4 @@
-<form action="" method="POST">
+<form class="newdiscussion" action="" method="POST">
<fieldset>
<legend>Start a new discussion:</legend>
<p>
@@ -9,6 +9,7 @@
<input class="submit" type="submit" />
</p>
</fieldset>
+ <input type="hidden" name="article" value="" />
</form>
<div class="discussionlist">
View
8 public/assets/pages/article.html
@@ -21,22 +21,22 @@
</section>
<div id="meta">
- <section id="contributors" class="container">
+ <section id="contributors" class="clearfix">
<h3>Contributors:</h3>
<ul id="contributorlist" />
</section>
- <section id="taglist" class="container">
+ <section id="taglist" class="clearfix">
<h3>Tags:</h3>
<ul id="tags" />
</section>
- <section id="categorylist" class="container">
+ <section id="categorylist" class="clearfix">
<h3>Categories:</h3>
<ul id="categories" />
</section>
- <section id="discuss" class="container">
+ <section id="discuss" class="clearfix">
<h3>Discuss:</h3>
<div id="discussions" />
</section>
View
31 public/css/index.css
@@ -3309,6 +3309,7 @@ body {
#discussions {
padding: 2em;
+ padding-left: 70px;
}
#discussions fieldset legend {
padding-left: 0;
@@ -3328,14 +3329,11 @@ body {
vertical-align: bottom;
}
-#discussions .discussionlist {
- border-top: 1px solid #ddd;
-}
-#discussions article .avatar {
- float: left;
- margin: 1em;
+#discussions article.discussion {
+ margin-bottom: 2em;
}
+
#discussions article:before {
display: table;
content: "";
@@ -3345,6 +3343,22 @@ body {
clear: both;
}
+#discussions .bubble {
+ padding: 3px;
+ background: #EEE;
+ border-radius: 3px;
+ padding: 1em;
+}
+
+#discussions article .avatar {
+ width: 48px;
+ height: auto;
+ border-radius: 3px;
+ position: relative;
+ float: left;
+ margin-left: -60px;
+}
+
#discussions article .body {
margin: 1em;
}
@@ -3353,4 +3367,9 @@ body {
font-size: 10px;
text-align: left;
color: #222;
+}
+
+#discussions .comments {
+ padding: 1em;
+ padding-left: 70px;
}
View
34 public/js/hubbleio.js
@@ -4,12 +4,15 @@
* AJAX!!!!
*********************/
- function ajax(method, url, callback) {
+ function ajax(method, url, data, callback) {
$.ajax({
type: method,
url: url,
+ data: data,
success: function(data) {
- callback(null, JSON.parse(data));
+ try { data = JSON.parse(data); }
+ catch(error) { }
+ callback(null, data);
},
error: function(request, text, error) {
var message = request.responseText || text || '';
@@ -19,8 +22,12 @@
});
}
- function post(url, callback) {
- return ajax('POST', url, callback);
+ function post(url, data, callback) {
+ if (typeof data === 'function') {
+ callback = data;
+ data = undefined;
+ }
+ return ajax('POST', url, data, callback);
}
/*********************
@@ -132,4 +139,23 @@
});
+ /*********************
+ * Discussions
+ *********************/
+
+ $('#discuss form').submit(function(ev) {
+ ev.preventDefault();
+ var form = $(this);
+ form.attr('disabled', 'disabled')
+ post(form.attr('action'), form.serialize(), function(err) {
+ console.log('back');
+ form.attr('disabled', '');
+ if (err) {
+ alert(err.message);
+ return;
+ }
+ document.location = '#discuss';
+ document.location.reload();
+ });
+ });
}());
View
54 server/assets.js
@@ -1,7 +1,10 @@
var fs = require('fs'),
Plates = require('plates'),
_ = require('underscore'),
- sort = require('./sort');
+ marked = require('github-flavored-markdown').parse,
+ hl = require('highlight').Highlight,
+ sort = require('./sort')
+;
var escape = encodeURIComponent;
@@ -56,7 +59,7 @@ module.exports = function(conf) {
"articleCategories": articleCategories,
"tags": assets['tags.html'].compose(repo.meta.tags),
"suggestions": suggestionMarkup,
- "discussions": assets['discussions/index.html'].compose(repo.discussions)
+ "discussions": assets['discussions/index.html'].compose(repo, repo.discussions)
};
var title = repo.meta.title || repo.github.title;
var nav = assets['nav/article.html'].compose(repo.github.name);
@@ -423,40 +426,73 @@ module.exports = function(conf) {
assets['discussions/index.html'] = {
raw: fs.readFileSync('./public/assets/discussions/index.html', 'utf8'),
- compose: function(discussions) {
+ compose: function(repo, discussions) {
var discussions = discussions.map(function(discussion) {
- return assets['discussions/discussion.html'].compose(discussion);
+ return assets['discussions/discussion.html'].compose(repo, discussion);
}).join('');
var map = new Plates.Map();
+ map.class('newdiscussion').use('url').as('action');
map.class('discussionlist').use('discussionlist');
var data = {
+ url: '/article/' + escape(repo.github.name) + '/comment',
discussionlist: discussions
};
- return Plates.bind(this.raw, data);
+ return Plates.bind(this.raw, data, map);
}
};
assets['discussions/discussion.html'] = {
raw: fs.readFileSync('./public/assets/discussions/discussion.html', 'utf8'),
- compose: function(discussion) {
+ compose: function(repo, discussion) {
var map = new Plates.Map();
+ map.class('author').use('author');
map.class('title').use('title');
map.class('body').use('body');
map.class('avatar').use('avatar').as('src');
- map.class('created').use('created')
+ map.class('created').use('created');
+ map.class('comments').use('comments');
+ map.class('discussion').use('url').as('data-url')
+
+ var commentsMarkup = (discussion.comments || []).map(function(comment) {
+ return assets['discussions/comment.html'].compose(comment);
+ }).join('');
var data = {
+ url: '/articles/' + escape(repo.github.name) + '/comment',
+ author: '<a href="https://github.com/' + discussion.user.login + '">' + discussion.user.login + '</a>',
title: discussion.title,
- body: discussion.body || "Lorem Ipsum",
+ body: hl(marked(discussion.body), false, true),
avatar: discussion.user && discussion.user.avatar_url,
- created: discussion.created_at
+ created: discussion.created_at,
+ comments: commentsMarkup
}
return Plates.bind(this.raw, data, map);
}
+ };
+
+ assets['discussions/comment.html'] = {
+ raw: fs.readFileSync('./public/assets/discussions/comment.html', 'utf8'),
+ compose: function(comment) {
+
+ var map = new Plates.Map();
+ map.class('author').use('author');
+ map.class('avatar').use('avatar').as('src');
+ map.class('body').use('body');
+ map.class('created').use('created')
+
+ var data = {
+ author: '<a href="https://github.com/' + comment.user.login + '">' + comment.user.login + '</a>',
+ body: hl(marked(comment.body), false, true),
+ avatar: comment.user && comment.user.avatar_url,
+ created: comment.created_at
+ };
+
+ return Plates.bind(this.raw, data, map);
+ }
}
return assets;
View
30 server/comments.js
@@ -1,17 +1,35 @@
-var Github = require('./github');
+var async = require('async'),
+ Github = require('./github');
module.exports = function(conf) {
var issues = Github(conf).issues;
function get(repo, callback) {
- issues.get(repo, callback);
+ issues.get(repo, function(err, retIssues) {
+ if (err) { return callback(err); }
+ async.forEach(retIssues, function(issue, done) {
+ issues(repo, issue.number).comments.get(function(err, comments) {
+ issue.comments = comments;
+ done();
+ });
+ }, function(err) {
+ if (err) { return callback(err); }
+ callback(null, retIssues);
+ });
+ });
}
function create(repo) {
- console.log(this.req);
- this.res.end();
- return;
- issues.create(repo, title, body, callback);
+ var that = this;
+ issues.create.call(this, repo, this.req.body.title, this.req.body.body, function(err) {
+ if (err) {
+ console.error(err);
+ that.res.writeHead(500);
+ that.res.end(err.message);
+ return;
+ }
+ that.res.end();
+ });
}
function reply(repo, issue, body, callback) {
View
1 server/content.js
@@ -231,7 +231,6 @@ Content.prototype.downloadComments = function(callback) {
comments.get(repo, function(err, comments) {
if (err) { return next(err); }
- console.log(comments);
that.repos[repoName].discussions = comments;
next();
});
View
107 server/github.js
@@ -1,7 +1,30 @@
var request = require('request'),
bubble = require('bubble'),
escape = encodeURIComponent,
- GITHUB_BASE_URL = 'https://api.github.com';
+ GITHUB_BASE_URL = 'https://api.github.com'
+ ;
+
+function handleRequest(expectedStatusCode, callback) {
+ var req = this.req;
+ return function(err, resp, body) {
+ if (err) {
+ console.error(err);
+ return callback(err);
+ }
+ if (resp.statusCode !== expectedStatusCode) {
+ try { body = JSON.parse(body); }
+ catch(error) { }
+ err = new Error('Github expected response status code is ' + resp.statusCode + ': ' + body.message || body);
+ return callback(err)
+ }
+ console.log('body: %j', body);
+ if (typeof body === 'string') {
+ try { body = JSON.parse(body); }
+ catch(error) { err = error; }
+ }
+ return callback(err, body);
+ }
+}
function Github(conf) {
@@ -43,27 +66,15 @@ function Github(conf) {
repo.github.name],
this.req.session);
- request.put(url, b(function(response) {
+ request.put(url, handleRequest.call(that, 201, b(function() {
- if (response.statusCode < 200 || response.statusCode >= 300) {
- if (response.statusCode === 404) {
- throw new Error('You already watch this repo');
- }
- throw new Error('Reply to github watch was status code:' + response.statusCode);
- }
-
var url = githubRepoActionURL([ 'repos', conf.orgname, repo.github.name]);
- request.get(url, b(function(resp, body) {
- if (response.statusCode < 200 || response.statusCode >= 300) {
- throw new Error('Reply from github repo get:' + response.statusCode);
- }
-
- repo.github = JSON.parse(body);
-
- }));
+ request.get(url, handleRequest.call(that, 200, b(function(body) {
+ repo.github = body;
+ })));
- }));
+ })));
}
@@ -113,14 +124,10 @@ function Github(conf) {
});
- request.get(url, b(function(resp, body) {
- if (response.statusCode < 200 || response.statusCode >= 300) {
- throw new Error('Reply from github repo get:' + response.statusCode);
- }
-
- repo.github = JSON.parse(body);
+ request.get(url, handleRequest.call(that, 200, b(function(body) {
+ repo.github = body;
- }));
+ })));
}));
@@ -134,35 +141,38 @@ function Github(conf) {
var issues = (function() {
function get(repo, callback) {
- request.get(githubRepoActionURL([ 'repos', conf.orgname, repo.github.name, 'issues']), function(err, resp, body) {
- if (err) { return callback(err); }
- try { body = JSON.parse(body); }
- catch(error) { err = error; }
- callback(err, body);
- });
+ request.get(githubRepoActionURL([ 'repos', conf.orgname, repo.github.name, 'issues']), handleRequest.call(this, 200, callback));
}
function create(repo, title, body, callback) {
+
+ if (! this.req.session.user || ! this.req.session.user.login) {
+ this.res.writeHead(403);
+ return this.res.end('Please login first');
+ }
+
var options = {
uri: githubRepoActionURL(['repos', conf.orgname, repo.github.name, 'issues'], this.req.session),
- qs: {
+ json: {
title: title,
body: body
}
};
- request.post(options, function(err, resp, body) {
- if (err) { return callback(err); }
- if (resp.statusCode !== 201) {
- err = new Error('Github issue create returned status code ' + resp.statusCode);
- }
- callback(err);
- });
+ console.log(options);
+
+ request.post(options, handleRequest.call(this, 201, callback));
}
- function issues(issue) {
+ function issues(repo, issue) {
function createComment(body, callback) {
+
+ if (! this.req.session.user || ! this.req.session.user.login) {
+ this.res.writeHead(403);
+ return this.res.end('Please login first');
+ }
+
var url = githubRepoActionURL([ 'repos',
conf.orgname,
repo.github.name,
@@ -171,15 +181,22 @@ function Github(conf) {
'comments'],
this.req.session);
- request.post(url, function(err, resp, body) {
- if (err) { return callback(err); }
- if (res.statusCode !== 201) { err = new Error('Error creating comment on github. status code: ' + resp.statusCode); }
- callback(err);
- });
+ request.post(url, handleRequest.call(this, 201, callback));
+ }
+
+ function get(callback) {
+ var url = githubRepoActionURL([ 'repos',
+ conf.orgname,
+ repo.github.name,
+ 'issues',
+ issue,
+ 'comments']);
+ request.get(url, handleRequest.call(this, 200, callback));
}
return {
comments: {
+ get: get,
create: createComment
}
}
View
4 server/server.js
@@ -15,12 +15,14 @@ var director = require('director'),
githubAuth = require('./auth/github'),
personalize = require('./personalize'),
Github = require('./github');
+ Comments = require('./comments');
var server = exports;
server.createServer = function(content, conf) {
- var github = Github(conf);
+ var github = Github(conf),
+ comments = Comments(conf);
function findRepo(name) {
var repo = content.getRepo(name);

0 comments on commit b80992e

Please sign in to comment.