Merge branch 'master' into post_window_refactor

v1.18.x
Julian Lam 12 years ago
commit 1ff77f853c

@ -7,6 +7,7 @@ require('nodefly').profile(
}
);
// Read config.js to grab redis info
var fs = require('fs'),
path = require('path'),

@ -2,7 +2,7 @@
"author": "psychobunny <andrew@designcreateplay.com>, julianlam <julian@designcreateplay.com>, barisusakli <baris@designcreateplay.com>",
"name": "NodeBB",
"description": "NodeBB Forum",
"version": "0.1",
"version": "0.0.1",
"homepage": "http://www.nodebb.org",
"repository": {
"url": "https://github.com/designcreateplay/NodeBB/"
@ -29,8 +29,7 @@
"node-gyp": "0.9.5",
"async": "0.2.8",
"node-imagemagick": "0.1.8",
"atom-writer": "1.0.3",
"xml-writer": "1.2.4",
"node-rss": "1.0.1",
"nodefly": "stable"
},
"devDependencies": {},

@ -0,0 +1,214 @@
.category {
a {
li {
list-style: none;
//border-bottom: 1px solid #eee;
margin-bottom: 10px;
padding-bottom: 10px;
&.deleted {
-moz-opacity: 0.30;
opacity: 0.30;
}
}
&:last-child li {
border-bottom: 0;
}
color: #333;
&:hover {
color: #333
}
}
ul {
margin-left: 0;
}
.thread-rating {
color: #444;
text-align: center;
margin-top: 7px;
span {
display: inline-block; margin-left: 5px;
i {
padding-left: 2.4px;
}
@media (max-width: 1200px)
{
margin-left: -1px;
}
}
}
.topic-row {
border-radius: 5px;
padding-left: 20px;
small {
vertical-align: 2px;
strong {
color: #666;
}
color: #999;
font-size: 14px;
}
h3 {
padding: 0;
margin: 0;
margin-top: 4px;
color: rgb(0, 136, 204);
line-height: 25px;
.topic-title {
width: 50%;
display: inline-block;
font-size: 20px;
white-space: nowrap;
text-overflow:ellipsis;
overflow: hidden;
.badge {
margin-right: 6px;
}
@media (max-width: 979px)
{
width: 100%;
}
}
}
@media (max-width: 979px)
{
width: 100%;
margin-left: 0px;
}
}
.latest-post {
float: right;
padding-top: 2px;
margin-right: 0px;
width: 40%;
.pull-right {
width: 100%;
height: 50px;
line-height: 16px;
margin-left: 1px;
padding: 5px;
border-left: 1px solid #bbb;
padding-left: 20px;
img {
display: block;
float: left;
}
p {
display: block;
float: left;
width: 70%;
margin-left: 10px;
overflow: hidden;
height: 32px;
}
span {
display: block;
float: left;
width: 70%;
margin-left: 10px;
overflow: hidden;
height: 16px;
margin-top: -10px;
color: #666;
}
}
}
.recent-replies {
overflow-y: auto;
overflow-x: hidden;
ul {
width: 100%;
height: 50px;
line-height: 16px;
margin-left: 1px;
padding: 5px;
li {
line-height: 16px;
img {
display: block;
float: left;
}
p {
display: block;
float: left;
width: 70%;
margin-left: 10px;
overflow: hidden;
height: 32px;
}
span {
display: block;
float: left;
width: 70%;
margin-left: 10px;
overflow: hidden;
height: 16px;
margin-top: -10px;
color: #666;
}
}
}
}
.sidebar-block {
.block-header {
padding: 8px;
padding-left: 13px;
display: block;
background: rgb(245,245,245);
color: #676;
font-weight: 400;
font-size: 14px;
border-radius: 5px 5px 0 0;
border-bottom: 1px solid #ddd;
}
.block-content {
padding: 10px;
}
border-radius: 5px;
background: white;
padding: 0;
margin-bottom: 20px;
.img-polaroid {
margin-top: 2px;
}
}
}

@ -1 +1,4 @@
@import "style";
@import "style";
@import "topic";
@import "category";

