mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-22 16:30:34 +01:00
Merge branch 'master' into user_groups
This commit is contained in:
@@ -16,7 +16,11 @@ Please support NodeBB development! Check out our IndieGoGo campaign and like, sh
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
NodeBB requires a version of Node.js at least 0.8 or greater, and a Redis version 2.6 or greater.
|
NodeBB requires the following software to be installed:
|
||||||
|
|
||||||
|
* A version of Node.js at least 0.8 or greater
|
||||||
|
* Redis, version 2.6 or greater.
|
||||||
|
* nginx, version 1.3.13 or greater
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|||||||
@@ -101,69 +101,87 @@
|
|||||||
|
|
||||||
@-webkit-keyframes scroll-2 /* Safari and Chrome */
|
@-webkit-keyframes scroll-2 /* Safari and Chrome */
|
||||||
{
|
{
|
||||||
0% {top: 0px;}
|
0% {top: 0px;}
|
||||||
25% {top: -90px;}
|
3% {top:-90px;}
|
||||||
50% {top: -180px;}
|
25% {top: -90px;}
|
||||||
75% {top: -270px;}
|
28% {top:-180px;}
|
||||||
|
50% {top: -180px;}
|
||||||
|
53% {top: -270px;};
|
||||||
|
75% {top: -270px;}
|
||||||
|
78% {top: -360px;}
|
||||||
100% {top: -360px;}
|
100% {top: -360px;}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scroll-2
|
@keyframes scroll-2
|
||||||
{
|
{
|
||||||
0% {top: 0px;}
|
0% {top: 0px;}
|
||||||
25% {top: -90px;}
|
3% {top:-90px;}
|
||||||
50% {top: -180px;}
|
25% {top: -90px;}
|
||||||
75% {top: -270px;}
|
28% {top:-180px;}
|
||||||
|
50% {top: -180px;}
|
||||||
|
53% {top: -270px;};
|
||||||
|
75% {top: -270px;}
|
||||||
|
78% {top: -360px;}
|
||||||
100% {top: -360px;}
|
100% {top: -360px;}
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes scroll-1 /* Safari and Chrome */
|
@-webkit-keyframes scroll-1 /* Safari and Chrome */
|
||||||
{
|
{
|
||||||
0% {top: 0px;}
|
0% {top: 0px;}
|
||||||
33% {top: -90px;}
|
3% {top:-90px;}
|
||||||
66% {top: -180px;}
|
33% {top: -90px;}
|
||||||
100% {top: -270px;}
|
36% {top: -180px;}
|
||||||
|
66% {top: -180px;}
|
||||||
|
69% {top: -270px;}
|
||||||
|
100% {top: -270px;}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scroll-1
|
@keyframes scroll-1
|
||||||
{
|
{
|
||||||
0% {top: 0px;}
|
0% {top: 0px;}
|
||||||
33% {top: -90px;}
|
3% {top:-90px;}
|
||||||
66% {top: -180px;}
|
33% {top: -90px;}
|
||||||
100% {top: -270px;}
|
36% {top: -180px;}
|
||||||
|
66% {top: -180px;}
|
||||||
|
69% {top: -270px;}
|
||||||
|
100% {top: -270px;}
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes scroll-0 /* Safari and Chrome */
|
@-webkit-keyframes scroll-0 /* Safari and Chrome */
|
||||||
{
|
{
|
||||||
0% {top: 0px;}
|
0% {top: 0px;}
|
||||||
50% {top: -90px;}
|
3% {top:-90px;}
|
||||||
100% {top: -180px;}
|
50% {top: -90px;}
|
||||||
|
53% {top: -180px;}
|
||||||
|
100% {top: -180px;}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scroll-0
|
@keyframes scroll-0
|
||||||
{
|
{
|
||||||
0% {top: 0px;}
|
0% {top: 0px;}
|
||||||
50% {top: -90px;}
|
3% {top:-90px;}
|
||||||
100% {top: -180px;}
|
50% {top: -90px;}
|
||||||
|
53% {top: -180px;}
|
||||||
|
100% {top: -180px;}
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-slider-2:hover {
|
.category-slider-2:hover {
|
||||||
position:relative;
|
position:relative;
|
||||||
|
|
||||||
-webkit-animation: scroll-2 10s ease 0.5s infinite normal;
|
-webkit-animation: scroll-2 10s ease-in 0.5s infinite normal;
|
||||||
animation: scroll-2 10s ease 0.5s infinite normal;/* Safari and Chrome: */
|
animation: scroll-2 10s ease-in 0.5s infinite normal;/* Safari and Chrome: */
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-slider-1:hover {
|
.category-slider-1:hover {
|
||||||
position:relative;
|
position:relative;
|
||||||
|
|
||||||
-webkit-animation: scroll-1 8s ease 0.5s infinite normal;
|
-webkit-animation: scroll-1 8s ease-in 0.5s infinite normal;
|
||||||
animation: scroll-1 8s ease 0.5s infinite normal;/* Safari and Chrome: */
|
animation: scroll-1 8s ease-in 0.5s infinite normal;/* Safari and Chrome: */
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-slider-0:hover {
|
.category-slider-0:hover {
|
||||||
position:relative;
|
position:relative;
|
||||||
|
|
||||||
-webkit-animation: scroll-0 6s ease 0.5s infinite normal;
|
-webkit-animation: scroll-0 6s ease-in 0.5s infinite normal;
|
||||||
animation: scroll-0 6s ease 0.5s infinite normal;/* Safari and Chrome: */
|
animation: scroll-0 6s ease-in 0.5s infinite normal;/* Safari and Chrome: */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,10 +136,6 @@ footer.footer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#right-menu{
|
|
||||||
float:right;
|
|
||||||
}
|
|
||||||
|
|
||||||
#chat-content {
|
#chat-content {
|
||||||
height:200px;
|
height:200px;
|
||||||
resize:none;
|
resize:none;
|
||||||
@@ -257,6 +253,11 @@ footer.footer {
|
|||||||
/* END: post-window needs to go in its own plugin area */
|
/* END: post-window needs to go in its own plugin area */
|
||||||
|
|
||||||
|
|
||||||
|
//theme
|
||||||
|
#search-form .btn-link {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//START: FIXES FOR BS3, may need to remove these when we get out of the RC releases
|
//START: FIXES FOR BS3, may need to remove these when we get out of the RC releases
|
||||||
@media (max-width: 979px) {
|
@media (max-width: 979px) {
|
||||||
@@ -266,9 +267,11 @@ footer.footer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.container > .navbar-header, .container > .navbar-collapse {
|
@media (min-width: 760px) {
|
||||||
padding-right: 0;
|
.container > .navbar-header, .container > .navbar-collapse {
|
||||||
margin-right: -11px;
|
padding-right: 0;
|
||||||
|
margin-right: -11px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
.badge {
|
||||||
|
|||||||
@@ -152,36 +152,38 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main-post {
|
.main-post {
|
||||||
h3 {
|
.main-post-buttons {
|
||||||
margin: 0;
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
.topic-title {
|
.topic-title {
|
||||||
width: auto;
|
width: auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 0 0 -5px 0;
|
margin: 0 0 -5px 0;
|
||||||
padding: 0 0 5px 0
|
padding: 0 0 5px 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.main-avatar {
|
.main-avatar {
|
||||||
color: white;
|
color: white;
|
||||||
position: relative;
|
position: relative;
|
||||||
float: left;
|
float: left;
|
||||||
margin: 0 10px 0 0;
|
margin: 0 10px 0 0;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width:100px;
|
width:100px;
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
display: none;
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-thumbnail {
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-thumbnail {
|
|
||||||
padding: 2px;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-content {
|
.post-content {
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ var socket,
|
|||||||
API_URL = data.api_url;
|
API_URL = data.api_url;
|
||||||
|
|
||||||
config = data;
|
config = data;
|
||||||
socket = io.connect(config.socket.address + (config.socket.port ? ':' + config.socket.port : ''));
|
socket = io.connect(config.socket.address);
|
||||||
|
|
||||||
var reconnecting = false;
|
var reconnecting = false;
|
||||||
var reconnectTries = 0;
|
var reconnectTries = 0;
|
||||||
@@ -314,6 +314,18 @@ var socket,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.openChat = function(username, touid) {
|
||||||
|
require(['chat'], function(chat) {
|
||||||
|
var chatModal;
|
||||||
|
if(!chat.modalExists(touid)) {
|
||||||
|
chatModal = chat.createModal(username, touid);
|
||||||
|
} else {
|
||||||
|
chatModal = chat.getModal(touid);
|
||||||
|
}
|
||||||
|
chat.load(chatModal.attr('UUID'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
app.createNewPosts = function(data) {
|
app.createNewPosts = function(data) {
|
||||||
data.posts[0].display_moderator_tools = 'none';
|
data.posts[0].display_moderator_tools = 'none';
|
||||||
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data),
|
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data),
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
followBtn.show();
|
followBtn.show();
|
||||||
unfollowBtn.hide();
|
unfollowBtn.hide();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
followBtn.hide();
|
||||||
|
unfollowBtn.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
followBtn.on('click', function() {
|
followBtn.on('click', function() {
|
||||||
@@ -54,17 +57,19 @@
|
|||||||
|
|
||||||
var onlineStatus = $('.account-online-status');
|
var onlineStatus = $('.account-online-status');
|
||||||
|
|
||||||
socket.on('api:user.isOnline', function(online) {
|
function handleUserOnline(data) {
|
||||||
if(online) {
|
if(data.online) {
|
||||||
onlineStatus.find('span span').text('online');
|
onlineStatus.find('span span').text('online');
|
||||||
onlineStatus.find('i').attr('class', 'icon-circle');
|
onlineStatus.find('i').attr('class', 'icon-circle');
|
||||||
} else {
|
} else {
|
||||||
onlineStatus.find('span span').text('offline');
|
onlineStatus.find('span span').text('offline');
|
||||||
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
socket.emit('api:user.isOnline', theirid);
|
socket.on('api:user.isOnline', handleUserOnline);
|
||||||
|
|
||||||
|
socket.emit('api:user.isOnline', theirid, handleUserOnline);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
if(parseInt(followersCount, 10) === 0) {
|
if(parseInt(followersCount, 10) === 0) {
|
||||||
$('#no-followers-notice').show();
|
$('#no-followers-notice').removeClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
app.addCommasToNumbers();
|
app.addCommasToNumbers();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
if(parseInt(followingCount, 10) === 0) {
|
if(parseInt(followingCount, 10) === 0) {
|
||||||
$('#no-following-notice').show();
|
$('#no-following-notice').removeClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,16 @@
|
|||||||
|
|
||||||
socket.on('api:updateHeader', function(data) {
|
socket.on('api:updateHeader', function(data) {
|
||||||
|
|
||||||
|
jQuery('#search-button').on('click', function() {
|
||||||
|
jQuery('#search-fields').removeClass('hide').show();
|
||||||
|
jQuery(this).hide();
|
||||||
|
jQuery('#search-fields input').focus()
|
||||||
|
|
||||||
|
jQuery('#search-form').on('submit', function() {
|
||||||
|
jQuery('#search-fields').hide();
|
||||||
|
jQuery('#search-button').show();
|
||||||
|
});
|
||||||
|
});
|
||||||
var rightMenu = $('#right-menu'),
|
var rightMenu = $('#right-menu'),
|
||||||
isLoggedIn = data.uid > 0;
|
isLoggedIn = data.uid > 0;
|
||||||
|
|
||||||
@@ -162,25 +172,18 @@
|
|||||||
socket.on('chatMessage', function(data) {
|
socket.on('chatMessage', function(data) {
|
||||||
|
|
||||||
require(['chat'], function(chat) {
|
require(['chat'], function(chat) {
|
||||||
var chatModal = chat.createModalIfDoesntExist(data.username, data.fromuid, function(created, modal) {
|
var modal = null;
|
||||||
if(!created)
|
if(chat.modalExists(data.fromuid)) {
|
||||||
chat.appendChatMessage(modal, data.message, data.timestamp);
|
modal = chat.getModal(data.fromuid);
|
||||||
});
|
chat.appendChatMessage(modal, data.message, data.timestamp);
|
||||||
|
} else {
|
||||||
|
modal = chat.createModal(data.username, data.fromuid);
|
||||||
|
}
|
||||||
|
|
||||||
chatModal.show();
|
chat.load(modal.attr('UUID'));
|
||||||
chat.bringModalToTop(chatModal);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('chatGoOffline', function(data) {
|
|
||||||
require(['chat'], function(chat) {
|
|
||||||
if(chat.modalOpen(data.uid)) {
|
|
||||||
var modal = chat.getModal(data.uid);
|
|
||||||
chat.appendChatMessage(modal, data.username + ' went offline\n', data.timestamp);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
require(['mobileMenu'], function(mobileMenu) {
|
require(['mobileMenu'], function(mobileMenu) {
|
||||||
mobileMenu.init();
|
mobileMenu.init();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,9 +10,14 @@
|
|||||||
if (password.value.length < 6) {
|
if (password.value.length < 6) {
|
||||||
$('#error').hide();
|
$('#error').hide();
|
||||||
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
|
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
|
||||||
noticeEl.querySelector('p').innerHTML = 'The password entered it too short, please pick a different password!';
|
noticeEl.querySelector('p').innerHTML = 'The password entered is too short, please pick a different password.';
|
||||||
noticeEl.style.display = 'block';
|
noticeEl.style.display = 'block';
|
||||||
} else if (password.value === repeat.value) {
|
} else if (password.value !== repeat.value) {
|
||||||
|
$('#error').hide();
|
||||||
|
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
|
||||||
|
noticeEl.querySelector('p').innerHTML = 'The two passwords you\'ve entered do not match.';
|
||||||
|
noticeEl.style.display = 'block';
|
||||||
|
} else {
|
||||||
socket.emit('user:reset.commit', { code: reset_code, password: password.value });
|
socket.emit('user:reset.commit', { code: reset_code, password: password.value });
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|||||||
@@ -67,7 +67,8 @@
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
moveThreadModal.on('shown', function() {
|
moveThreadModal.on('shown.bs.modal', function() {
|
||||||
|
|
||||||
var loadingEl = document.getElementById('categories-loading');
|
var loadingEl = document.getElementById('categories-loading');
|
||||||
if (loadingEl) {
|
if (loadingEl) {
|
||||||
socket.once('api:categories.get', function(data) {
|
socket.once('api:categories.get', function(data) {
|
||||||
@@ -287,11 +288,7 @@
|
|||||||
if(username === app.username || !app.username)
|
if(username === app.username || !app.username)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
require(['chat'], function(chat) {
|
app.openChat(username, touid);
|
||||||
var chatModal = chat.createModalIfDoesntExist(username, touid);
|
|
||||||
chatModal.modal();
|
|
||||||
chat.bringModalToTop(chatModal); // I don't think this is necessary
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ajaxify.register_events([
|
ajaxify.register_events([
|
||||||
@@ -379,6 +376,18 @@
|
|||||||
this.innerHTML = data.content;
|
this.innerHTML = data.content;
|
||||||
$(this).fadeIn(250);
|
$(this).fadeIn(250);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(data.uploadedImages && data.uploadedImages.length) {
|
||||||
|
$('#images_'+data.pid).html('');
|
||||||
|
for(var i=0; i< data.uploadedImages.length; ++i) {
|
||||||
|
var img = $('<i class="icon-picture icon-1"></i><a href="' + data.uploadedImages[i].url +'"> '+data.uploadedImages[i].name+'</a><br/>');
|
||||||
|
$('#images_' + data.pid).append(img);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$('#images_'+data.pid).html('');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('time to recreate images', data);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:posts.favourite', function(data) {
|
socket.on('api:posts.favourite', function(data) {
|
||||||
|
|||||||
@@ -17,46 +17,74 @@ define(['taskbar'], function(taskbar) {
|
|||||||
return $('#chat-modal-' + touid);
|
return $('#chat-modal-' + touid);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.modalOpen = function(touid) {
|
module.modalExists = function(touid) {
|
||||||
return $('#chat-modal-' + touid).length !== 0;
|
return $('#chat-modal-' + touid).length !== 0;
|
||||||
}
|
}
|
||||||
module.createModalIfDoesntExist = function(username, touid, callback) {
|
|
||||||
var chatModal = $('#chat-modal-' + touid);
|
|
||||||
|
|
||||||
if(!chatModal.length) {
|
function checkStatus(chatModal, callback) {
|
||||||
var chatModal = $('#chat-modal').clone();
|
socket.emit('api:user.isOnline', chatModal.touid, function(data) {
|
||||||
chatModal.attr('id','chat-modal-' + touid);
|
if(data.online !== chatModal.online) {
|
||||||
var uuid = utils.generateUUID();
|
if(data.online) {
|
||||||
chatModal.attr('UUID', uuid);
|
module.appendChatMessage(chatModal, chatModal.username + ' has come online.\n', data.timestamp);
|
||||||
chatModal.appendTo($('body'));
|
} else {
|
||||||
chatModal.draggable({
|
module.appendChatMessage(chatModal, chatModal.username + ' has gone offline.\n', data.timestamp);
|
||||||
start:function(){
|
|
||||||
module.bringModalToTop(chatModal);
|
|
||||||
}
|
}
|
||||||
});
|
chatModal.online = data.online;
|
||||||
chatModal.find('#chat-with-name').html(username);
|
}
|
||||||
|
if(callback)
|
||||||
|
callback(data.online);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
chatModal.find('.close').on('click', function(e) {
|
function checkOnlineStatus(chatModal) {
|
||||||
chatModal.hide();
|
if(chatModal.intervalId === 0) {
|
||||||
taskbar.discard('chat', uuid);
|
chatModal.intervalId = setInterval(function(){
|
||||||
});
|
checkStatus(chatModal);
|
||||||
|
}, 1000);
|
||||||
chatModal.on('click', function(e) {
|
|
||||||
module.bringModalToTop(chatModal);
|
|
||||||
});
|
|
||||||
|
|
||||||
addSendHandler(chatModal, touid);
|
|
||||||
|
|
||||||
getChatMessages(chatModal, touid, callback);
|
|
||||||
|
|
||||||
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with '+username});
|
|
||||||
return chatModal;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(callback)
|
module.createModal = function(username, touid, callback) {
|
||||||
callback(false, chatModal);
|
|
||||||
|
|
||||||
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with '+username});
|
var chatModal = $('#chat-modal').clone(),
|
||||||
|
uuid = utils.generateUUID();
|
||||||
|
|
||||||
|
chatModal.intervalId = 0;
|
||||||
|
chatModal.touid = touid;
|
||||||
|
chatModal.username = username;
|
||||||
|
|
||||||
|
chatModal.attr('id', 'chat-modal-' + touid);
|
||||||
|
chatModal.attr('UUID', uuid);
|
||||||
|
chatModal.appendTo($('body'));
|
||||||
|
chatModal.draggable({
|
||||||
|
start:function() {
|
||||||
|
module.bringModalToTop(chatModal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
chatModal.find('#chat-with-name').html(username);
|
||||||
|
|
||||||
|
chatModal.find('.close').on('click', function(e) {
|
||||||
|
clearInterval(chatModal.intervalId);
|
||||||
|
chatModal.intervalId = 0;
|
||||||
|
chatModal.hide();
|
||||||
|
taskbar.discard('chat', uuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
chatModal.on('click', function(e) {
|
||||||
|
module.bringModalToTop(chatModal);
|
||||||
|
});
|
||||||
|
|
||||||
|
addSendHandler(chatModal);
|
||||||
|
|
||||||
|
checkStatus(chatModal, function(online) {
|
||||||
|
chatModal.online = online;
|
||||||
|
getChatMessages(chatModal, function() {
|
||||||
|
checkOnlineStatus(chatModal);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with ' + username});
|
||||||
return chatModal;
|
return chatModal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,45 +92,46 @@ define(['taskbar'], function(taskbar) {
|
|||||||
var chatModal = $('div[UUID="'+uuid+'"]');
|
var chatModal = $('div[UUID="'+uuid+'"]');
|
||||||
chatModal.show();
|
chatModal.show();
|
||||||
module.bringModalToTop(chatModal);
|
module.bringModalToTop(chatModal);
|
||||||
|
checkOnlineStatus(chatModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.minimize = function(uuid) {
|
module.minimize = function(uuid) {
|
||||||
var chatModal = $('div[UUID="'+uuid+'"]');
|
var chatModal = $('div[UUID="'+uuid+'"]');
|
||||||
chatModal.hide();
|
chatModal.hide();
|
||||||
taskbar.minimize('chat', uuid);
|
taskbar.minimize('chat', uuid);
|
||||||
|
clearInterval(chatModal.intervalId);
|
||||||
|
chatModal.intervalId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChatMessages(chatModal, touid, callback) {
|
function getChatMessages(chatModal, callback) {
|
||||||
socket.emit('getChatMessages', {touid:touid}, function(messages) {
|
socket.emit('getChatMessages', {touid:chatModal.touid}, function(messages) {
|
||||||
for(var i = 0; i<messages.length; ++i) {
|
for(var i = 0; i<messages.length; ++i) {
|
||||||
module.appendChatMessage(chatModal, messages[i].content, messages[i].timestamp);
|
module.appendChatMessage(chatModal, messages[i].content, messages[i].timestamp);
|
||||||
}
|
}
|
||||||
|
callback();
|
||||||
if(callback)
|
|
||||||
callback(true, chatModal);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSendHandler(chatModal, touid) {
|
function addSendHandler(chatModal) {
|
||||||
chatModal.find('#chat-message-input').off('keypress');
|
chatModal.find('#chat-message-input').off('keypress');
|
||||||
chatModal.find('#chat-message-input').on('keypress', function(e) {
|
chatModal.find('#chat-message-input').on('keypress', function(e) {
|
||||||
if(e.which === 13) {
|
if(e.which === 13) {
|
||||||
sendMessage(chatModal, touid);
|
sendMessage(chatModal);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
chatModal.find('#chat-message-send-btn').off('click');
|
chatModal.find('#chat-message-send-btn').off('click');
|
||||||
chatModal.find('#chat-message-send-btn').on('click', function(e){
|
chatModal.find('#chat-message-send-btn').on('click', function(e){
|
||||||
sendMessage(chatModal, touid);
|
sendMessage(chatModal);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMessage(chatModal, touid) {
|
function sendMessage(chatModal) {
|
||||||
var msg = app.strip_tags(chatModal.find('#chat-message-input').val());
|
var msg = app.strip_tags(chatModal.find('#chat-message-input').val());
|
||||||
if(msg.length) {
|
if(msg.length) {
|
||||||
msg = msg +'\n';
|
msg = msg +'\n';
|
||||||
socket.emit('sendChatMessage', { touid:touid, message:msg});
|
socket.emit('sendChatMessage', { touid:chatModal.touid, message:msg});
|
||||||
chatModal.find('#chat-message-input').val('');
|
chatModal.find('#chat-message-input').val('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ define(['taskbar'], function(taskbar) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function createImageLabel(img, postImages) {
|
function createImageLabel(img, postImages) {
|
||||||
var imageLabel = $('<div class="label label-primary"><span>'+ img.name +'</span></div>');
|
var imageLabel = $('<span class="label label-primary">' + img.name +'</span>');
|
||||||
var closeButton = $('<button class="close">×</button>');
|
var closeButton = $('<button class="close">×</button>');
|
||||||
|
|
||||||
closeButton.on('click', function(e) {
|
closeButton.on('click', function(e) {
|
||||||
@@ -152,7 +152,7 @@ define(['taskbar'], function(taskbar) {
|
|||||||
pid: threadData.pid,
|
pid: threadData.pid,
|
||||||
title: threadData.title || '',
|
title: threadData.title || '',
|
||||||
body: threadData.body || '',
|
body: threadData.body || '',
|
||||||
images: []
|
images: threadData.uploadedImages
|
||||||
};
|
};
|
||||||
composer.load(uuid);
|
composer.load(uuid);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
<span class="label label-danger">banned</span>
|
<span class="label label-danger">banned</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="user-actions">
|
<div id="user-actions">
|
||||||
<a id="follow-btn" href="#" class="btn hide">Follow</a>
|
<a id="follow-btn" href="#" class="btn btn-default">Follow</a>
|
||||||
<a id="unfollow-btn" href="#" class="btn hide">Unfollow</a>
|
<a id="unfollow-btn" href="#" class="btn btn-default">Unfollow</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<span class='formatted-number'>{following.postcount}</span>
|
<span class='formatted-number'>{following.postcount}</span>
|
||||||
<i class='icon-pencil'></i>
|
<i class='icon-pencil'></i>
|
||||||
</div>
|
</div>
|
||||||
<a id="unfollow-btn" href="#" class="btn unfollow-btn" followingUid="{following.uid}" data-username="{following.username}">Unfollow</a>
|
<a id="unfollow-btn" href="#" class="btn btn-default unfollow-btn" followingUid="{following.uid}" data-username="{following.username}">Unfollow</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- END following -->
|
<!-- END following -->
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
</div><!-- /.modal-dialog -->
|
</div><!-- /.modal-dialog -->
|
||||||
</div><!-- /.modal -->
|
</div><!-- /.modal -->
|
||||||
|
|
||||||
<div id="chat-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Chat" aria-hidden="true">
|
<div id="chat-modal" class="modal" tabindex="-1" role="dialog" aria-labelledby="Chat" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
|||||||
@@ -53,29 +53,35 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="/users">Users</a>
|
<a href="/users">Users</a>
|
||||||
</li>
|
</li>
|
||||||
|
<!--Enable when /search form is completed <li class="visible-xs">
|
||||||
|
<a href="/search">Search</a>
|
||||||
|
</li>-->
|
||||||
<li>
|
<li>
|
||||||
<a href="/"></a>
|
<a href="/"></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<form id="search-form" class="navbar-form navbar-right hidden-xs" role="search" method="GET" action="">
|
||||||
|
<div class="hide" id="search-fields">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" placeholder="Search" name="query">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-default hide">Search</button>
|
||||||
|
</div>
|
||||||
|
<button id="search-button" type="button" class="btn btn-link nodebb-loggedin"><i class="icon-search"></i></button>
|
||||||
|
</form>
|
||||||
|
|
||||||
<ul id="right-menu" class="nav navbar-nav navbar-right">
|
<ul id="right-menu" class="nav navbar-nav navbar-right">
|
||||||
<li class="notifications dropdown text-center">
|
<li class="notifications dropdown text-center hidden-xs">
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"><i class="icon-circle-blank"></i></a>
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"><i class="icon-circle-blank"></i></a>
|
||||||
<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown">
|
<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown">
|
||||||
<li><a href="#"><i class="icon-refresh icon-spin"></i> Loading Notifications</a></li>
|
<li>
|
||||||
|
<a href="#"><i class="icon-refresh icon-spin"></i> Loading Notifications</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<form id="search-form" class="navbar-form navbar-right" role="search" method="GET" action="">
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control" placeholder="Search" name="query">
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-default hide">Search</button>
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div id="pagination"></div>
|
<div id="pagination"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,17 +1,30 @@
|
|||||||
<h1>Reset Password</h1>
|
<ol class="breadcrumb">
|
||||||
|
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<a href="/" itemprop="url"><span itemprop="title">Home</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<span itemprop="title">Reset Password</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="alert alert-info">
|
||||||
|
Please enter your <strong>email address</strong> and we will send you an email with instructions on how to reset your account.
|
||||||
|
</div>
|
||||||
<div class="well">
|
<div class="well">
|
||||||
<div class="alert alert-success" id="success" style="display:none">
|
<div class="alert alert-success" id="success" style="display:none">
|
||||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||||
<strong>Password Reset Sent</strong>
|
<strong>Password Reset Sent</strong>
|
||||||
<p></p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="alert" id="error" style="display:none">
|
<div class="alert alert-danger" id="error" style="display:none">
|
||||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||||
<strong>Invalid Email!</strong>
|
<strong>Invalid Email / Email does not exist!</strong>
|
||||||
<p></p>
|
|
||||||
</div>
|
</div>
|
||||||
<label for="email">Email Address</label><input type="text" placeholder="Enter Email Address" id="email" /><br />
|
<form onsubmit="return false;">
|
||||||
<button class="btn btn-primary" id="reset" type="submit">Reset Password</button>
|
<input type="text" class="form-control input-block input-lg" placeholder="Enter Email Address" id="email" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<button class="btn btn-primary btn-block btn-lg" id="reset" type="submit">Reset Password</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="{relative_path}/src/forum/reset.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/forum/reset.js"></script>
|
||||||
@@ -1,23 +1,37 @@
|
|||||||
<h1>Reset Password</h1>
|
<ol class="breadcrumb">
|
||||||
|
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<a href="/" itemprop="url"><span itemprop="title">Home</span></a>
|
||||||
|
</li>
|
||||||
|
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<a href="/reset" itemprop="url"><span itemprop="title">Reset Password</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<span itemprop="title">Update Password</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
<div class="well">
|
<div class="well">
|
||||||
<div class="alert alert-success" id="success" style="display:none">
|
<div class="alert alert-success" id="success" style="display:none">
|
||||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||||
<strong>Password Changed</strong>
|
<strong>Password Changed</strong>
|
||||||
<p>Password successfully reset, please <a href="/login">log in again</a>.</p>
|
<p>Password successfully reset, please <a href="/login">log in again</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="alert" id="notice" style="display:none">
|
<div class="alert alert-warning" id="notice" style="display:none">
|
||||||
<strong></strong>
|
<strong></strong>
|
||||||
<p></p>
|
<p></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="alert alert-error" id="error" style="display:none">
|
<div class="alert alert-danger" id="error" style="display:none">
|
||||||
<strong>Incorrect Reset Code</strong>
|
<strong>Incorrect Reset Code</strong>
|
||||||
<p>The reset code received was incorrect. Please try again, or <a href="/reset">request a new reset code</a></p>
|
<p>The reset code received was incorrect. Please try again, or <a href="/reset">request a new reset code</a></p>
|
||||||
</div>
|
</div>
|
||||||
<div id="reset-form">
|
<form onsubmit="return false;" id="reset-form">
|
||||||
<label for="password">New Password</label><input type="password" placeholder="A new password" id="password" /><br />
|
<label for="password">New Password</label>
|
||||||
<label for="repeat">... and again</label><input type="password" placeholder="The same password" id="repeat" /><br />
|
<input class="form-control input-lg" type="password" placeholder="A new password" id="password" /><br />
|
||||||
<button class="btn btn-primary" id="reset" type="submit" disabled>Reset Password</button>
|
<label for="repeat">Confirm Password</label>
|
||||||
</div>
|
<input class="form-control input-lg" type="password" placeholder="The same password" id="repeat" /><br />
|
||||||
|
<button class="btn btn-primary btn-lg btn-block" id="reset" type="submit" disabled>Reset Password</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" template-variable="reset_code" value="{reset_code}" />
|
<input type="hidden" template-variable="reset_code" value="{reset_code}" />
|
||||||
|
|
||||||
|
|||||||
@@ -170,23 +170,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="move_thread_modal" class="modal hide fade">
|
|
||||||
<div class="modal-header">
|
<div id="move_thread_modal" class="modal" tabindex="-1" role="dialog" aria-labelledby="Chat" aria-hidden="true">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<div class="modal-dialog">
|
||||||
<h3>Move Thread</h3>
|
<div class="modal-content">
|
||||||
</div>
|
<div class="modal-header">
|
||||||
<div class="modal-body">
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<p id="categories-loading"><i class="icon-spin icon-refresh"></i> Loading Categories</p>
|
<h3>Move Thread</h3>
|
||||||
<ul class="category-list"></ul>
|
</div>
|
||||||
<div id="move-confirm" style="display: none;">
|
<div class="modal-body">
|
||||||
<hr />
|
<p id="categories-loading"><i class="icon-spin icon-refresh"></i> Loading Categories</p>
|
||||||
<div class="alert">This topic will be moved to the category <strong><span id="confirm-category-name"></span></strong></div>
|
<ul class="category-list"></ul>
|
||||||
|
<div id="move-confirm" style="display: none;">
|
||||||
|
<hr />
|
||||||
|
<div class="alert">This topic will be moved to the category <strong><span id="confirm-category-name"></span></strong></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal" id="move_thread_cancel">Close</a>
|
||||||
|
<button type="button" class="btn btn-primary" id="move_thread_commit" disabled>Move</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn" data-dismiss="modal" id="move_thread_cancel">Close</a>
|
|
||||||
<button type="button" class="btn btn-primary" id="move_thread_commit" disabled>Move</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" template-variable="expose_tools" value="{expose_tools}" />
|
<input type="hidden" template-variable="expose_tools" value="{expose_tools}" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div>
|
<div>
|
||||||
|
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li class='active'><a href='/users-latest'>Latest Users</a></li>
|
<li class=''><a href='/users-latest'>Latest Users</a></li>
|
||||||
<li class=''><a href='/users-sort-posts'>Top Posters</a></li>
|
<li class=''><a href='/users-sort-posts'>Top Posters</a></li>
|
||||||
<li class=''><a href='/users-sort-reputation'>Most Reputation</a></li>
|
<li class=''><a href='/users-sort-reputation'>Most Reputation</a></li>
|
||||||
<li class=''><a href='/users-search'>Search</a></li>
|
<li class=''><a href='/users-search'>Search</a></li>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
var category_name = categoryData.name,
|
var category_name = categoryData.name,
|
||||||
category_slug = categoryData.slug,
|
category_slug = categoryData.slug,
|
||||||
|
disabled = categoryData.disabled || '0',
|
||||||
category_description = categoryData.description;
|
category_description = categoryData.description;
|
||||||
|
|
||||||
function getTopicIds(next) {
|
function getTopicIds(next) {
|
||||||
@@ -32,6 +33,7 @@ var RDB = require('./redis.js'),
|
|||||||
var categoryData = {
|
var categoryData = {
|
||||||
'category_name' : category_name,
|
'category_name' : category_name,
|
||||||
'category_description': category_description,
|
'category_description': category_description,
|
||||||
|
'disabled': disabled,
|
||||||
'show_sidebar' : 'show',
|
'show_sidebar' : 'show',
|
||||||
'show_topic_button': 'inline-block',
|
'show_topic_button': 'inline-block',
|
||||||
'no_topics_message': 'hidden',
|
'no_topics_message': 'hidden',
|
||||||
|
|||||||
@@ -75,8 +75,7 @@ var async = require('async'),
|
|||||||
server_conf = config,
|
server_conf = config,
|
||||||
client_conf = {
|
client_conf = {
|
||||||
socket: {
|
socket: {
|
||||||
address: protocol + '//' + host,
|
address: protocol + '//' + host + (config.use_port ? ':' + config.port : '')
|
||||||
port: config.port
|
|
||||||
},
|
},
|
||||||
api_url: protocol + '//' + host + (config.use_port ? ':' + config.port : '') + relative_path + '/api/',
|
api_url: protocol + '//' + host + (config.use_port ? ':' + config.port : '') + relative_path + '/api/',
|
||||||
relative_path: relative_path
|
relative_path: relative_path
|
||||||
|
|||||||
@@ -18,17 +18,19 @@ var fs = require('fs'),
|
|||||||
RDB.smembers('plugins:active', next);
|
RDB.smembers('plugins:active', next);
|
||||||
},
|
},
|
||||||
function(plugins, next) {
|
function(plugins, next) {
|
||||||
async.each(plugins, function(plugin) {
|
if (plugins && Array.isArray(plugins) && plugins.length > 0) {
|
||||||
// TODO: Update this check to also check node_modules
|
async.each(plugins, function(plugin) {
|
||||||
var pluginPath = path.join(__dirname, '../plugins/', plugin),
|
// TODO: Update this check to also check node_modules
|
||||||
modulePath = path.join(__dirname, '../node_modules/', plugin);
|
var pluginPath = path.join(__dirname, '../plugins/', plugin),
|
||||||
if (fs.existsSync(pluginPath)) _self.loadPlugin(pluginPath, next);
|
modulePath = path.join(__dirname, '../node_modules/', plugin);
|
||||||
else if (fs.existsSync(modulePath)) _self.loadPlugin(modulePath, next);
|
if (fs.existsSync(pluginPath)) _self.loadPlugin(pluginPath, next);
|
||||||
else {
|
else if (fs.existsSync(modulePath)) _self.loadPlugin(modulePath, next);
|
||||||
if (global.env === 'development') winston.info('[plugins] Plugin \'' + plugin + '\' not found');
|
else {
|
||||||
next(); // Ignore this plugin silently
|
if (global.env === 'development') winston.info('[plugins] Plugin \'' + plugin + '\' not found');
|
||||||
}
|
next(); // Ignore this plugin silently
|
||||||
}, next);
|
}
|
||||||
|
}, next);
|
||||||
|
} else next();
|
||||||
}
|
}
|
||||||
], function(err) {
|
], function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ var RDB = require('./redis.js'),
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
PostTools.edit = function(uid, pid, title, content) {
|
PostTools.edit = function(uid, pid, title, content, images) {
|
||||||
var success = function() {
|
var success = function() {
|
||||||
posts.setPostField(pid, 'content', content);
|
posts.setPostField(pid, 'content', content);
|
||||||
posts.setPostField(pid, 'edited', Date.now());
|
posts.setPostField(pid, 'edited', Date.now());
|
||||||
@@ -66,6 +66,11 @@ var RDB = require('./redis.js'),
|
|||||||
});
|
});
|
||||||
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
|
function(next) {
|
||||||
|
posts.uploadPostImages(pid, images, function(err, uploadedImages) {
|
||||||
|
next(err, uploadedImages);
|
||||||
|
});
|
||||||
|
},
|
||||||
function(next) {
|
function(next) {
|
||||||
posts.getPostField(pid, 'tid', function(tid) {
|
posts.getPostField(pid, 'tid', function(tid) {
|
||||||
PostTools.isMain(pid, tid, function(isMainPost) {
|
PostTools.isMain(pid, tid, function(isMainPost) {
|
||||||
@@ -76,7 +81,7 @@ var RDB = require('./redis.js'),
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
next(null, tid);
|
next(null, {tid:tid, isMainPost:isMainPost});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -84,10 +89,12 @@ var RDB = require('./redis.js'),
|
|||||||
PostTools.toHTML(content, next);
|
PostTools.toHTML(content, next);
|
||||||
}
|
}
|
||||||
], function(err, results) {
|
], function(err, results) {
|
||||||
io.sockets.in('topic_' + results[0]).emit('event:post_edited', {
|
io.sockets.in('topic_' + results[1].tid).emit('event:post_edited', {
|
||||||
pid: pid,
|
pid: pid,
|
||||||
title: title,
|
title: title,
|
||||||
content: results[1]
|
isMainPost: results[1].isMainPost,
|
||||||
|
content: results[2],
|
||||||
|
uploadedImages:results[0]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -179,6 +186,7 @@ var RDB = require('./redis.js'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
PostTools.toHTML = function(raw, callback) {
|
PostTools.toHTML = function(raw, callback) {
|
||||||
|
raw = raw || '';
|
||||||
plugins.fireHook('filter:post.parse', raw, function(parsed) {
|
plugins.fireHook('filter:post.parse', raw, function(parsed) {
|
||||||
var cheerio = require('cheerio');
|
var cheerio = require('cheerio');
|
||||||
|
|
||||||
|
|||||||
42
src/posts.js
42
src/posts.js
@@ -332,7 +332,7 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
async.parallel({
|
async.parallel({
|
||||||
uploadedImages: function(next) {
|
uploadedImages: function(next) {
|
||||||
uploadPostImages(postData, images, function(err, uploadedImages) {
|
Posts.uploadPostImages(postData.pid, images, function(err, uploadedImages) {
|
||||||
if(err) {
|
if(err) {
|
||||||
winston.error('Uploading images failed!', err.stack);
|
winston.error('Uploading images failed!', err.stack);
|
||||||
next(null, []);
|
next(null, []);
|
||||||
@@ -350,7 +350,6 @@ var RDB = require('./redis.js'),
|
|||||||
}
|
}
|
||||||
}, function(err, results) {
|
}, function(err, results) {
|
||||||
postData.uploadedImages = results.uploadedImages;
|
postData.uploadedImages = results.uploadedImages;
|
||||||
Posts.setPostField(pid, 'uploadedImages', JSON.stringify(postData.uploadedImages));
|
|
||||||
postData.content = results.content;
|
postData.content = results.content;
|
||||||
callback(postData);
|
callback(postData);
|
||||||
});
|
});
|
||||||
@@ -366,41 +365,44 @@ var RDB = require('./redis.js'),
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function uploadPostImages(postData, images, callback) {
|
Posts.uploadPostImages = function(pid, images, callback) {
|
||||||
var imgur = require('./imgur');
|
var imgur = require('./imgur');
|
||||||
imgur.setClientID(meta.config.imgurClientID);
|
imgur.setClientID(meta.config.imgurClientID);
|
||||||
|
|
||||||
var uploadedImages = [];
|
if(!images)
|
||||||
|
return callback(null, []);
|
||||||
|
|
||||||
|
var uploadedImages = images.filter(function(image) { return !!image.url; });
|
||||||
|
|
||||||
|
function uploadImage(image, next) {
|
||||||
|
if(!image.data)
|
||||||
|
return next(null);
|
||||||
|
|
||||||
function uploadImage(image, callback) {
|
|
||||||
imgur.upload(image.data, 'base64', function(err, data) {
|
imgur.upload(image.data, 'base64', function(err, data) {
|
||||||
if(err) {
|
if(err) {
|
||||||
callback(err);
|
next(err);
|
||||||
} else {
|
} else {
|
||||||
if(data.success) {
|
if(data.success) {
|
||||||
var img= {url:data.data.link, name:image.name};
|
var img= {url:data.data.link, name:image.name};
|
||||||
uploadedImages.push(img);
|
uploadedImages.push(img);
|
||||||
callback(null);
|
next(null);
|
||||||
} else {
|
} else {
|
||||||
winston.error('Can\'t upload image, did you set imgurClientID?');
|
winston.error('Can\'t upload image, did you set imgurClientID?');
|
||||||
callback(data);
|
next(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!images) {
|
async.each(images, uploadImage, function(err) {
|
||||||
callback(null, uploadedImages);
|
if(!err) {
|
||||||
} else {
|
Posts.setPostField(pid, 'uploadedImages', JSON.stringify(uploadedImages));
|
||||||
async.each(images, uploadImage, function(err) {
|
callback(null, uploadedImages);
|
||||||
if(!err) {
|
} else {
|
||||||
callback(null, uploadedImages);
|
console.log(err);
|
||||||
} else {
|
callback(err, null);
|
||||||
console.log(err);
|
}
|
||||||
callback(err, null);
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Posts.getPostsByUid = function(uid, start, end, callback) {
|
Posts.getPostsByUid = function(uid, start, end, callback) {
|
||||||
|
|||||||
46
src/user.js
46
src/user.js
@@ -7,7 +7,8 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
bcrypt = require('bcrypt'),
|
bcrypt = require('bcrypt'),
|
||||||
notifications = require('./notifications.js'),
|
notifications = require('./notifications.js'),
|
||||||
topics = require('./topics.js'),
|
topics = require('./topics.js'),
|
||||||
async = require('async');
|
async = require('async'),
|
||||||
|
userSearch = require('reds').createSearch('nodebbusersearch');
|
||||||
|
|
||||||
(function(User) {
|
(function(User) {
|
||||||
User.create = function(username, password, email, callback) {
|
User.create = function(username, password, email, callback) {
|
||||||
@@ -90,6 +91,8 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
RDB.zadd('users:postcount', 0, uid);
|
RDB.zadd('users:postcount', 0, uid);
|
||||||
RDB.zadd('users:reputation', 0, uid);
|
RDB.zadd('users:reputation', 0, uid);
|
||||||
|
|
||||||
|
userSearch.index(username, uid);
|
||||||
|
|
||||||
io.sockets.emit('user.latest', {userslug: userslug, username: username});
|
io.sockets.emit('user.latest', {userslug: userslug, username: username});
|
||||||
|
|
||||||
if (password !== undefined) {
|
if (password !== undefined) {
|
||||||
@@ -385,25 +388,42 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
User.reIndexAll = function(callback) {
|
||||||
|
User.getUsers('users:joindate', 0, -1, function(err, usersData) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reIndexUser(uid, username) {
|
||||||
|
userSearch.remove(uid, function(){
|
||||||
|
userSearch.index(username, uid);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i=0; i<usersData.length; ++i) {
|
||||||
|
reIndexUser(usersData[i].uid, usersData[i].username);
|
||||||
|
}
|
||||||
|
callback(null, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
User.search = function(username, callback) {
|
User.search = function(username, callback) {
|
||||||
if(!username) {
|
if(!username) {
|
||||||
callback([]);
|
callback([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RDB.keys('username:*'+ username + '*:uid', function(err, keys) {
|
userSearch.query(query = username).type('or').end(function(err, uids) {
|
||||||
if(!err) {
|
if(err) {
|
||||||
if(keys && keys.length) {
|
|
||||||
RDB.mget(keys, function(err, uids) {
|
|
||||||
User.getDataForUsers(uids, function(userdata) {
|
|
||||||
callback(userdata);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callback([]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(uids && uids.length) {
|
||||||
|
User.getDataForUsers(uids, function(userdata) {
|
||||||
|
callback(userdata);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
callback([]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ var express = require('express'),
|
|||||||
|
|
||||||
// Middlewares
|
// Middlewares
|
||||||
app.use(express.favicon(path.join(__dirname, '../', 'public', 'favicon.ico')));
|
app.use(express.favicon(path.join(__dirname, '../', 'public', 'favicon.ico')));
|
||||||
app.use(require('less-middleware')({ src: path.join(__dirname, '../', 'public') }));
|
app.use(require('less-middleware')({ src: path.join(__dirname, '../', 'public'), prefix:nconf.get('relative_path') }));
|
||||||
app.use(nconf.get('relative_path'), express.static(path.join(__dirname, '../', 'public')));
|
app.use(nconf.get('relative_path'), express.static(path.join(__dirname, '../', 'public')));
|
||||||
app.use(express.bodyParser()); // Puts POST vars in request.body
|
app.use(express.bodyParser()); // Puts POST vars in request.body
|
||||||
app.use(express.cookieParser()); // If you want to parse cookies (res.cookies)
|
app.use(express.cookieParser()); // If you want to parse cookies (res.cookies)
|
||||||
@@ -295,6 +295,11 @@ var express = require('express'),
|
|||||||
async.waterfall([
|
async.waterfall([
|
||||||
function(next) {
|
function(next) {
|
||||||
categories.getCategoryById(cid, 0, function(err, categoryData) {
|
categories.getCategoryById(cid, 0, function(err, categoryData) {
|
||||||
|
|
||||||
|
if(categoryData) {
|
||||||
|
if(categoryData.disabled === '1')
|
||||||
|
return next(new Error('Category disabled'), null);
|
||||||
|
}
|
||||||
next(err, categoryData);
|
next(err, categoryData);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -403,10 +408,16 @@ var express = require('express'),
|
|||||||
app.get('/reindex', function(req, res) {
|
app.get('/reindex', function(req, res) {
|
||||||
topics.reIndexAll(function(err) {
|
topics.reIndexAll(function(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
res.json(err);
|
return res.json(err);
|
||||||
} else {
|
|
||||||
res.send('All topics reindexed');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user.reIndexAll(function(err) {
|
||||||
|
if(err) {
|
||||||
|
return res.json(err);
|
||||||
|
} else {
|
||||||
|
res.send('Topics and users reindexed');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
(function(io) {
|
(function(io) {
|
||||||
var users = {},
|
var users = {},
|
||||||
userSockets = {},
|
userSockets = {},
|
||||||
rooms = {},
|
rooms = {};
|
||||||
chats = {};
|
|
||||||
|
|
||||||
global.io = io;
|
global.io = io;
|
||||||
|
|
||||||
@@ -58,13 +57,6 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
|
|
||||||
user.getUserField(uid, 'username', function(err, username) {
|
user.getUserField(uid, 'username', function(err, username) {
|
||||||
socket.emit('event:connect', {status: 1, username:username, uid:uid});
|
socket.emit('event:connect', {status: 1, username:username, uid:uid});
|
||||||
|
|
||||||
if(chats[uid]) {
|
|
||||||
for(var i=0; i<chats[uid].length; ++i) {
|
|
||||||
io.sockets.in(chats[uid][i]).emit('chatMessage', {fromuid:uid, username:username, message: username+' came online\n', timestamp: Date.now()});
|
|
||||||
socket.join(chats[uid][i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -83,18 +75,6 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
delete users[sessionID];
|
delete users[sessionID];
|
||||||
if(uid) {
|
if(uid) {
|
||||||
io.sockets.in('global').emit('api:user.isOnline', isUserOnline(uid));
|
io.sockets.in('global').emit('api:user.isOnline', isUserOnline(uid));
|
||||||
|
|
||||||
user.getUserField(uid, 'username', function(err, username) {
|
|
||||||
|
|
||||||
if(chats[uid] && chats[uid].length) {
|
|
||||||
|
|
||||||
for(var i=0; i<chats[uid].length; ++i) {
|
|
||||||
|
|
||||||
io.sockets.in(chats[uid][i]).emit('chatGoOffline', {uid:uid, username:username, timestamp:Date.now()});
|
|
||||||
socket.leave(chats[uid][i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,8 +250,8 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
socket.emit('api:user.get_online_users', returnData);
|
socket.emit('api:user.get_online_users', returnData);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:user.isOnline', function(uid) {
|
socket.on('api:user.isOnline', function(uid, callback) {
|
||||||
socket.emit('api:user.isOnline', isUserOnline(uid));
|
callback({online:isUserOnline(uid), timestamp:Date.now()});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:user.changePassword', function(data, callback) {
|
socket.on('api:user.changePassword', function(data, callback) {
|
||||||
@@ -364,7 +344,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
socket.emit('event:alert', {
|
socket.emit('event:alert', {
|
||||||
title: 'Thank you for posting',
|
title: 'Thank you for posting',
|
||||||
message: 'You have successfully posted. Click here to view your post.',
|
message: 'You have successfully posted. Click here to view your post.',
|
||||||
type: 'warning',
|
type: 'success',
|
||||||
timeout: 2000
|
timeout: 2000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -417,7 +397,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
socket.emit('event:alert', {
|
socket.emit('event:alert', {
|
||||||
title: 'Reply Successful',
|
title: 'Reply Successful',
|
||||||
message: 'You have successfully replied. Click here to view your reply.',
|
message: 'You have successfully replied. Click here to view your reply.',
|
||||||
type: 'warning',
|
type: 'success',
|
||||||
timeout: 2000
|
timeout: 2000
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -497,7 +477,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
posts.emitContentTooShortAlert(socket);
|
posts.emitContentTooShortAlert(socket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
postTools.edit(uid, data.pid, data.title, data.content);
|
postTools.edit(uid, data.pid, data.title, data.content, data.images);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:posts.delete', function(data) {
|
socket.on('api:posts.delete', function(data) {
|
||||||
@@ -549,15 +529,12 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
|
|
||||||
var msg = utils.strip_tags(data.message);
|
var msg = utils.strip_tags(data.message);
|
||||||
|
|
||||||
var uids = [uid, touid].sort();
|
|
||||||
var chatroom = 'chatroom_'+uids[0]+'_'+uids[1];
|
|
||||||
|
|
||||||
user.getUserField(uid, 'username', function(err, username) {
|
user.getUserField(uid, 'username', function(err, username) {
|
||||||
var finalMessage = username + ': ' + msg,
|
var finalMessage = username + ' : ' + msg,
|
||||||
notifText = 'New message from <strong>' + username + '</strong>';
|
notifText = 'New message from <strong>' + username + '</strong>';
|
||||||
|
|
||||||
if(!isUserOnline(touid)) {
|
if(!isUserOnline(touid)) {
|
||||||
notifications.create(notifText, 5, '#', 'notification_' + uid + '_' + touid, function(nid) {
|
notifications.create(notifText, 5, 'javascript:app.openChat(''+username+'', '+uid+');', 'notification_' + uid + '_' + touid, function(nid) {
|
||||||
notifications.push(nid, [touid], function(success) {
|
notifications.push(nid, [touid], function(success) {
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -571,13 +548,8 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
numSockets = userSockets[touid].length;
|
numSockets = userSockets[touid].length;
|
||||||
|
|
||||||
for(var x=0; x<numSockets; ++x) {
|
for(var x=0; x<numSockets; ++x) {
|
||||||
userSockets[touid][x].join(chatroom);
|
|
||||||
userSockets[touid][x].emit('chatMessage', {fromuid:uid, username:username, message: finalMessage, timestamp: Date.now()});
|
userSockets[touid][x].emit('chatMessage', {fromuid:uid, username:username, message: finalMessage, timestamp: Date.now()});
|
||||||
}
|
}
|
||||||
|
|
||||||
chats[touid] = chats[touid] || [];
|
|
||||||
if(chats[touid].indexOf(chatroom) === -1)
|
|
||||||
chats[touid].push(chatroom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(userSockets[uid]) {
|
if(userSockets[uid]) {
|
||||||
@@ -585,13 +557,8 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
numSockets = userSockets[uid].length;
|
numSockets = userSockets[uid].length;
|
||||||
|
|
||||||
for(var x=0; x<numSockets; ++x) {
|
for(var x=0; x<numSockets; ++x) {
|
||||||
userSockets[uid][x].join(chatroom);
|
|
||||||
userSockets[uid][x].emit('chatMessage', {fromuid:touid, username:username, message:'You : ' + msg, timestamp: Date.now()});
|
userSockets[uid][x].emit('chatMessage', {fromuid:touid, username:username, message:'You : ' + msg, timestamp: Date.now()});
|
||||||
}
|
}
|
||||||
|
|
||||||
chats[uid] = chats[uid] || [];
|
|
||||||
if(chats[uid].indexOf(chatroom) === -1)
|
|
||||||
chats[uid].push(chatroom);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -617,7 +584,6 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
if (uid > 0) {
|
if (uid > 0) {
|
||||||
if (parseInt(data.tid) > 0) {
|
if (parseInt(data.tid) > 0) {
|
||||||
topics.getTopicData(data.tid, function(topicData) {
|
topics.getTopicData(data.tid, function(topicData) {
|
||||||
|
|
||||||
if (data.body)
|
if (data.body)
|
||||||
topicData.body = data.body;
|
topicData.body = data.body;
|
||||||
|
|
||||||
@@ -640,9 +606,17 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (parseInt(data.pid) > 0) {
|
} else if (parseInt(data.pid) > 0) {
|
||||||
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
function(next) {
|
function(next) {
|
||||||
posts.getPostField(data.pid, 'content', function(raw) {
|
posts.getPostFields(data.pid, ['content', 'uploadedImages'], function(raw) {
|
||||||
|
try {
|
||||||
|
raw.uploadedImages = JSON.parse(raw.uploadedImages);
|
||||||
|
} catch(e) {
|
||||||
|
winston.err(e);
|
||||||
|
raw.uploadedImages = [];
|
||||||
|
}
|
||||||
|
|
||||||
next(null, raw);
|
next(null, raw);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -655,7 +629,8 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
socket.emit('api:composer.push', {
|
socket.emit('api:composer.push', {
|
||||||
title: results[1],
|
title: results[1],
|
||||||
pid: data.pid,
|
pid: data.pid,
|
||||||
body: results[0]
|
body: results[0].content,
|
||||||
|
uploadedImages: results[0].uploadedImages
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user