fixed conflicts

v1.18.x
Baris Usakli 11 years ago
commit 6e16cb4b30

3
.gitignore vendored

@ -16,3 +16,6 @@ provision.sh
*.komodoproject
feeds/recent.rss
# winston?
error.log

@ -25,6 +25,7 @@
var fs = require('fs'),
async = require('async'),
semver = require('semver'),
winston = require('winston'),
pkg = require('./package.json'),
path = require('path'),
@ -48,6 +49,12 @@
winston.error(err.stack);
};
require('child_process').exec('/usr/bin/which convert', function(err, stdout, stderr) {
if(err || !stdout) {
winston.warn('Couldn\'t find convert. Did you install imagemagick?');
}
});
// Log GNU copyright info along with server info
winston.info('NodeBB v' + pkg.version + ' Copyright (C) 2013 DesignCreatePlay Inc.');
winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
@ -73,6 +80,10 @@
winston.info('Base Configuration OK.');
}
if (semver.gt(pkg.dependencies['nodebb-theme-cerulean'], require('./node_modules/nodebb-theme-cerulean/package.json').version)) {
winston.error('nodebb-theme-cerulean is out of date - please run npm install.')
}
require('./src/database').init(function(err) {
meta.configs.init(function () {

@ -15,7 +15,7 @@
"dependencies": {
"socket.io": "~0.9.16",
"redis": "0.8.3",
"mongodb": "1.3.20",
"mongodb": "~1.3.19",
"express": "3.2.0",
"express-namespace": "~0.1.1",
"emailjs": "0.3.4",
@ -43,10 +43,11 @@
"uglify-js": "~2.4.0",
"validator": "~1.5.1",
"nodebb-plugin-mentions": "~0.1.15",
"nodebb-plugin-markdown": "~0.2.0",
"nodebb-plugin-markdown": "~0.2.1",
"nodebb-theme-vanilla": "~0.0.9",
"nodebb-theme-cerulean": "0.0.10",
"cron": "~1.0.1"
"cron": "~1.0.1",
"semver": "~2.2.1"
},
"optionalDependencies": {
"hiredis": "~0.1.15"

@ -36,5 +36,8 @@
"loading": "Lade",
"more_posts": "Mehr Posts",
"move_topic": "Thema verschieben",
"topic_will_be_moved_to": "Dieses Thema wird verschoben nach"
"topic_will_be_moved_to": "Dieses Thema wird verschoben nach",
"reputation": "Reputation",
"posts": "Posts"
}

@ -7,7 +7,7 @@
"location": "Wohnort",
"age": "Alter",
"joined": "Beigetreten",
"profil_views": "Profilaufrufe",
"profile_views": "Profilaufrufe",
"reputation": "Reputation",
"posts": "Posts",
"followers": "Follower",
@ -18,7 +18,7 @@
"change_picture": "Ändere Profilbild",
"edit": "Ändern",
"uploaded_pictures": "Hochgeladene Bilder",
"uploaded_picture": "Hochgeladene Bilder",
"upload_new_picture": "Neues Bild hochladen",
"change_password": "Ändere Passwort",
"confirm_password": "Passwort wiederholen",
@ -29,7 +29,7 @@
"image_spec": "Du solltest nur Dateien die PNG, JPG, oder GIF kleiner als 256kb hochladen.",
"settings": "Einstellungen",
"show_my_email": "Zeige meine E-Mail Adresse an.",
"show_email": "Zeige meine E-Mail Adresse an.",
"has_no_follower": "Dieser User hat noch keine Follower.",
"follows_no_one": "Dieser User folgt noch niemanden."

@ -32,8 +32,11 @@
"favourites.has_no_favourites": "You don't have any favourites, favourite some posts to see them here!",
"posted_by": "posted by",
"loading": "Lade",
"loading": "Loading",
"more_posts": "More Posts",
"move_topic": "Move Topic",
"topic_will_be_moved_to": "This topic will be moved to the category"
"topic_will_be_moved_to": "This topic will be moved to the category",
"reputation": "Reputation",
"posts": "Posts"
}

@ -1,35 +1,35 @@
{
"banned": "Banned",
"offline": "offline",
"email": "email",
"fullname": "full name",
"website": "website",
"location": "location",
"age": "age",
"joined": "joined",
"profil_views": "profil views",
"reputation": "reputation",
"posts": "posts",
"followers": "followers",
"following": "following",
"signature": "signature",
"gravatar": "gravatar",
"birthday": "birthday",
"offline": "Offline",
"email": "Email",
"fullname": "Full Name",
"website": "Website",
"location": "Location",
"age": "Age",
"joined": "Joined",
"profile_views": "Profile views",
"reputation": "Reputation",
"posts": "Posts",
"followers": "Followers",
"following": "Following",
"signature": "Signature",
"gravatar": "Gravatar",
"birthday": "Birthday",
"change_picture": "change picture",
"edit": "edit",
"uploaded_pictures": "uploaded pictures",
"upload_new_picture": "upload new picture",
"change_password": "change password",
"confirm_password": "confirm password",
"password": "password",
"change_picture": "Change Picture",
"edit": "Edit",
"uploaded_picture": "Uploaded Picture",
"upload_new_picture": "Upload New Picture",
"change_password": "Change Password",
"confirm_password": "Confirm Password",
"password": "Password",
"upload_picture": "Upload picture",
"upload_a_picture": "Upload a picture",
"image_spec": "You may only upload PNG, JPG, or GIF files under 256kb.",
"settings": "settings",
"show_my_email": "show my email",
"show_email": "Show My Email",
"has_no_follower": "This user doesn't have any followers :(",
"follows_no_one": "This user isn't following anyone :("

@ -35,5 +35,8 @@
"loading": "Cargando",
"more_posts": "Más posts",
"move_topic": "Mover Tema",
"topic_will_be_moved_to": "Este tema sera movido a la categoría"
"topic_will_be_moved_to": "Este tema sera movido a la categoría",
"reputation": "Reputación",
"posts": "Posts"
}

@ -1,35 +1,35 @@
{
"banned": "Banneado",
"offline": "desconectado",
"email": "email",
"fullname": "nombre completo",
"website": "website",
"location": "ubicación",
"age": "edad",
"joined": "registro",
"profil_views": "visitas en su perfil",
"reputation": "reputación",
"posts": "posts",
"followers": "seguidores",
"following": "siguiendo",
"signature": "firma",
"gravatar": "gravatar",
"birthday": "cumpleaños",
"offline": "Desconectado",
"email": "Email",
"fullname": "Nombre Completo",
"website": "Website",
"location": "Ubicación",
"age": "Edad",
"joined": "Registro",
"profile_views": "Visitas en su perfil",
"reputation": "Reputación",
"posts": "Posts",
"followers": "Seguidores",
"following": "Siguiendo",
"signature": "Firma",
"gravatar": "Gravatar",
"birthday": "Cumpleaños",
"change_picture": "cambiar foto",
"edit": "editar",
"uploaded_pictures": "fotos cargadas",
"upload_new_picture": "cargar nueva foto",
"change_password": "cambiar contraseña",
"confirm_password": "confirmar contraseña",
"password": "contraseña",
"change_picture": "Cambiar Foto",
"edit": "Editar",
"uploaded_picture": "Fotos Cargadas",
"upload_new_picture": "Cargar Nueva Foto",
"change_password": "Cambiar Contraseña",
"confirm_password": "Confirmar Contraseña",
"password": "Contraseña",
"upload_picture": "Cargar foto",
"upload_a_picture": "Cargar una foto",
"image_spec": "Solo puedes usar PNG, JPG, o GIF hasta 256kb.",
"settings": "opciones",
"show_my_email": "mostrar mi email",
"settings": "Opciones",
"show_email": "Mostrar mi Email",
"has_no_follower": "Este miembro no tiene seguidores :(",
"follows_no_one": "Este miembro no sigue a nadie, que pena :("

@ -0,0 +1,14 @@
{
"new_topic_button": "Nouveau Sujet",
"no_topics": "<strong>Il n'y a aucun topic dans cette catégorie.</strong><br />Pourquoi ne pas en créer un?",
"sidebar.recent_replies": "Réponses Récentes",
"sidebar.active_participants": "Participants Actifs",
"sidebar.moderators": "Modérateurs",
"posts": "messages",
"views": "vues",
"posted": "posté",
"browsing": "naviguer",
"no_replies": "Personne n'a répondu",
"replied": "répondu",
"last_edited_by": "dernière édition par"
}

@ -0,0 +1,10 @@
{
"chat.chatting_with": "Chat avec <span id=\"chat-with-name\"></span>",
"chat.placeholder": "taper le message ici, presser entrer pour envoyer",
"chat.send": "Envoyer",
"stats.online": "Online",
"stats.users": "Utilisateurs",
"stats.topics": "Sujets",
"stats.posts": "Message",
"success": "succès"
}

@ -0,0 +1,31 @@
{
"home": "Accueil",
"search": "Recherche",
"buttons.close": "Fermer",
"403.title": "Accès Refusé",
"403.message": "Il semble que vous vous soyez retrouvé sur une page dont vous n'avez pas accès. Peut-être devriez vous <a href='/login'>essayez de vous connecter</a>?",
"404.title": "Introuvable",
"404.message": "Il semble que vous vous soyez retrouvé sur une page qui n'existe pas. Retourner à <a href='/'>l'accueil</a>.",
"500.title": "Erreur Interne.",
"500.message": "Oops! Il semblerait que quelque chose se soit mal passé!",
"register": "S'inscrire",
"login": "Connecter",
"logout": "Déconnection",
"logout.title": "Vous êtes maintenant déconnecté.",
"logout.message": "Vous vous êtes déconnecté de NodeBB avec succès",
"save_changes": "Enregistrer les changements",
"close": "Fermer",
"header.admin": "Admin",
"header.recent": "Récent",
"header.unread": "Non Lu",
"header.users": "Utilisateurs",
"header.search": "Recherche",
"header.profile": "Profile",
"notifications.loading": "Chargement des Notifications",
"chats.loading": "Chargement des Chats"
}

@ -0,0 +1,10 @@
{
"login": "Connexion",
"username": "Identifiant",
"password": "Mot de passe",
"remember_me": "Se souvenir de moi?",
"forgot_password": "Mot de passe oublié?",
"alternative_logins": "Connexion Alternative",
"failed_login_attempt": "Echèc d'authentification, veuillez réessayer.",
"login_successful": "Vous êtes maintenant connecté!"
}

@ -0,0 +1,9 @@
{
"title": "Notifications",
"back_to_home": "retour à NodeBB",
"mark_all_as_read": "Tout marquer comme lu",
"outgoing_link": "Lien Sortant",
"outgoing_link_message": "Vous quitter NodeBB",
"continue_to": "Continuer vers",
"return_to": "Retour vers"
}

@ -0,0 +1,5 @@
{
"day": "Jour",
"week": "Semaine",
"month": "Mois"
}

@ -0,0 +1,16 @@
{
"register": "S'inscrire",
"help.email": "Par défault, votre email est masqué du public.",
"help.username_restrictions": "Un identifiant unique entre %1 et %2 charactères. Les autres utilisateurs peuvent vous citer avec @<span id='yourUsername'>username</span>.",
"help.minimum_password_length": "Votre mot de passe doit avoir au moins %1 charactères.",
"email_address": "Adresse Email",
"email_address_placeholder": "Entrer l'addresse Email",
"username": "Nom d'utilisateur",
"username_placeholder": "Entré le Nom d'utilisateur",
"password": "Mot de passe",
"password_placeholder": "Entrer le Mot de passe",
"confirm_password": "Confirmer le Mot de passe",
"confirm_password_placeholder": "Confirmer le Mot de passe",
"register_now_button": "S'enregistrer maintenant",
"alternative_registration": "Enregistrement Alternatif"
}

@ -0,0 +1,13 @@
{
"reset_password": "Réinitialiser le Mot de passe",
"update_password": "Mettre à jour le Mot de passe",
"password_changed.title": "Mot de passe modifié",
"password_changed.message": "<p>Mot de passe réinitialisé avec succès, veuillez vous <a href=\"/login\">reconnecter</a>.",
"wrong_reset_code.title": "Code de Réinisialisation Incorrect",
"wrong_reset_code.message": "Le Code de Réinisialisation est Incorrect. Veillez réessayer, ou <a href=\"/reset\">demander un nouveau Code de Réinisialisation</a>.",
"new_password": "Nouveau Mot de passe",
"repeat_password": "Confirmer le Mot de passe",
"enter_email": "Veuillez entrer votre <strong>adresse email</strong> et vous recevrez un email avec les instruction pour réinitialiser votre compte.",
"password_reset_sent": "Réinitialisation de Mot de Passe Envoyée",
"invalid_email": "Email Invalide / L'Email n'existe pas!"
}

@ -0,0 +1,42 @@
{
"topic": "Sujet",
"topics": "Sujets",
"no_topics_found": "Aucun sujet trouvé!",
"profile": "Profile",
"posted_by": "Envoyé by",
"chat": "Chat",
"notify_me": "Être notifié des réponses dans ce sujet",
"quote": "Citer",
"reply": "Répondre",
"edit": "Editer",
"delete": "Supprimer",
"banned": "bannir",
"link": "Lien",
"thread_tools.title": "Outils du Fil",
"thread_tools.pin": "Epingler le fil",
"thread_tools.lock": "Verrouiller le fil",
"thread_tools.move": "Déplacer le fil",
"thread_tools.delete": "Supprimer le fil",
"load_categories": "Chargement des Categories",
"disabled_categories_note": "Les Catégories Désactivées sont grisées",
"confirm_move": "Déplacer",
"favourite": "Favoris",
"favourites": "Favoris",
"favourites.not_logged_in.title": "Non Connecté",
"favourites.not_logged_in.message": "Veuillez vous connecter avant de mettre ce message en Favoris",
"favourites.has_no_favourites": "Vous n'avez aucun Favoris, mettre en favoris des messages pour les voir apparaître ici!",
"posted_by": "posté par",
"loading": "Chargement",
"more_posts": "d'autres Messages",
"move_topic": "Déplacer le Sujet",
"topic_will_be_moved_to": "Ce sujet sera déplacé vers la catégorie",
"reputation": "réputation",
"posts": "messages"
}

@ -0,0 +1,5 @@
{
"no_unread_topics": "Aucun sujet non lu.",
"mark_all_read": "Marquer tout comme lu",
"load_more": "Charger la suite"
}

@ -0,0 +1,36 @@
{
"banned": "Banni",
"offline": "Hors-ligne",
"email": "email",
"fullname": "Nom",
"website": "Site Web",
"location": "Emplacement",
"age": "age",
"joined": "adhésion",
"profil_views": "vues du profil",
"reputation": "réputation",
"posts": "messages",
"followers": "suiveurs",
"following": "suivis",
"signature": "signature",
"gravatar": "gravatar",
"birthday": "anniversaire",
"change_picture": "changer d'image",
"edit": "editer",
"uploaded_picture": "images uploadées",
"upload_new_picture": "uploader une nouvelle image",
"change_password": "chnger le mot de passe",
"confirm_password": "confirmer le mot de passe",
"password": "mot de passe",
"upload_picture": "Uploader un image",
"upload_a_picture": "Uploader un image",
"image_spec": "Vous pouvez uploader seulement des fichiers de types PNG, JPG, ou GIF en dessous de 256kb.",
"settings": "paramètres",
"show_my_email": "montrer mon email",
"has_no_follower": "Cet utilisateur n'a aucun suiver :(",
"follows_no_one": "Cet utilisateur ne suit personne :("
}

@ -0,0 +1,9 @@
{
"latest_users": "Derniers Utilisateurs",
"top_posters": "Meilleurs Publieur",
"most_reputation": "Meilleur Réputation",
"online": "En Ligne",
"search": "Rechercher",
"enter_username": "Entrer un nom d'utilisateur pour rechercher",
"load_more": "Charger la suite"
}

@ -31,6 +31,8 @@ var ajaxify = {};
var pagination, paginator_bar;
ajaxify.currentPage = null;
ajaxify.go = function (url, callback, template, quiet) {
// start: the following should be set like so: ajaxify.onchange(function(){}); where the code actually belongs
$(window).off('scroll');
@ -69,6 +71,8 @@ var ajaxify = {};
}
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
ajaxify.currentPage = tpl_url;
if (window.history && window.history.pushState) {
window.history[!quiet ? 'pushState' : 'replaceState']({
url: url
@ -90,7 +94,7 @@ var ajaxify = {};
translator.load(tpl_url);
jQuery('#footer, #content').addClass('ajaxifying');
jQuery('#footer, #content').removeClass('hide').addClass('ajaxifying');
templates.flush();
templates.load_template(function () {
@ -129,6 +133,10 @@ var ajaxify = {};
return false;
};
ajaxify.refresh = function() {
ajaxify.go(ajaxify.currentPage);
};
$('document').ready(function () {
if (!window.history || !window.history.pushState) {
return; // no ajaxification for old browsers
@ -154,7 +162,7 @@ var ajaxify = {};
return;
}
if (!e.ctrlKey && e.which === 1) {
if ((!e.ctrlKey && !e.shiftKey) && e.which === 1) {
if (this.host === window.location.host) {
// Internal link
var url = this.href.replace(rootUrl + '/', '');

@ -1,16 +1,16 @@
var socket,
config,
app = {
'username': null,
'uid': null
"username": null,
"uid": null,
"isFocused": true,
"currentRoom": null
};
(function () {
var showWelcomeMessage = false;
app.loadConfig = function() {
$.ajax({
url: RELATIVE_PATH + '/api/config',
success: function (data) {
@ -135,7 +135,7 @@ var socket,
},
async: false
});
}
};
app.logout = function() {
$.post(RELATIVE_PATH + '/logout', {
@ -143,12 +143,12 @@ var socket,
}, function() {
window.location.href = RELATIVE_PATH + '/';
});
}
};
// takes a string like 1000 and returns 1,000
app.addCommas = function (text) {
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
}
};
// Willingly stolen from: http://phpjs.org/functions/strip_tags/
app.strip_tags = function (input, allowed) {
@ -159,7 +159,7 @@ var socket,
return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
});
}
};
// use unique alert_id to have multiple alerts visible at a time, use the same alert_id to fade out the current instance
// type : error, success, info, warning/notify
@ -222,7 +222,7 @@ var socket,
});
}
}
}
};
app.alertSuccess = function (message, timeout) {
if (!timeout)
@ -234,7 +234,7 @@ var socket,
type: 'success',
timeout: timeout
});
}
};
app.alertError = function (message, timeout) {
if (!timeout)
@ -246,9 +246,8 @@ var socket,
type: 'danger',
timeout: timeout
});
}
};
app.currentRoom = null;
app.enterRoom = function (room) {
if (socket) {
if (app.currentRoom === room) {
@ -272,7 +271,7 @@ var socket,
});
socket.emit('api:user.get_online_users', uids);
}
};
function highlightNavigationLink() {
var path = window.location.pathname,
@ -291,7 +290,7 @@ var socket,
}
});
}
}
};
app.createUserTooltips = function() {
$('img[title].teaser-pic,img[title].user-img').each(function() {
@ -300,13 +299,13 @@ var socket,
title: $(this).attr('title')
});
});
}
};
app.makeNumbersHumanReadable = function(elements) {
elements.each(function() {
$(this).html(utils.makeNumberHumanReadable($(this).attr('title')));
});
}
};
app.processPage = function () {
app.populateOnlineUsers();
@ -323,7 +322,7 @@ var socket,
setTimeout(function () {
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
}, 100);
}
};
app.showLoginMessage = function () {
function showAlert() {
@ -343,13 +342,13 @@ var socket,
showAlert();
}
}
}
};
app.addCommasToNumbers = function () {
$('.formatted-number').each(function (index, element) {
$(element).html(app.addCommas($(element).html()));
});
}
};
app.openChat = function (username, touid) {
if (username === app.username) {
@ -384,7 +383,7 @@ var socket,
chat.load(chatModal.attr('UUID'));
chat.center(chatModal);
});
}
};
app.scrollToTop = function () {
$('body,html').animate({
@ -442,6 +441,14 @@ var socket,
input.val('');
return false;
});
$(window).blur(function(){
app.isFocused = false;
});
$(window).focus(function(){
app.isFocused = true;
});
});
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;