@ -1,10 +1,3 @@
.caret-left {
border-left: 0;
border-right: 4px solid black;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
}
.no-select {
-webkit-touch-callout: none;
-webkit-user-select: none;
@ -26,7 +19,7 @@
}
body {
/*background: #fdfdfd;*/
/*background: #fdfdfd;*/ // port to default theme when it is implemented.
-webkit-transition: margin-bottom 250ms ease;
-moz-transition: margin-bottom 250ms ease;
-ms-transition: margin-bottom 250ms ease;
@ -128,388 +121,7 @@ footer.footer {
.sidebar-block {
.block-header {
padding: 8px;
padding-left: 13px;
display: block;
background: rgb(245,245,245);
color: #676;
font-weight: 400;
font-size: 14px;
border-radius: 5px 5px 0 0;
border-bottom: 1px solid #ddd;
}
.block-content {
padding: 10px;
}
border-radius: 5px;
background: white;
padding: 0;
margin-bottom: 20px;
.img-polaroid {
margin-top: 2px;
}
}
.category {
a {
li {
list-style: none;
//border-bottom: 1px solid #eee;
margin-bottom: 10px;
padding-bottom: 10px;
&.deleted {
-moz-opacity: 0.30;
opacity: 0.30;
}
}
&:last-child li {
border-bottom: 0;
}
color: #333;
&:hover {
color: #333
}
}
ul {
margin-left: 0;
}
.thread-rating {
color: #444;
text-align: center;
margin-top: 7px;
span {
display: inline-block; margin-left: 5px;
i {
padding-left: 2.4px;
}
@media (max-width: 1200px)
{
margin-left: -1px;
}
}
}
.topic-row {
border-radius: 5px;
padding-left: 20px;
small {
vertical-align: 2px;
strong {
color: #666;
}
color: #999;
font-size: 14px;
}
h3 {
padding: 0;
margin: 0;
margin-top: 4px;
color: rgb(0, 136, 204);
line-height: 25px;
.topic-title {
width: 50%;
display: inline-block;
font-size: 20px;
white-space: nowrap;
text-overflow:ellipsis;
overflow: hidden;
.badge {
margin-right: 6px;
}
@media (max-width: 979px)
{
width: 100%;
}
}
}
@media (max-width: 979px)
{
width: 100%;
margin-left: 0px;
}
}
.latest-post {
float: right;
padding-top: 2px;
margin-right: 0px;
width: 40%;
.pull-right {
width: 100%;
height: 50px;
line-height: 16px;
margin-left: 1px;
padding: 5px;
border-left: 1px solid #bbb;
padding-left: 20px;
img {
display: block;
float: left;
}
p {
display: block;
float: left;
width: 70%;
margin-left: 10px;
overflow: hidden;
height: 32px;
}
span {
display: block;
float: left;
width: 70%;
margin-left: 10px;
overflow: hidden;
height: 16px;
margin-top: -10px;
color: #666;
}
}
}
.recent-replies {
overflow-y: auto;
overflow-x: hidden;
ul {
width: 100%;
height: 50px;
line-height: 16px;
margin-left: 1px;
padding: 5px;
li {
line-height: 16px;
img {
display: block;
float: left;
}
p {
display: block;
float: left;
width: 70%;
margin-left: 10px;
overflow: hidden;
height: 32px;
}
span {
display: block;
float: left;
width: 70%;
margin-left: 10px;
overflow: hidden;
height: 16px;
margin-top: -10px;
color: #666;
}
}
}
}
}
.post-container {
list-style-type: none;
padding: 0;
margin: 0;
clear: both;
.profile-image-block {
background: white;
display: inline-block;
text-align: center;
font-size: 12px;
}
li {
padding-bottom: 15px;
&.deleted {
-moz-opacity: 0.30;
opacity: 0.30;
}
}
.profile-block, .post-block {
border: 1px solid #f0f0f0;
border-radius: 5px;
padding: 10px;
}
img {
margin: 5px;
}
.profile-block {
background: #fafafa;
margin-right: -11px;
margin-left: -11px;
margin-bottom: -11px;
margin-top: 15px;
border-radius: 0 0 5px 5px;
font-size: 10px;
line-height: 18px;
padding: 5px;
padding-left: 10px;
img.hidden-desktop {
max-width: 10px;
max-height: 10px;
}
}
.post-content {
min-height: 50px;
padding: 2px 5px 0 5px;
word-wrap: break-word;
}
.post-block {
.post-buttons {
font-size: 12px;
float: right;
margin-right: 5px;
div {
display: inline-block;
padding-left: 15px;
padding-right: 15px;
border-left: 1px solid #f0f0f0;
cursor: pointer;
&:last-child {
padding-right: 5px;
}
}
.icon-star {
//theme this to make it yellow eventually
}
}
background: #fff;
}
&.deleted {
-moz-opacity: 0.30;
opacity: 0.30;
}
.main-post {
h3 {
margin: 0;
.topic-title {
width: 60%;
white-space: nowrap;
text-overflow:ellipsis;
overflow: hidden;
display: inline-block;
margin: 0;
padding: 0;
padding-top: 5px;
margin-bottom: -5px;
@media (max-width: 1200px) {
width: 500px;
}
@media (min-width: 768px) and (max-width: 979px) {
width: 320px;
}
@media (max-width: 767px) {
width: 75%;
}
}
}
.main-avatar {
color: white;
position: relative;
float: left;
margin-right: 15px;
margin-bottom: 0px;
padding-bottom: 0px;
text-align: center;
@media (max-width: 767px) {
width: 20%;
max-width: 85px;
}
@media (max-width: 400px) {
display: none;
}
}
.main-avatar:hover .hover-overlay {
opacity: 0.75;
}
.hover-overlay {
margin: 5px;
position: absolute;
bottom: 0px;
height: 35px;
padding-top: 2px;
width: 80px;
font-size: 13px;
line-height: 16px;
background: #000;
opacity: 0;
transition: opacity 0.3s;
}
.post-content {
min-height: 80px;
}
hr {
margin-top: 0;
margin-right: 10px;
margin-bottom: 0;
}
.post-block {
.post-buttons {
div {
border: 0;
}
}
}
.favourite {
cursor: pointer;
}
.btn {
display: inline-block;
}
}
}
#user_label {
#user_label { //belongs in header.less
img {
border: 1px solid #454;
margin-right: 8px;
@ -636,11 +248,12 @@ footer.footer {
padding-top:25px;
cursor: pointer;
margin-bottom: 20px;
border-radius: 5px;
}
.category-row h4 {
font-weight: 700;
text-align: left;
/*color: #555;*/
/*color: #555;*/ // NOTE: color for cat/topic header links should be grey in the default theme when we get around to it.
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

@ -0,0 +1,165 @@
.post-container {
list-style-type: none;
padding: 0;
margin: 0;
clear: both;
.profile-image-block {
background: white;
display: inline-block;
text-align: center;
font-size: 12px;
}
li {
padding-bottom: 15px;
&.deleted {
-moz-opacity: 0.30;
opacity: 0.30;
}
}
.profile-block, .post-block {
border: 1px solid #f0f0f0;
border-radius: 5px;
padding: 10px;
}
img {
margin: 5px;
}
.profile-block {
background: #fafafa;
margin-right: -11px;
margin-left: -11px;
margin-bottom: -11px;
margin-top: 15px;
border-radius: 0 0 5px 5px;
font-size: 10px;
line-height: 18px;
padding: 5px;
padding-left: 10px;
img.hidden-desktop {
max-width: 10px;
max-height: 10px;
}
}
.post-content {
min-height: 50px;
padding: 2px 5px 0 5px;
word-wrap: break-word;
}
.post-block {
.post-buttons {
font-size: 12px;
float: right;
margin-right: 5px;
div {
display: inline-block;
padding-left: 15px;
padding-right: 15px;
border-left: 1px solid #f0f0f0;
cursor: pointer;
&:last-child {
padding-right: 5px;
}
}
.icon-star {
//theme this to make it yellow eventually
}
}
background: #fff;
}
&.deleted {
-moz-opacity: 0.30;
opacity: 0.30;
}
.main-post {
h3 {
margin: 0;
.topic-title {
width: auto;
white-space: nowrap;
text-overflow:ellipsis;
overflow: hidden;
margin: 0;
padding: 0;
padding-top: 5px;
margin-bottom: -5px;
padding-bottom: 5px;
}
}
.main-avatar {
color: white;
position: relative;
float: left;
margin-right: 15px;
margin-bottom: 0px;
padding-bottom: 0px;
text-align: center;
@media (max-width: 767px) {
display: none;
}
}
.main-avatar:hover .hover-overlay {
opacity: 0.75;
}
.hover-overlay {
margin: 5px;
position: absolute;
bottom: 0px;
height: 35px;
padding-top: 2px;
width: 80px;
font-size: 13px;
line-height: 16px;
background: #000;
opacity: 0;
transition: opacity 0.3s;
}
.post-content {
min-height: 80px;
}
hr {
margin-top: 0;
margin-right: 10px;
margin-bottom: 0;
}
.post-block {
.post-buttons {
div {
border: 0;
}
}
}
.favourite {
cursor: pointer;
}
.btn {
display: inline-block;
}
.topic-buttons {
margin-top: 8px;
}
}
}

@ -38,7 +38,7 @@ var ajaxify = {};
} else if (templates[url]) {
tpl_url = url;
}
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
if (quiet !== true) {
window.history.pushState({
@ -75,6 +75,8 @@ var ajaxify = {};
ajaxify.onclick = function(ev) {
if (this.href == window.location.href + "#") return;
var url = this.href.replace(rootUrl +'/', '');
if (this.target !== '') return;
if (!ev.ctrlKey && ev.which === 1) {
if (ajaxify.go(url)) {

@ -365,13 +365,18 @@ var socket,
socket.on('api:user.get_online_users', function(users) {
jQuery('.username-field').each(function() {
var uid = jQuery(this).parents('li').attr('data-uid');
if (this.processed === true) return;
var el = jQuery(this),
uid = el.parents('li').attr('data-uid');
if (uid && jQuery.inArray(uid, users) !== -1) {
jQuery(this).prepend('<i class="icon-circle"></i>');
el.prepend('<i class="icon-circle"></i>&nbsp;');
} else {
jQuery(this).prepend('<i class="icon-circle-blank"></i>');
el.prepend('<i class="icon-circle-blank"></i>&nbsp;');
}
el.processed = true;
});
});

@ -47,6 +47,14 @@
<button id="new_post" class="btn btn-primary btn-large {show_category_features}">New Topic</button>
</div>
<div class="span3 {show_category_features} category-sidebar">
<div class="sidebar-block img-polaroid">
<div class="block-header">
<a target="_blank" href="../{category_id}.rss"><i class="icon-rss-sign icon-2x"></i></a>&nbsp;
<i class="icon-facebook-sign icon-2x"></i>&nbsp;
<i class="icon-twitter-sign icon-2x"></i>&nbsp;
<i class="icon-google-plus-sign icon-2x"></i>&nbsp;
</div>
</div>
<div class="sidebar-block img-polaroid">
<div class="block-header">
Recent Replies

@ -41,7 +41,7 @@
<div class="nav-collapse collapse">
<ul class="nav nodebb-inline-block">
<li>
<a href="/latest">Recent <span class="badge badge-inverse">3</span></a>
<a href="/latest">Recent <!--<span class="badge badge-inverse">3</span>--></a>
</li>
<!--<li>
<a href="/popular">Popular</a>

@ -23,29 +23,30 @@
<i class="icon-pencil"></i><span class="user_posts_{main_posts.uid}">8</span>
</div>
</a>
<h3><p id="topic_title_{main_posts.pid}" class="topic-title">{topic_name}</p>
<div class="pull-right hidden-phone" style="margin-right: 10px;">
<button id="ids_{main_posts.pid}_{main_posts.uid}" class="btn edit {main_posts.display_moderator_tools}" type="button"><i class="icon-pencil"></i></button>
<button id="ids_{main_posts.pid}_{main_posts.uid}" class="btn delete {main_posts.display_moderator_tools}" type="button"><i class="icon-trash"></i></button>
<button id="quote_{main_posts.pid}_{main_posts.uid}" class="btn quote" type="button"><i class="icon-quote-left"></i></button>
<button id="favs_{main_posts.pid}_{main_posts.uid}" class="favourite btn" type="button"><span class="post_rep_{main_posts.pid}">Favourite {main_posts.post_rep} </span><i class="{main_posts.fav_star_class}"></i></button>
<button id="post_reply" class="btn btn-primary btn post_reply" type="button">Reply <i class="icon-reply"></i></button>
</div>
</h3>
<h3><p id="topic_title_{main_posts.pid}" class="topic-title">{topic_name}</p></h3>
<hr />
<small>
posted {main_posts.relativeTime} ago by <strong><a href="/users/{main_posts.username}" class="username-field">{main_posts.username}</a></strong>
<span class="{main_posts.edited-class}"><i class="icon-edit" title="edited by {main_posts.editor} {main_posts.relativeEditTime} ago"></i></span>
</small>
<div class="topic-buttons pull-left">
<a href="/users/{main_posts.username}" class="username-field btn">{main_posts.username}</a>
<a target="_blank" class="btn" href="../{topic_id}.rss"><i class="icon-rss-sign"></i></a>
<button id="ids_{main_posts.pid}_{main_posts.uid}" class="btn edit {main_posts.display_moderator_tools}" type="button"><i class="icon-pencil"></i></button>
<button id="ids_{main_posts.pid}_{main_posts.uid}" class="btn delete {main_posts.display_moderator_tools}" type="button"><i class="icon-trash"></i></button>
<button id="quote_{main_posts.pid}_{main_posts.uid}" class="btn quote" type="button"><i class="icon-quote-left"></i></button>
<button id="favs_{main_posts.pid}_{main_posts.uid}" class="favourite btn" type="button"><span class="post_rep_{main_posts.pid}">Favourite {main_posts.post_rep} </span><i class="{main_posts.fav_star_class}"></i></button>
<button id="post_reply" class="btn btn-primary btn post_reply" type="button">Reply <i class="icon-reply"></i></button>
</div>
<div style="clear:both; margin-bottom: 10px;"></div>
<div id="content_{main_posts.pid}" class="post-content">{main_posts.content}</div>
<div class="post-signature">{main_posts.signature}</div>
<div class="profile-block"></div>
<div class="profile-block">
<img class="hidden-desktop" src="{main_posts.gravatar}?s=10&default=identicon" align="left" /> posted by <strong><a class="" href="/users/{main_posts.username}">{main_posts.username}</a></strong> {main_posts.relativeTime} ago
<span class="{main_posts.edited-class} hidden-phone">| last edited by <strong><a href="/users/{main_posts.editor}">{main_posts.editor}</a></strong> {main_posts.relativeEditTime} ago</span>
<span class="{main_posts.edited-class}"><i class="icon-edit visible-phone" title="edited by {main_posts.editor} {main_posts.relativeEditTime} ago"></i></span>
</div>
</div>
</div>
</li>

@ -166,6 +166,7 @@ var RDB = require('./redis.js'),
for (var i=0, ii=tids.length; i<ii; i++) {
if (!deleted[i] || (deleted[i] && privileges.view_deleted) || uid[i] === current_user) {
retrieved_topics.push({
'tid' : tids[i],
'title' : title[i],
'uid' : uid[i],
'username': usernames[i],
@ -261,7 +262,7 @@ var RDB = require('./redis.js'),
}
Categories.getRecentReplies = function(cid, callback) {
RDB.zrange('categories:recent_posts:cid:' + cid, 0, -1, function(err, pids) {
RDB.zrange('categories:recent_posts:cid:' + cid, 0, 4, function(err, pids) {
if (pids.length == 0) {
callback(false);
return;

@ -3,43 +3,33 @@
schema = require('./schema.js'),
posts = require('./posts.js'),
topics = require('./topics.js'),
fs = require('fs');
fs = require('fs'),
rss = require('node-rss');
function saveFeed(feed, xml, tid) {
feed.endEntry();
fs.writeFile('feeds/topics/' + tid + '.rss', xml.toString(), function (err) {
function saveFeed(location, feed) {
console.log(rss.getFeedXML(feed));
console.log('derp');
fs.writeFile(location, rss.getFeedXML(feed), function (err) {
if (err) throw err;
});
}
function createFeed(xml, urn, title, feed_url, author) {
var ATOMWriter = require('atom-writer'),
feed = new ATOMWriter(xml);
return feed
.startFeed(urn)
.writeStartIndex(1)
.writeItemsPerPage(20)
.writeTotalResults(20)
.writeTitle(title)
.writeLink(feed_url, 'application/atom+xml', 'self');
function createFeed(title, description, feed_url, xml_url, author, urn) {
return rss.createNewFeed(
title,
feed_url,
description,
author,
xml_url,
{
'urn' : urn
}
);
}
function createEntry(feed, urn, title, content, url, author) {
return feed
.startEntry(urn)
.writeTitle(title)
.writeLink(url, 'text/html')
.writeContent(content, 'text', 'en')
.writeAuthorRAW(author)
.endEntry();
}
Feed.updateTopic = function(tid, cid) {
var cache_time_in_seconds = 60,
XMLWriter = require('xml-writer');
xml = new XMLWriter(true);
var cache_time_in_seconds = 60;
function getTopicData(next) {
topics.getTopicById(tid, 0, function(topicData) {
@ -58,25 +48,65 @@
var topicData = results[0],
postsData = results[1].postData,
userData = results[1].userData,
url = '/topic/' + topicData.slug;
location = '/topic/' + topicData.slug,
xml_url = '/topic/' + tid + '.rss';
var post = topicData.main_posts[0];
var urn = 'urn:' + cid + ':' + tid;
var feed = createFeed(xml, urn, topicData.topic_name, url, post.username);
var feed = createFeed(topicData.topic_name, '', location, xml_url, post.username, urn);
var title;
for (var i = 0, ii = postsData.pid.length; i < ii; i++) {
urn = 'urn:' + cid + ':' + tid + ':' + postsData.pid[i];
title = 'Reply to ' + topicData.topic_name + ' on ' + (new Date(parseInt(postsData.timestamp[i], 10)).toUTCString());
feed = createEntry(feed, urn, title, postsData.content[i], url, userData[postsData.uid[i]].username);
feed.addNewItem(
title,
location,
postsData.timestamp[i],
postsData.content[i],
{
'urn' : urn,
'username' : userData[postsData.uid[i]].username
}
);
}
saveFeed(feed, xml, tid);
saveFeed('feeds/topics/' + tid + '.rss', feed);
});
};
Feed.updateCategory = function(params) {
Feed.updateCategory = function(cid) {
categories.getCategoryById(cid, 0, function(categoryData) {
var location = '/category/' + categoryData.category_id + '/' + categoryData.category_name,
xml_url = '/category' + cid + '.rss';
var urn = 'urn:' + cid;
var feed = createFeed(categoryData.category_name, '', location, xml_url, 'NodeBB', urn); // not exactly sure if author for a category should be site_title?
var title;
var topics = categoryData.topics;
for (var i = 0, ii = topics.length; i < ii; i++) {
urn = 'urn:' + cid + ':' + topics[i].tid;
title = topics[i].title + '. Posted on ' + (new Date(parseInt(topics[i].timestamp, 10)).toUTCString());
feed.addNewItem(
title,
location,
topics[i].timestamp,
topics[i].teaser_text,
{
'urn' : urn,
'username' : topics[i].username
}
);
}
saveFeed('feeds/categories/' + cid + '.rss', feed);
});
};
}(exports));

@ -7,7 +7,8 @@ var RDB = require('./redis.js')
posts = require('./posts.js'),
marked = require('marked'),
threadTools = require('./threadTools.js'),
async = require('async');
async = require('async'),
feed = require('./feed.js');
marked.setOptions({
breaks: true
@ -370,6 +371,8 @@ marked.setOptions({
});
RDB.incr('cid:' + category_id + ':topiccount');
feed.updateCategory(category_id);
});
});
};

@ -118,7 +118,19 @@ var express = require('express'),
});
app.get('/category/:category_id/:slug?', function(req, res) {
var category_url = req.params.category_id + (req.params.slug ? '/' + req.params.slug : '');
var cid = req.params.category_id;
if (cid.match('.rss')) {
fs.readFile('feeds/categories/' + cid, function (err, data) {
if (err) {
res.send("Unable to locate an rss feed at this location.");
return;
}
res.send(data);
});
return;
}
var category_url = cid + (req.params.slug ? '/' + req.params.slug : '');
res.send(build_header() + '<script>templates.ready(function(){ajaxify.go("category/' + category_url + '");});</script>' + templates['footer']);
});

Loading…
Cancel
Save