@ -84,7 +84,9 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
$('#uploadPictureBtn').on('click', function() {
$('#change-picture-modal').modal('hide');
uploader.open(config.relative_path + '/user/uploadpicture', function(imageUrlOnServer) {
uploader.open(RELATIVE_PATH + '/user/uploadpicture', function(imageUrlOnServer) {
imageUrlOnServer = imageUrlOnServer + '?' + new Date().getTime();
$('#user-current-picture').attr('src', imageUrlOnServer);
$('#user-uploaded-picture').attr('src', imageUrlOnServer);

@ -1,4 +1,4 @@
define(function() {
define(['uploader'], function(uploader) {
var Categories = {};
Categories.init = function() {
@ -82,7 +82,8 @@ define(function() {
description: $('#inputDescription').val(),
icon: $('#new-category-modal i').val(),
bgColor: '#0059b2',
color: '#fff'
color: '#fff',
order: $('.admin-categories #entry-container').children().length + 1
};
socket.emit('api:admin.categories.create', category, function(err, data) {
@ -147,7 +148,6 @@ define(function() {
var btn = $(this);
var categoryRow = btn.parents('li');
var cid = categoryRow.attr('data-cid');
console.log(this.getAttribute('data-disabled'));
var disabled = this.getAttribute('data-disabled') === '0' ? '1' : '0';
categoryRow.remove();
@ -179,6 +179,31 @@ define(function() {
var cid = $(this).parents('li[data-cid]').attr('data-cid');
Categories.launchPermissionsModal(cid);
});
$('.upload-button').on('click', function() {
var inputEl = this;
uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', function(imageUrlOnServer) {
inputEl.value = imageUrlOnServer;
$(inputEl).parents('li[data-cid]').find('.preview-box').css('background', 'url(' + imageUrlOnServer + '?' + new Date().getTime() + ')');
modified(inputEl);
});
});
$('.admin-categories').delegate('.delete-image', 'click', function() {
var parent = $(this).parents('li[data-cid]'),
inputEl = parent.find('.upload-button'),
preview = parent.find('.preview-box'),
bgColor = parent.find('.category_bgColor').val();
inputEl.value = '';
modified(inputEl);
preview.css('background', bgColor);
$(this).hide();
});
});
};

@ -76,7 +76,7 @@ define(['uploader'], function(uploader) {
$('#uploadLogoBtn').on('click', function() {
uploader.open(config.relative_path + '/admin/uploadlogo', function(image) {
uploader.open(RELATIVE_PATH + '/admin/uploadlogo', function(image) {
$('#logoUrl').val(image);
});

@ -83,36 +83,39 @@ define(function () {
Category.onNewTopic = function(data) {
var html = templates.prepare(templates['category'].blocks['topics']).parse({
topics: [data]
}),
topic = $(html),
container = $('#topics-container'),
topics = $('#topics-container').children('.category-item'),
numTopics = topics.length;
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
jQuery('#category-no-topics').remove();
if (numTopics > 0) {
for (var x = 0; x < numTopics; x++) {
if ($(topics[x]).find('.fa-thumb-tack').length) {
if(x === numTopics - 1) {
topic.insertAfter(topics[x]);
});
translator.translate(html, function(translatedHTML) {
var topic = $(translatedHTML),
container = $('#topics-container'),
topics = $('#topics-container').children('.category-item'),
numTopics = topics.length;
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
jQuery('#category-no-topics').remove();
if (numTopics > 0) {
for (var x = 0; x < numTopics; x++) {
if ($(topics[x]).find('.fa-thumb-tack').length) {
if(x === numTopics - 1) {
topic.insertAfter(topics[x]);
}
continue;
}
continue;
topic.insertBefore(topics[x]);
break;
}
topic.insertBefore(topics[x]);
break;
} else {
container.append(topic);
}
} else {
container.append(topic);
}
topic.hide().fadeIn('slow');
socket.emit('api:categories.getRecentReplies', templates.get('category_id'));
topic.hide().fadeIn('slow');
socket.emit('api:categories.getRecentReplies', templates.get('category_id'));
addActiveUser(data);
addActiveUser(data);
$('#topics-container span.timeago').timeago();
$('#topics-container span.timeago').timeago();
});
}
function addActiveUser(data) {
@ -131,20 +134,22 @@ define(function () {
}
Category.onTopicsLoaded = function(topics) {
var html = templates.prepare(templates['category'].blocks['topics']).parse({
topics: topics
}),
container = $('#topics-container');
});
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container');
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
jQuery('#category-no-topics').remove();
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
jQuery('#category-no-topics').remove();
html = $(html);
container.append(html);
html = $(translatedHTML);
container.append(html);
$('#topics-container span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
$('#topics-container span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
});
}
Category.loadMoreTopics = function(cid) {

@ -67,6 +67,7 @@
notifTrigger = notifContainer.querySelector('a'),
notifList = document.getElementById('notif-list'),
notifIcon = $('.notifications a');
notifTrigger.addEventListener('click', function(e) {
e.preventDefault();
if (notifContainer.className.indexOf('open') === -1) {
@ -169,6 +170,10 @@
});
app.refreshTitle();
if (ajaxify.currentPage === 'notifications') {
ajaxify.refresh();
}
// Update the favicon + local storage
var savedCount = parseInt(localStorage.getItem('notifications:count'),10) || 0;
localStorage.setItem('notifications:count', savedCount+1);
@ -208,7 +213,7 @@
});
});
socket.on('chatMessage', function(data) {
socket.on('event:chats.receive', function(data) {
require(['chat'], function(chat) {
var modal = null;
if (chat.modalExists(data.fromuid)) {
@ -219,6 +224,9 @@
chat.load(modal.attr('UUID'));
} else {
chat.toggleNew(modal.attr('UUID'), true);
}
if (!modal.is(":visible") || !app.isFocused) {
app.alternatingTitle(data.username + ' has messaged you');
}
} else {

@ -81,18 +81,20 @@ define(function() {
}
Recent.onTopicsLoaded = function(topics) {
var html = templates.prepare(templates['recent'].blocks['topics']).parse({
topics: topics
}),
container = $('#topics-container');
});
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container');
$('#category-no-topics').remove();
$('#category-no-topics').remove();
html = $(html);
container.append(html);
$('span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
html = $(html);
container.append(html);
$('span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
});
}
Recent.loadMoreTopics = function() {

@ -802,8 +802,8 @@ define(function() {
pagination.parentNode.style.display = 'block';
progressBarContainer.css('display', '');
if (scrollTop < 50 && Topic.postCount > 1) {
if (scrollTop < jQuery('.posts > .post-row:first-child').height() && Topic.postCount > 1) {
localStorage.removeItem("topic:" + tid + ":bookmark");
pagination.innerHTML = '1 out of ' + Topic.postCount;
progressBar.width(0);

@ -71,18 +71,20 @@ define(function() {
});
function onTopicsLoaded(topics) {
var html = templates.prepare(templates['unread'].blocks['topics']).parse({
topics: topics
}),
container = $('#topics-container');
});
$('#category-no-topics').remove();
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container');
html = $(html);
container.append(html);
$('span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
$('#category-no-topics').remove();
html = $(translatedHTML);
container.append(html);
$('span.timeago').timeago();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
});
}
function loadMoreTopics() {

@ -103,6 +103,7 @@ define(['taskbar'], function(taskbar) {
module.bringModalToTop(chatModal);
checkOnlineStatus(chatModal);
taskbar.updateActive(uuid);
chatModal.find('#chat-message-input').focus();
}
module.minimize = function(uuid) {
@ -114,7 +115,7 @@ define(['taskbar'], function(taskbar) {
}
function getChatMessages(chatModal, callback) {
socket.emit('getChatMessages', {touid:chatModal.touid}, function(messages) {
socket.emit('api:chats.get', {touid:chatModal.touid}, function(messages) {
for(var i = 0; i<messages.length; ++i) {
module.appendChatMessage(chatModal, messages[i].content, messages[i].timestamp);
}
@ -141,7 +142,7 @@ define(['taskbar'], function(taskbar) {
var msg = app.strip_tags(chatModal.find('#chat-message-input').val());
if(msg.length) {
msg = msg +'\n';
socket.emit('sendChatMessage', { touid:chatModal.touid, message:msg});
socket.emit('api:chats.send', { touid:chatModal.touid, message:msg});
chatModal.find('#chat-message-input').val('');
}
}

@ -300,14 +300,7 @@
namespace = namespace.replace(d + '.', '');
template = setBlock(regex, result, template);
} else if (data[d] instanceof Object) {
namespace += d + '.';
regex = makeRegex(d),
block = getBlock(regex, namespace, template)
if (block == null) continue;
block = parse(data[d], namespace, block);
template = setBlock(regex, block, template);
template = parse(data[d], d + '.', template);
} else {
function checkConditional(key, value) {
var conditional = makeConditionalRegex(key),
@ -320,14 +313,16 @@
if (conditionalBlock[1]) {
// there is an else statement
if (!value) {
template = template.replace(matches[i], conditionalBlock[1]);
template = template.replace(matches[i], conditionalBlock[1].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
} else {
template = template.replace(matches[i], conditionalBlock[0]);
template = template.replace(matches[i], conditionalBlock[0].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
}
} else {
// regular if statement
if (!value) {
template = template.replace(matches[i], '');
} else {
template = template.replace(matches[i], matches[i].replace(/<!-- ((\IF\b)|(\bENDIF\b))([^@]*?)-->/gi, ''));
}
}
}
@ -350,7 +345,11 @@
if (namespace) {
var regex = new RegExp("{" + namespace + "[\\s\\S]*?}", 'g');
template = template.replace(regex, '');
namespace = '';
}
// clean up all undefined conditionals
template = template.replace(/<!-- IF([^@]*?)ENDIF([^@]*?)-->/gi, '');
return template;

@ -53,7 +53,7 @@
<span class="timeago" title="{joindate}"></span>
<br/>
<span class="account-bio-label">[[user:profil_views]]</span>
<span class="account-bio-label">[[user:profile_views]]</span>
<span class="formatted-number">{profileviews}</span>
<br/>

@ -10,17 +10,17 @@
<div class="modal-body">
<div id="gravatar-box">
<img id="user-gravatar-picture" src="" class="img-thumbnail user-profile-picture">
<span class="user-picture-label">[[user: gravatar]]</span>
<span class="user-picture-label">[[user:gravatar]]</span>
<i class='fa fa-check fa-2x'></i>
</div>
<br/>
<div id="uploaded-box">
<img id="user-uploaded-picture" src="" class="img-thumbnail user-profile-picture">
<span class="user-picture-label">[[user: uploaded_picture]]</span>
<span class="user-picture-label">[[user:uploaded_picture]]</span>
<i class='fa fa-check fa-2x'></i>
</div>
<a id="uploadPictureBtn" href="#">[[user: upload_new_picture]]</a>
<a id="uploadPictureBtn" href="#">[[user:upload_new_picture]]</a>
</div>
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>

@ -12,7 +12,7 @@
<h4>privacy</h4>
<div class="checkbox">
<label>
<input id="showemailCheckBox" type="checkbox" {showemail}> [[user:show_my_email]]
<input id="showemailCheckBox" type="checkbox" {showemail}> [[user:show_email]]
</label>
</div>
</div>

@ -14,12 +14,15 @@
<!-- BEGIN categories -->
<li data-cid="{categories.cid}" class="entry-row">
<div class="row">
<div class="col-sm-2 hidden-xs">
<div class="preview-box" style="background: {categories.bgColor}; color: {categories.color};">
<div class="col-sm-2 hidden-xs text-center">
<div class="preview-box" style="background: {categories.background}; color: {categories.color};">
<div class="icon">
<i data-name="icon" value="{categories.icon}" class="fa {categories.icon} fa-2x"></i>
</div>
</div>
</div><br />
<!-- IF categories.image -->
<small class="pointer delete-image"><i data-name="icon" value="fa-times" class="fa fa-times"></i> Delete Image</small>
<!-- ENDIF categories.image -->
</div>
<div class="col-sm-10">
<form class="form">
@ -67,11 +70,8 @@
<hr />
<li data-disabled="{categories.disabled}"><a href="#"></a></li>
</ul>
<button type="button" data-name="image" data-value="{categories.image}" class="btn btn-default upload-button"><i class="fa fa-upload"></i> Image</button>
</div>
<!-- <div class="btn-group">
<button type="submit" class="btn btn-default disable-btn" data-disabled="{categories.disabled}">Disable</button>
<button type="button" class="btn btn-default permissions">Permissions</button>
</div> -->
</div>
</div>
</div>
@ -80,17 +80,7 @@
<input type="hidden" data-name="order" data-value="{categories.order}"></input>
</form>
</div>
<!-- <form class="form-inline">
<div class="icon">
<i data-name="icon" value="{categories.icon}" class="fa {categories.icon} fa-2x"></i>
</div>
<input placeholder="Category Name" data-name="name" value="{categories.name}" class="form-control category_name"></input>
<input placeholder="#0059b2" data-name="bgColor" value="{categories.bgColor}" class="form-control category_bgColor" />
<input placeholder="#fff" data-name="color" value="{categories.color}" class="form-control category_color" />
<input data-name="description" placeholder="Category Description" value="{categories.description}" class="form-control category_description description"></input>
<input type="hidden" data-name="order" data-value="{categories.order}"></input>
<button type="submit" class="btn btn-default disable-btn" data-disabled="{categories.disabled}">Disable</button>
</form> -->
</div>
</li>
<!-- END categories -->

@ -26,6 +26,11 @@
<p>Use <strong>privilege thresholds</strong> to manage how much reputation a user must gain to receive moderator access.</p><br />
<strong>Manage Thread</strong><br /> <input type="text" class="form-control" value="1000" data-field="privileges:manage_topic"><br />
<strong>Manage Content</strong><br /> <input type="text" class="form-control" value="1000" data-field="privileges:manage_content"><br />
<div class="checkbox">
<label>
<input type="checkbox" data-field="privileges:disabled"> <strong>Disable Privilege Threshold System</strong>
</label>
</div>
</div>
</form>
@ -55,6 +60,17 @@
</div>
</form>
<form>
<h3>Profile Settings</h3>
<div class="alert alert-warning">
<div class="checkbox">
<label>
<input type="checkbox" data-field="profile:convertProfileImageToPNG"> <strong>Convert profile image uploads to PNG</strong>
</label>
</div>
</div>
</form>
<form>
<h3>User Settings</h3>
<div class="alert alert-warning">

@ -59,7 +59,7 @@
<div id="alert_window"></div>
<footer id="footer" class="container footer">
<footer id="footer" class="container footer hide">
{footerHTML}
<div class="copyright">
Copyright &copy; 2013 <a target="_blank" href="http://www.nodebb.com">NodeBB Forums</a> | <a target="_blank" href="//github.com/designcreateplay/NodeBB/graphs/contributors">Contributors</a>

@ -8,7 +8,7 @@
<a href="category/{categories.slug}" itemprop="url">
<meta itemprop="name" content="{categories.name}">
<h4><span class="badge {categories.badgeclass}">{categories.topic_count} </span> {categories.name}</h4>
<div class="icon" style="background: {categories.bgColor}; color: {categories.color};">
<div class="icon" style="background: {categories.background}; color: {categories.color};">
<div id="category-{categories.cid}" class="category-slider-{categories.post_count}">
<div class="category-box"><i class="fa {categories.icon} fa-4x"></i></div>
<div class="category-box" itemprop="description">{categories.description}</div>

@ -9,198 +9,199 @@
<input type="hidden" template-variable="facebook-share-url" value="{facebook-share-url}" />
<input type="hidden" template-variable="google-share-url" value="{google-share-url}" />
<div class="container">
<div class="topic row">
<ol class="breadcrumb">
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
<a href="/" itemprop="url"><span itemprop="title">[[global:home]]</span></a>
</li>
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
<a href="/category/{category_slug}" itemprop="url"><span itemprop="title">{category_name}</span></a>
</li>
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
<span itemprop="title">{topic_name} <a target="_blank" href="../{topic_id}.rss"><i class="fa fa-rss-square"></i></a></span>
</li>
</ol>
<ul id="post-container" class="container posts" data-tid="{topic_id}">
<!-- BEGIN posts -->
<li class="row post-row infiniteloaded" data-pid="{posts.pid}" data-uid="{posts.uid}" data-username="{posts.username}" data-index="{posts.index}" data-deleted="{posts.deleted}" itemscope itemtype="http://schema.org/Comment">
<a id="post_anchor_{posts.pid}" name="{posts.pid}"></a>
<div class="topic">
<ol class="breadcrumb">
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
<a href="/" itemprop="url"><span itemprop="title">[[global:home]]</span></a>
</li>
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
<a href="/category/{category_slug}" itemprop="url"><span itemprop="title">{category_name}</span></a>
</li>
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
<span itemprop="title">{topic_name} <a target="_blank" href="../{topic_id}.rss"><i class="fa fa-rss-square"></i></a></span>
</li>
</ol>
<ul id="post-container" class="posts" data-tid="{topic_id}">
<!-- BEGIN posts -->
<li class="row post-row infiniteloaded" data-pid="{posts.pid}" data-uid="{posts.uid}" data-username="{posts.username}" data-index="{posts.index}" data-deleted="{posts.deleted}" itemscope itemtype="http://schema.org/Comment">
<a id="post_anchor_{posts.pid}" name="{posts.pid}"></a>
<meta itemprop="datePublished" content="{posts.relativeTime}">
<meta itemprop="dateModified" content="{posts.relativeEditTime}">
<div class="col-md-1 profile-image-block hidden-xs hidden-sm sub-post">
<a href="/user/{posts.userslug}">
<img src="{posts.picture}" align="left" class="img-thumbnail" itemprop="image" />
<!-- IF posts.user_banned -->
<span class="label label-danger">[[topic:banned]]</span>
<!-- ENDIF posts.user_banned -->
</a>
<meta itemprop="datePublished" content="{posts.relativeTime}">
<meta itemprop="dateModified" content="{posts.relativeEditTime}">
</div>
<div class="col-md-1 profile-image-block hidden-xs hidden-sm sub-post">
<a href="/user/{posts.userslug}">
<img src="{posts.picture}" align="left" class="img-thumbnail" itemprop="image" />
<!-- IF posts.user_banned -->
<span class="label label-danger">[[topic:banned]]</span>
<!-- ENDIF posts.user_banned -->
<div class="col-md-11">
<div class="post-block">
<a class="main-post avatar" href="/user/{posts.userslug}">
<img itemprop="image" src="{posts.picture}" align="left" class="img-thumbnail" width=150 height=150 />
</a>
</div>
<h3 class="main-post">
<p id="topic_title_{posts.pid}" class="topic-title" itemprop="name">{topic_name}</p>
</h3>
<div class="topic-buttons">
<div class="btn-group">
<button class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" type="button" title="[[topic:posted_by]] {posts.username}">
<span class="username-field" href="/user/{posts.userslug}" itemprop="author">{posts.username}&nbsp;</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="/user/{posts.userslug}"><i class="fa fa-user"></i> [[topic:profile]]</a></li>
<li><div class="chat"><i class="fa fa-comment"></i> [[topic:chat]]</div></li>
</ul>
</div>
<div class="col-md-11">
<div class="post-block">
<a class="main-post avatar" href="/user/{posts.userslug}">
<img itemprop="image" src="{posts.picture}" align="left" class="img-thumbnail" width=150 height=150 />
</a>
<h3 class="main-post">
<p id="topic_title_{posts.pid}" class="topic-title" itemprop="name">{topic_name}</p>
</h3>
<div class="topic-buttons">
<div class="btn-group">
<button class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" type="button" title="[[topic:posted_by]] {posts.username}">
<span class="username-field" href="/user/{posts.userslug}" itemprop="author">{posts.username}&nbsp;</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="/user/{posts.userslug}"><i class="fa fa-user"></i> [[topic:profile]]</a></li>
<li><div class="chat"><i class="fa fa-comment"></i> [[topic:chat]]</div></li>
</ul>
</div>
<div class="btn-group">
<!-- IF @first -->
<button class="btn btn-sm btn-default follow" type="button" title="Be notified of new replies in this topic"><i class="fa fa-eye"></i></button>
<!-- ENDIF @first -->
<button data-favourited="{posts.favourited}" class="favourite btn btn-sm btn-default <!-- IF posts.favourited --> btn-warning <!-- ENDIF posts.favourited -->" type="button">
<span class="favourite-text">[[topic:favourite]]</span>
<span class="post_rep_{posts.pid}">{posts.reputation} </span>
<!-- IF posts.favourited -->
<i class="fa fa-star"></i>
<!-- ELSE -->
<i class="fa fa-star-o"></i>
<!-- ENDIF posts.favourited -->
</button>
</div>
<div class="btn-group">
<button class="btn btn-sm btn-default quote" type="button" title="[[topic:quote]]"><i class="fa fa-quote-left"></i></button>
<button class="btn btn-sm btn-primary btn post_reply" type="button">[[topic:reply]] <i class="fa fa-reply"></i></button>
</div>
<div class="btn-group">
<!-- IF @first -->
<button class="btn btn-sm btn-default follow" type="button" title="Be notified of new replies in this topic"><i class="fa fa-eye"></i></button>
<!-- ENDIF @first -->
<button data-favourited="{posts.favourited}" class="favourite btn btn-sm btn-default <!-- IF posts.favourited --> btn-warning <!-- ENDIF posts.favourited -->" type="button">
<span class="favourite-text">[[topic:favourite]]</span>
<span class="post_rep_{posts.pid}">{posts.reputation} </span>
<!-- IF posts.favourited -->
<i class="fa fa-star"></i>
<!-- ELSE -->
<i class="fa fa-star-o"></i>
<!-- ENDIF posts.favourited -->
</button>
</div>
<div class="btn-group">
<button class="btn btn-sm btn-default quote" type="button" title="[[topic:quote]]"><i class="fa fa-quote-left"></i></button>
<button class="btn btn-sm btn-primary btn post_reply" type="button">[[topic:reply]] <i class="fa fa-reply"></i></button>
<div class="pull-right">
<div class="btn-group post-tools">
<button class="btn btn-sm btn-default link" type="button" title="[[topic:link]]"><i class="fa fa-link"></i></button>
<button class="btn btn-sm btn-default facebook-share" type="button" title=""><i class="fa fa-facebook"></i></button>
<button class="btn btn-sm btn-default twitter-share" type="button" title=""><i class="fa fa-twitter"></i></button>
<button class="btn btn-sm btn-default google-share" type="button" title=""><i class="fa fa-google-plus"></i></button>
</div>
<div class="pull-right">
<div class="btn-group post-tools">
<button class="btn btn-sm btn-default link" type="button" title="[[topic:link]]"><i class="fa fa-link"></i></button>
<button class="btn btn-sm btn-default facebook-share" type="button" title=""><i class="fa fa-facebook"></i></button>
<button class="btn btn-sm btn-default twitter-share" type="button" title=""><i class="fa fa-twitter"></i></button>
<button class="btn btn-sm btn-default google-share" type="button" title=""><i class="fa fa-google-plus"></i></button>
</div>
<!-- IF posts.display_moderator_tools -->
<div class="btn-group post-tools">
<button class="btn btn-sm btn-default edit" type="button" title="[[topic:edit]]"><i class="fa fa-pencil"></i></button>
<button class="btn btn-sm btn-default delete" type="button" title="[[topic:delete]]"><i class="fa fa-trash-o"></i></button>
</div>
<!-- ENDIF posts.display_moderator_tools -->
<!-- IF posts.display_moderator_tools -->
<div class="btn-group post-tools">
<button class="btn btn-sm btn-default edit" type="button" title="[[topic:edit]]"><i class="fa fa-pencil"></i></button>
<button class="btn btn-sm btn-default delete" type="button" title="[[topic:delete]]"><i class="fa fa-trash-o"></i></button>
</div>
<input id="post_{posts.pid}_link" value="" class="pull-right" style="display:none;"></input>
<!-- ENDIF posts.display_moderator_tools -->
</div>
<div id="content_{posts.pid}" class="post-content" itemprop="text">{posts.content}</div>
<!-- IF posts.signature -->
<div class="post-signature">{posts.signature}</div>
<!-- ENDIF posts.signature -->
<div class="post-info">
<span class="pull-left">
{posts.additional_profile_info}
</span>
<span class="pull-right">
[[category:posted]] <span class="relativeTimeAgo timeago" title="{posts.relativeTime}"></span>
<!-- IF posts.editor -->
<span>| [[category:last_edited_by]] <strong><a href="/user/{posts.editorslug}">{posts.editorname}</a></strong></span>
<span class="timeago" title="{posts.relativeEditTime}"></span>
<!-- ENDIF posts.editor -->
</span>
<div style="clear:both;"></div>
</div>
<input id="post_{posts.pid}_link" value="" class="pull-right" style="display:none;"></input>
</div>
</div>
</li>
<!-- IF @first -->
<li class="well post-bar">
<div class="inline-block">
<small class="topic-stats">
<span>[[category:posts]]</span>
<strong><span id="topic-post-count" class="human-readable-number" title="{postcount}">{postcount}</span></strong> |
<span>[[category:views]]</span>
<strong><span class="human-readable-number" title="{viewcount}">{viewcount}</span></strong> |
<span>[[category:browsing]]</span>
</small>
<div class="thread_active_users active-users inline-block"></div>
</div>
<div class="topic-main-buttons pull-right inline-block">
<button class="btn btn-primary post_reply" type="button">[[topic:reply]]</button>
<div class="btn-group thread-tools hide">
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">[[topic:thread_tools.title]] <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="#" class="pin_thread"><i class="fa fa-thumb-tack"></i> [[topic:thread_tools.pin]]</a></li>
<li><a href="#" class="lock_thread"><i class="fa fa-lock"></i> [[topic:thread_tools.lock]]</a></li>
<li class="divider"></li>
<li><a href="#" class="move_thread"><i class="fa fa-arrows"></i> [[topic:thread_tools.move]]</a></li>
<li class="divider"></li>
<li><a href="#" class="delete_thread"><span class="text-error"><i class="fa fa-trash-o"></i> [[topic:thread_tools.delete]]</span></a></li>
</ul>
<div id="content_{posts.pid}" class="post-content" itemprop="text">{posts.content}</div>
<!-- IF posts.signature -->
<div class="post-signature">{posts.signature}</div>
<!-- ENDIF posts.signature -->
<div class="post-info">
<span class="pull-left">
[[topic:reputation]]: <i class='fa fa-star'></i> <span class='formatted-number'>{posts.user_rep}</span>&nbsp;|&nbsp;[[topic:posts]]: <i class='fa fa-pencil'></i> <span class='formatted-number'>{posts.user_postcount}</span>
{posts.additional_profile_info}
</span>
<span class="pull-right">
[[category:posted]] <span class="relativeTimeAgo timeago" title="{posts.relativeTime}"></span>
<!-- IF posts.editor -->
<span>| [[category:last_edited_by]] <strong><a href="/user/{posts.editorslug}">{posts.editorname}</a></strong></span>
<span class="timeago" title="{posts.relativeEditTime}"></span>
<!-- ENDIF posts.editor -->
</span>
<div style="clear:both;"></div>
</div>
</div>
<div style="clear:both;"></div>
</li>
<!-- ENDIF @first -->
<!-- END posts -->
</ul>
<div class="well col-md-11 col-xs-12 pull-right hide">
<div class="topic-main-buttons pull-right inline-block hide">
<div class="loading-indicator" done="0" style="display:none;">
[[topic:loading]] <span class="hidden-xs" style="display:inline!important;">[[topic:more_posts]]</span> <i class="fa fa-refresh fa-spin"></i>
</div>
<button class="btn btn-primary post_reply" type="button">[[topic:reply]]</button>
<div class="btn-group thread-tools hide">
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">[[topic:thread_tools.title]] <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="#" class="pin_thread"><i class="fa fa-thumb-tack"></i> [[topic:thread_tools.pin]]</a></li>
<li><a href="#" class="lock_thread"><i class="fa fa-lock"></i> [[topic:thread_tools.lock]]</a></li>
<li class="divider"></li>
<li><a href="#" class="move_thread"><i class="fa fa-arrows"></i> [[topic:thread_tools.move]]</a></li>
<li class="divider"></li>
<li><a href="#" class="delete_thread"><span class="text-error"><i class="fa fa-trash-o"></i> [[topic:thread_tools.delete]]</span></a></li>
</ul>
</li>
<!-- IF @first -->
<li class="well post-bar">
<div class="inline-block">
<small class="topic-stats">
<span>[[category:posts]]</span>
<strong><span id="topic-post-count" class="human-readable-number" title="{postcount}">{postcount}</span></strong> |
<span>[[category:views]]</span>
<strong><span class="human-readable-number" title="{viewcount}">{viewcount}</span></strong> |
<span>[[category:browsing]]</span>
</small>
<div class="thread_active_users active-users inline-block"></div>
</div>
<div class="topic-main-buttons pull-right inline-block">
<button class="btn btn-primary post_reply" type="button">[[topic:reply]]</button>
<div class="btn-group thread-tools hide">
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">[[topic:thread_tools.title]] <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="#" class="pin_thread"><i class="fa fa-thumb-tack"></i> [[topic:thread_tools.pin]]</a></li>
<li><a href="#" class="lock_thread"><i class="fa fa-lock"></i> [[topic:thread_tools.lock]]</a></li>
<li class="divider"></li>
<li><a href="#" class="move_thread"><i class="fa fa-arrows"></i> [[topic:thread_tools.move]]</a></li>
<li class="divider"></li>
<li><a href="#" class="delete_thread"><span class="text-error"><i class="fa fa-trash-o"></i> [[topic:thread_tools.delete]]</span></a></li>
</ul>
</div>
</div>
<div style="clear:both;"></div>
</li>
<!-- ENDIF @first -->
<!-- END posts -->
</ul>
<div class="well col-md-11 col-xs-12 pull-right hide">
<div class="topic-main-buttons pull-right inline-block hide">
<div class="loading-indicator" done="0" style="display:none;">
[[topic:loading]] <span class="hidden-xs hidden-sm" style="display:inline!important;">[[topic:more_posts]]</span> <i class="fa fa-refresh fa-spin"></i>
</div>
<button class="btn btn-primary post_reply" type="button">[[topic:reply]]</button>
<div class="btn-group thread-tools hide">
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">[[topic:thread_tools.title]] <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="#" class="pin_thread"><i class="fa fa-thumb-tack"></i> [[topic:thread_tools.pin]]</a></li>
<li><a href="#" class="lock_thread"><i class="fa fa-lock"></i> [[topic:thread_tools.lock]]</a></li>
<li class="divider"></li>
<li><a href="#" class="move_thread"><i class="fa fa-arrows"></i> [[topic:thread_tools.move]]</a></li>
<li class="divider"></li>
<li><a href="#" class="delete_thread"><span class="text-error"><i class="fa fa-trash-o"></i> [[topic:thread_tools.delete]]</span></a></li>
</ul>
</div>
<div style="clear:both;"></div>
</div>
<div style="clear:both;"></div>
</div>
<div id="move_thread_modal" class="modal" tabindex="-1" role="dialog" aria-labelledby="Move Topic" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>[[topic:move_topic]]</h3>
</div>
<div class="modal-body">
<p id="categories-loading"><i class="fa fa-spin fa-refresh"></i> [[topic:load_categories]]</p>
<ul class="category-list"></ul>
<p>
[[topic:disabled_categories_note]]
</p>
<div id="move-confirm" style="display: none;">
<hr />
<div class="alert alert-info">[[topic:topic_will_be_moved_to]] <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">[[global:buttons.close]]</button>
<button type="button" class="btn btn-primary" id="move_thread_commit" disabled>[[topic:confirm_move]]</button>
<div id="move_thread_modal" class="modal" tabindex="-1" role="dialog" aria-labelledby="Move Topic" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>[[topic:move_topic]]</h3>
</div>
<div class="modal-body">
<p id="categories-loading"><i class="fa fa-spin fa-refresh"></i> [[topic:load_categories]]</p>
<ul class="category-list"></ul>
<p>
[[topic:disabled_categories_note]]
</p>
<div id="move-confirm" style="display: none;">
<hr />
<div class="alert alert-info">[[topic:topic_will_be_moved_to]] <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">[[global:buttons.close]]</button>
<button type="button" class="btn btn-primary" id="move_thread_commit" disabled>[[topic:confirm_move]]</button>
</div>
</div>
</div>
</div>
</div>
</div>

@ -229,7 +229,7 @@ var db = require('./database.js'),
return;
}
posts.getPostSummaryByPids(pids, function(err, postData) {
posts.getPostSummaryByPids(pids, true, function(err, postData) {
if (postData.length > count) {
postData = postData.slice(0, count);
}
@ -288,7 +288,10 @@ var db = require('./database.js'),
Categories.getCategoryData = function(cid, callback) {
db.exists('category:' + cid, function(err, exists) {
if (exists) {
db.getObject('category:' + cid, callback);
db.getObject('category:' + cid, function(err, data) {
data.background = data.image ? 'url(' + data.image + ')' : data.bgColor;
callback(err, data);
});
} else {
callback(new Error('No category found!'));
}

@ -46,7 +46,7 @@
return;
}
if(collection) {
collection.ensureIndex({_key :1, setName:1}, {background:true}, function(err, name){
collection.ensureIndex({_key :1}, {background:true}, function(err, name){
if(err) {
winston.error("Error creating index " + err.message);
}
@ -73,6 +73,39 @@
});
}
//
// helper functions
//
function removeHiddenFields(item) {
if(item) {
if(item._id) {
delete item._id;
}
if(item._key) {
delete item._key;
}
}
return item;
}
function findItem(data, key) {
if(!data) {
return null;
}
for(var i=0; i<data.length; ++i) {
if(data[i]._key === key) {
var item = data.splice(i, 1);
if(item && item.length) {
return item[0];
} else {
return null;
}
}
}
return null;
}
//
// Exported functions
@ -155,8 +188,7 @@
stats.raw = JSON.stringify(stats, null, 4);
stats.mongo = true;
//remove this when andrew adds in undefined checking to templates
stats.redis = false;
callback(err, stats);
});
@ -165,7 +197,7 @@
// key
module.exists = function(key, callback) {
db.collection('objects').findOne({$or:[{_key:key}, {setName:key}]}, function(err, item) {
db.collection('objects').findOne({_key:key}, function(err, item) {
callback(err, item !== undefined && item !== null);
});
}
@ -180,16 +212,8 @@
}
}
if(result === 0) {
db.collection('objects').remove({setName:key}, function(err, result) {
if(callback) {
callback(err, result);
}
});
} else {
if(callback) {
callback(null, result);
}
if(callback) {
callback(null, result);
}
});
}
@ -210,21 +234,6 @@
}
//hashes
function removeHiddenFields(item) {
if(item) {
if(item._id) {
delete item._id;
}
if(item._key) {
delete item._key;
}
if(item.setName) {
delete item.setName;
}
}
return item;
}
module.setObject = function(key, data, callback) {
data['_key'] = key;
db.collection('objects').update({_key:key}, {$set:data}, {upsert:true, w: 1}, function(err, result) {
@ -262,30 +271,10 @@
return callback(err);
}
var returnData = [],
resultIndex = 0;
function findData(key) {
if(!data) {
return null;
}
for(var i=0; i<data.length; ++i) {
if(data[i]._key === key) {
var item = data.splice(i, 1);
if(item && item.length) {
return item[0];
} else {
return null;
}
}
}
return null;
}
var returnData = [];
for(var i=0; i<keys.length; ++i) {
returnData.push(findData(keys[i]));
returnData.push(findItem(data, keys[i]));
}
callback(err, returnData);
@ -505,15 +494,18 @@
value:value
};
data.setName = key;
module.setObject(key + ':' + value, data, callback);
db.collection('objects').update({_key:key, value:value}, {$set:data}, {upsert:true, w: 1}, function(err, result) {
if(callback) {
callback(err, result);
}
});
}
module.sortedSetRemove = function(key, value, callback) {
if(value !== null && value !== undefined) {
value = value.toString();
}
db.collection('objects').remove({setName:key, value:value}, function(err, result) {
db.collection('objects').remove({_key:key, value:value}, function(err, result) {
if(callback) {
callback(err, result);
}
@ -521,7 +513,7 @@
}
function getSortedSetRange(key, start, stop, sort, callback) {
db.collection('objects').find({setName:key}, {fields:{value:1}})
db.collection('objects').find({_key:key}, {fields:{value:1}})
.limit(stop - start + 1)
.skip(start)
.sort({score: sort})
@ -557,7 +549,7 @@
stop = args[5];
db.collection('objects').find({setName:key, score: {$gt:min, $lt:max}}, {fields:{value:1}})
db.collection('objects').find({_key:key, score: {$gte:min, $lte:max}}, {fields:{value:1}})
.limit(stop - start + 1)
.skip(start)
.sort({score: -1})
@ -576,7 +568,7 @@
}
module.sortedSetCount = function(key, min, max, callback) {
db.collection('objects').count({setName:key, score: {$gt:min, $lt:max}}, function(err, count) {
db.collection('objects').count({_key:key, score: {$gte:min, $lte:max}}, function(err, count) {
if(err) {
return callback(err);
}
@ -609,7 +601,7 @@
if(value !== null && value !== undefined) {
value = value.toString();
}
db.collection('objects').findOne({setName:key, value: value}, {fields:{score:1}}, function(err, result) {
db.collection('objects').findOne({_key:key, value: value}, {fields:{score:1}}, function(err, result) {
if(err) {
return callback(err);
}
@ -625,22 +617,17 @@
if(value !== null && value !== undefined) {
value = value.toString();
}
db.collection('objects').find({setName:{$in:keys}, value: value}).toArray(function(err, result) {
db.collection('objects').find({_key:{$in:keys}, value: value}).toArray(function(err, result) {
if(err) {
return callback(err);
}
var returnData = [],
resultIndex = 0;
item;
for(var i=0; i<keys.length; ++i) {
if(result && resultIndex < result.length && keys[i] === result[resultIndex].setName) {
returnData.push(result[resultIndex].score);
++resultIndex;
} else {
returnData.push(null);
}
item = findItem(result, keys[i]);
returnData.push(item ? item.score : null);
}
callback(null, returnData);

@ -168,8 +168,6 @@
}
redisData.raw = JSON.stringify(redisData, null, 4);
redisData.redis = true;
//remove this when andrew adds in undefined checking to templates
redisData.mongo = false;
callback(null, redisData);
});

@ -104,12 +104,12 @@ var async = require('async'),
}
},
function (next) {
var success = function(err, config) {
var success = function (err, config) {
if (!config) {
return next(new Error('aborted'));
}
function dbQuestionsSuccess(err, databaseConfig) {
var dbQuestionsSuccess = function (err, databaseConfig) {
if (!databaseConfig) {
return next(new Error('aborted'));
}
@ -135,7 +135,7 @@ var async = require('async'),
config.bcrypt_rounds = 12;
config.upload_path = '/public/uploads';
config.use_port = (config.use_port.slice(0, 1) === 'y') ? true : false;
config.use_port = config.use_port.slice(0, 1) === 'y';
var urlObject = url.parse(config.base_url),
relative_path = (urlObject.pathname && urlObject.pathname.length > 1) ? urlObject.pathname : '',
@ -152,12 +152,20 @@ var async = require('async'),
install.save(server_conf, client_conf, function(err) {
require('./database').init(next);
});
}
};
if(config.database === 'redis') {
prompt.get(install.redisQuestions, dbQuestionsSuccess);
if (config['redis:host'] && config['redis:port']) {
dbQuestionsSuccess(null, config);
} else {
prompt.get(install.redisQuestions, dbQuestionsSuccess);
}
} else if(config.database === 'mongo') {
prompt.get(install.mongoQuestions, dbQuestionsSuccess);
if (config['mongo:host'] && config['mongo:port']) {
dbQuestionsSuccess(null, config);
} else {
prompt.get(install.mongoQuestions, dbQuestionsSuccess);
}
} else {
return next(new Error('unknown database : ' + config.database));
}
@ -173,9 +181,9 @@ var async = require('async'),
} else {
// Use provided values, fall back to defaults
var config = {},
question, x, numQ;
for(x=0,numQ=install.questions.length;x<numQ;x++) {
question = install.questions[x];
question, x, numQ, allQuestions = install.questions.concat(install.redisQuestions).concat(install.mongoQuestions);
for(x=0,numQ=allQuestions.length;x<numQ;x++) {
question = allQuestions[x];
config[question.name] = install.values[question.name] || question['default'] || '';
}
success(null, config);

@ -144,27 +144,19 @@ var fs = require('fs'),
};
Meta.title = {
build: function (urlFragment, current_user, callback) {
var self = this,
user = require('./user');
build: function (urlFragment, callback) {
var user = require('./user');
async.parallel({
title: function (next) {
self.parseFragment(urlFragment, next);
},
notifCount: function (next) {
user.notifications.getUnreadCount(current_user, next);
}
}, function (err, values) {
Meta.title.parseFragment(urlFragment, function(err, title) {
var title;
if (err) {
title = Meta.config.title || 'NodeBB';
} else {
title = (values.title ? values.title + ' | ' : '') + (Meta.config.title || 'NodeBB');
title = (title ? title + ' | ' : '') + (Meta.config.title || 'NodeBB');
}
callback(null, title, values.notifCount);
callback(null, title);
});
},
parseFragment: function (urlFragment, callback) {

@ -48,10 +48,14 @@ var db = require('./database'),
}
function hasEnoughRep(next) {
user.getUserField(uid, 'reputation', function(err, reputation) {
if (err) return next(null, false);
next(null, parseInt(reputation, 10) >= parseInt(meta.config['privileges:manage_content'], 10));
});
if (parseInt(meta.config['privileges:disabled'], 10)) {
return next(null, false);
} else {
user.getUserField(uid, 'reputation', function(err, reputation) {
if (err) return next(null, false);
next(null, parseInt(reputation, 10) >= parseInt(meta.config['privileges:manage_content'], 10));
});
}
}
async.parallel([getThreadPrivileges, isOwnPost, hasEnoughRep], function(err, results) {

@ -134,45 +134,30 @@ var db = require('./database'),
callback(new Error('reply-error'), null);
}
async.parallel([
function(next) {
topics.markUnRead(tid, function(err) {
if(err) {
return next(err);
}
topics.markAsRead(tid, uid);
next();
});
},
function(next) {
topics.pushUnreadCount(null, next);
},
function(next) {
Posts.getCidByPid(postData.pid, function(err, cid) {
if(err) {
return next(err);
}
Posts.getCidByPid(postData.pid, function(err, cid) {
if(err) {
return callback(err, null);
}
db.delete('cid:' + cid + ':read_by_uid');
next();
});
},
function(next) {
threadTools.notifyFollowers(tid, uid);
next();
},
function(next) {
Posts.addUserInfoToPost(postData, function(err) {
if(err) {
return next(err);
}
next();
});
db.delete('cid:' + cid + ':read_by_uid');
});
topics.markAsUnreadForAll(tid, function(err) {
if(err) {
return callback(err, null);
}
], function(err, results) {
topics.markAsRead(tid, uid);
topics.pushUnreadCount();
});
threadTools.notifyFollowers(tid, uid);
Posts.addUserInfoToPost(postData, function(err) {
if(err) {
return callback(err, null);
}
callback(null, postData);
});
});
@ -205,7 +190,7 @@ var db = require('./database'),
Posts.addUserInfoToPost = function(post, callback) {
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) {
if (err) {
return callback();
return callback(err);
}
postTools.parseSignature(userData.signature, function(err, signature) {
@ -242,7 +227,7 @@ var db = require('./database'),
});
};
Posts.getPostSummaryByPids = function(pids, callback) {
Posts.getPostSummaryByPids = function(pids, stripTags, callback) {
var posts = [];
@ -283,10 +268,17 @@ var db = require('./database'),
function(postData, next) {
if (postData.content) {
postTools.parse(postData.content, function(err, content) {
if (!err) {
if(err) {
return next(err);
}
if(stripTags) {
postData.content = utils.strip_tags(content);
} else {
postData.content = content;
}
next(err, postData);
next(null, postData);
});
} else {
next(null, postData);
@ -504,7 +496,7 @@ var db = require('./database'),
if (err)
return callback(err, null);
Posts.getPostSummaryByPids(pids, function(err, posts) {
Posts.getPostSummaryByPids(pids, false, function(err, posts) {
if (err)
return callback(err, null);

@ -10,7 +10,8 @@ var nconf = require('nconf'),
pkg = require('./../../package.json'),
categories = require('./../categories'),
meta = require('../meta'),
plugins = require('../plugins');
plugins = require('../plugins'),
utils = require('./../../public/src/utils.js');
@ -97,6 +98,53 @@ var nconf = require('nconf'),
});
});
app.post('/category/uploadpicture', function(req, res) {
if (!req.user)
return res.redirect('/403');
var allowedTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'];
if (allowedTypes.indexOf(req.files.userPhoto.type) === -1) {
res.send({
error: 'Allowed image types are png, jpg and gif!'
});
return;
}
var tempPath = req.files.userPhoto.path;
var extension = path.extname(req.files.userPhoto.name);
if (!extension) {
res.send({
error: 'Error uploading file! Error : Invalid extension!'
});
return;
}
var filename = 'category' + utils.generateUUID() + extension;
var uploadPath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), filename);
winston.info('Attempting upload to: ' + uploadPath);
var is = fs.createReadStream(tempPath);
var os = fs.createWriteStream(uploadPath);
is.on('end', function () {
fs.unlinkSync(tempPath);
console.log(nconf.get('upload_url') + filename);
res.json({
path: nconf.get('upload_url') + filename
});
});
os.on('error', function (err) {
fs.unlinkSync(tempPath);
winston.err(err);
});
is.pipe(os);
});
app.post('/uploadlogo', function(req, res) {
if (!req.user)

@ -2,6 +2,7 @@ var path = require('path'),
nconf = require('nconf'),
async = require('async'),
db = require('../database'),
user = require('../user'),
auth = require('./authentication'),
topics = require('../topics'),
@ -214,14 +215,18 @@ var path = require('path'),
});
app.get('/search', function (req, res) {
return res.json({
show_no_topics: 'hide',
show_no_posts: 'hide',
show_results: 'hide',
search_query: '',
posts: [],
topics: []
});
if (req.user && req.user.uid) {
return res.json({
show_no_topics: 'hide',
show_no_posts: 'hide',
show_results: 'hide',
search_query: '',
posts: [],
topics: []
});
} else {
res.send(403);
}
});
app.get('/search/:term', function (req, res, next) {
@ -232,7 +237,7 @@ var path = require('path'),
return callback(err, null);
}
posts.getPostSummaryByPids(pids, function (err, posts) {
posts.getPostSummaryByPids(pids, false, function (err, posts) {
if (err){
return callback(err, null);
}
@ -253,20 +258,24 @@ var path = require('path'),
});
}
async.parallel([searchPosts, searchTopics], function (err, results) {
if (err) {
return next();
}
if (req.user && req.user.uid) {
async.parallel([searchPosts, searchTopics], function (err, results) {
if (err) {
return next();
}
return res.json({
show_no_topics: results[1].length ? 'hide' : '',
show_no_posts: results[0].length ? 'hide' : '',
show_results: '',
search_query: req.params.term,
posts: results[0],
topics: results[1]
return res.json({
show_no_topics: results[1].length ? 'hide' : '',
show_no_posts: results[0].length ? 'hide' : '',
show_results: '',
search_query: req.params.term,
posts: results[0],
topics: results[1]
});
});
});
} else {
res.send(403);
}
});
app.get('/reset', function (req, res) {

@ -78,6 +78,7 @@ var DebugRoute = function(app) {
});
});
});
});
};

@ -102,7 +102,7 @@ var fs = require('fs'),
if (!req.user)
return res.redirect('/403');
var uploadSize = meta.config.maximumProfileImageSize || 256;
var uploadSize = parseInt(meta.config.maximumProfileImageSize, 10) || 256;
if (req.files.userPhoto.size > uploadSize * 1024) {
res.send({
@ -147,18 +147,21 @@ var fs = require('fs'),
return;
}
var filename = uid + '-profileimg' + extension;
var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10);
var filename = uid + '-profileimg' + (convertToPNG ? '.png' : extension);
var uploadPath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), filename);
winston.info('Attempting upload to: ' + uploadPath);
var is = fs.createReadStream(tempPath);
var os = fs.createWriteStream(uploadPath);
var im = require('node-imagemagick');
is.on('end', function () {
fs.unlinkSync(tempPath);
require('node-imagemagick').crop({
im.crop({
srcPath: uploadPath,
dstPath: uploadPath,
width: 128,
@ -177,6 +180,22 @@ var fs = require('fs'),
user.setUserField(uid, 'uploadedpicture', imageUrl);
user.setUserField(uid, 'picture', imageUrl);
if (convertToPNG) {
im.convert([uploadPath, 'png:-'],
function(err, stdout){
if (err) {
winston.err(err);
res.send({
error: 'Unable to convert image to PNG.'
});
return;
}
fs.writeFileSync(uploadPath, stdout, 'binary');
});
}
res.json({
path: imageUrl
});

@ -33,10 +33,14 @@ var db = require('./database'),
});
},
hasEnoughRep: function(next) {
user.getUserField(uid, 'reputation', function(err, reputation) {
if (err) return next(null, false);
next(null, parseInt(reputation, 10) >= parseInt(meta.config['privileges:manage_topic'], 10));
});
if (parseInt(meta.config['privileges:disabled'], 10)) {
return next(null, false);
} else {
user.getUserField(uid, 'reputation', function(err, reputation) {
if (err) return next(null, false);
next(null, parseInt(reputation, 10) >= parseInt(meta.config['privileges:manage_topic'], 10));
});
}
}
}, function(err, results) {
callback(err, !results ? undefined : {

@ -701,7 +701,7 @@ var async = require('async'),
});
}
Topics.markUnRead = function(tid, callback) {
Topics.markAsUnreadForAll = function(tid, callback) {
db.delete('tid:' + tid + ':read_by_uid', callback);
}

@ -237,7 +237,15 @@ Upgrade.upgradeRedis = function(callback) {
function updateKeyToHash(key, next) {
RDB.get(key, function(err, value) {
RDB.hset('global', newKeys[key], value, next);
if(err) {
return next(err);
}
if(value === null) {
RDB.hset('global', newKeys[key], initialValues[key], next);
} else {
RDB.hset('global', newKeys[key], value, next);
}
});
}
@ -270,6 +278,19 @@ Upgrade.upgradeRedis = function(callback) {
'totalpostcount':'postCount'
};
var initialValues = {
'global:next_user_id': 1,
'next_topic_id': 0,
'next_gid': 1,
'notifications:next_nid': 0,
'global:next_category_id': 12,
'global:next_message_id': 0,
'global:next_post_id': 0,
'usercount': 1,
'totaltopiccount': 0,
'totalpostcount': 0
};
async.each(keys, updateKeyToHash, function(err) {
if(err) {
return next(err);

@ -677,7 +677,7 @@ websockets.init = function(io) {
});
});
socket.on('getChatMessages', function(data, callback) {
socket.on('api:chats.get', function(data, callback) {
var touid = data.touid;
Messaging.getMessages(uid, touid, function(err, messages) {
if (err)
@ -687,7 +687,7 @@ websockets.init = function(io) {
});
});
socket.on('sendChatMessage', function(data) {
socket.on('api:chats.send', function(data) {
var touid = data.touid;
if (touid === uid || uid === 0) {
@ -696,9 +696,15 @@ websockets.init = function(io) {
var msg = utils.strip_tags(data.message);
user.getUserField(uid, 'username', function(err, username) {
user.getMultipleUserFields([uid, touid], ['username'], function(err, usersData) {
if(err) {
return;
}
var finalMessage = username + ' : ' + msg,
notifText = 'New message from <strong>' + username + '</strong>';
notifText = 'New message from <strong>' + username + '</strong>',
username = usersData[0].username,
toUsername = usersData[1].username;
if (!isUserOnline(touid)) {
notifications.create(notifText, 'javascript:app.openChat(&apos;' + username + '&apos;, ' + uid + ');', 'notification_' + uid + '_' + touid, function(nid) {
@ -715,7 +721,7 @@ websockets.init = function(io) {
numSockets = userSockets[touid].length;
for (var x = 0; x < numSockets; ++x) {
userSockets[touid][x].emit('chatMessage', {
userSockets[touid][x].emit('event:chats.receive', {
fromuid: uid,
username: username,
message: finalMessage,
@ -729,9 +735,9 @@ websockets.init = function(io) {
numSockets = userSockets[uid].length;
for (var x = 0; x < numSockets; ++x) {
userSockets[uid][x].emit('chatMessage', {
userSockets[uid][x].emit('event:chats.receive', {
fromuid: touid,
username: username,
username: toUsername,
message: 'You : ' + msg,
timestamp: Date.now()
});
@ -1078,8 +1084,8 @@ websockets.init = function(io) {
});
socket.on('api:meta.buildTitle', function(text, callback) {
meta.title.build(text, uid, function(err, title, numNotifications) {
callback(title, numNotifications);
meta.title.build(text, function(err, title) {
callback(title);
});
});

Loading…
Cancel
Save