From 5945ab1a0aa3e5dcf0d3326d75db4fa0bb08cc5e Mon Sep 17 00:00:00 2001 From: Noah Chase Date: Sat, 19 Oct 2013 13:11:28 -0400 Subject: [PATCH 01/21] relax username validation (#413) this commit allows for matching accented characters, dots, '@' symbol, and other important things. --- public/src/utils.js | 2 +- tests/utils.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/utils.js diff --git a/public/src/utils.js b/public/src/utils.js index c99fbb99a3..6b9343ee95 100644 --- a/public/src/utils.js +++ b/public/src/utils.js @@ -94,7 +94,7 @@ }, isUserNameValid: function(name) { - return (name && name !== "" && (/^[a-zA-Z0-9 _-]+$/.test(name))); + return (name && name !== "" && (/^['"\s\-.*0-9\u00BF-\u1FFF\u2C00-\uD7FF\w]+$/.test(name))); }, isPasswordValid: function(password) { diff --git a/tests/utils.js b/tests/utils.js new file mode 100644 index 0000000000..70643802f8 --- /dev/null +++ b/tests/utils.js @@ -0,0 +1,12 @@ +var assert = require('assert'), + utils = require('./../public/src/utils.js'); + + +describe("Utility Methods", function(){ + describe("username validation", function(){ + it("accepts latin-1 characters", function(){ + var username = "John\"'-. Doeäâèéë1234"; + assert(utils.isUserNameValid(username), 'invalid username'); + }); + }); +}); From f4faee4283cb315e2bc7a4ca62bd8bd38d797654 Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Tue, 22 Oct 2013 15:54:02 -0400 Subject: [PATCH 02/21] moved image uploading to a require js module, added image upload to site logo --- public/src/forum/accountedit.js | 94 ++++------------------------- public/src/forum/admin/settings.js | 11 +++- public/src/modules/uploader.js | 83 +++++++++++++++++++++++++ public/templates/accountedit.tpl | 35 ----------- public/templates/admin/footer.tpl | 35 +++++++++++ public/templates/admin/header.tpl | 4 ++ public/templates/admin/settings.tpl | 3 +- public/templates/footer.tpl | 34 +++++++++++ public/templates/header.tpl | 2 +- src/posts.js | 10 ++- src/routes/admin.js | 57 +++++++++++++++-- src/routes/user.js | 2 +- 12 files changed, 242 insertions(+), 128 deletions(-) create mode 100644 public/src/modules/uploader.js diff --git a/public/src/forum/accountedit.js b/public/src/forum/accountedit.js index 7771562454..530261c77d 100644 --- a/public/src/forum/accountedit.js +++ b/public/src/forum/accountedit.js @@ -1,4 +1,4 @@ -define(['forum/accountheader'], function(header) { +define(['forum/accountheader', 'uploader'], function(header, uploader) { var AccountEdit = {}; AccountEdit.init = function() { @@ -7,61 +7,6 @@ define(['forum/accountheader'], function(header) { var gravatarPicture = templates.get('gravatarpicture'); var uploadedPicture = templates.get('uploadedpicture'); - $('#uploadForm').submit(function() { - AccountEdit.status('uploading the file ...'); - - $('#upload-progress-bar').css('width', '0%'); - $('#upload-progress-box').show(); - $('#upload-progress-box').removeClass('hide'); - - if (!$('#userPhotoInput').val()) { - AccountEdit.error('select an image to upload!'); - return false; - } - - $(this).find('#imageUploadCsrf').val($('#csrf_token').val()); - - - $(this).ajaxSubmit({ - - error: function(xhr) { - AccountEdit.error('Error: ' + xhr.status); - }, - - uploadProgress: function(event, position, total, percent) { - console.log(percent); - $('#upload-progress-bar').css('width', percent + '%'); - }, - - - success: function(response) { - if (response.error) { - AccountEdit.error(response.error); - return; - } - - var imageUrlOnServer = response.path; - - $('#user-current-picture').attr('src', imageUrlOnServer); - $('#user-uploaded-picture').attr('src', imageUrlOnServer); - - uploadedPicture = imageUrlOnServer; - - setTimeout(function() { - AccountEdit.hideAlerts(); - $('#upload-picture-modal').modal('hide'); - }, 750); - - socket.emit('api:updateHeader', { - fields: ['username', 'picture', 'userslug'] - }); - AccountEdit.success('File uploaded successfully!'); - } - }); - - return false; - }); - var selectedImageType = ''; $('#submitBtn').on('click', function() { @@ -137,17 +82,21 @@ define(['forum/accountheader'], function(header) { $('#uploadPictureBtn').on('click', function() { $('#change-picture-modal').modal('hide'); - $('#upload-picture-modal').modal('show'); - $('#upload-picture-modal').removeClass('hide'); + uploader.open(config.relative_path + '/user/uploadpicture', function(imageUrlOnServer) { + $('#user-current-picture').attr('src', imageUrlOnServer); + $('#user-uploaded-picture').attr('src', imageUrlOnServer); + + uploadedPicture = imageUrlOnServer; + + socket.emit('api:updateHeader', { + fields: ['username', 'picture', 'userslug'] + }); + }); - AccountEdit.hideAlerts(); return false; }); - $('#pictureUploadSubmitBtn').on('click', function() { - $('#uploadForm').submit(); - }); (function handlePasswordChange() { var currentPassword = $('#inputCurrentPassword'); @@ -230,27 +179,6 @@ define(['forum/accountheader'], function(header) { }()); }; - AccountEdit.hideAlerts = function() { - $('#alert-status').addClass('hide'); - $('#alert-success').addClass('hide'); - $('#alert-error').addClass('hide'); - $('#upload-progress-box').addClass('hide'); - } - - AccountEdit.status = function(message) { - AccountEdit.hideAlerts(); - $('#alert-status').text(message).removeClass('hide'); - } - - AccountEdit.success = function(message) { - AccountEdit.hideAlerts(); - $('#alert-success').text(message).removeClass('hide'); - } - - AccountEdit.error = function(message) { - AccountEdit.hideAlerts(); - $('#alert-error').text(message).removeClass('hide'); - } AccountEdit.changeUserPicture = function(type) { var userData = { diff --git a/public/src/forum/admin/settings.js b/public/src/forum/admin/settings.js index b6017af47e..bbf04fef3e 100644 --- a/public/src/forum/admin/settings.js +++ b/public/src/forum/admin/settings.js @@ -1,4 +1,4 @@ -define(function() { +define(['uploader'], function(uploader) { var Settings = {}; Settings.init = function() { @@ -69,6 +69,15 @@ define(function() { }); } }); + + $('#uploadLogoBtn').on('click', function() { + + uploader.open(config.relative_path + '/admin/uploadlogo', function(image) { + $('#logoUrl').val(image); + }); + + uploader.hideAlerts(); + }); }; Settings.remove = function(key) { diff --git a/public/src/modules/uploader.js b/public/src/modules/uploader.js new file mode 100644 index 0000000000..381e0d2cad --- /dev/null +++ b/public/src/modules/uploader.js @@ -0,0 +1,83 @@ +define(function() { + + var module = {}; + + module.open = function(route, callback) { + $('#upload-picture-modal').modal('show').removeClass('hide'); + module.hideAlerts(); + + $('#uploadForm')[0].reset(); + $('#uploadForm').attr('action', route); + + $('#pictureUploadSubmitBtn').off('click').on('click', function() { + $('#uploadForm').submit(); + }); + + $('#uploadForm').off('submit').submit(function() { + + function status(message) { + module.hideAlerts(); + $('#alert-status').text(message).removeClass('hide'); + } + + function success(message) { + module.hideAlerts(); + $('#alert-success').text(message).removeClass('hide'); + } + + function error(message) { + module.hideAlerts(); + $('#alert-error').text(message).removeClass('hide'); + } + + status('uploading the file ...'); + + $('#upload-progress-bar').css('width', '0%'); + $('#upload-progress-box').show().removeClass('hide'); + + if (!$('#userPhotoInput').val()) { + error('select an image to upload!'); + return false; + } + + $(this).find('#imageUploadCsrf').val($('#csrf_token').val()); + + + $(this).ajaxSubmit({ + + error: function(xhr) { + error('Error: ' + xhr.status); + }, + + uploadProgress: function(event, position, total, percent) { + $('#upload-progress-bar').css('width', percent + '%'); + }, + + success: function(response) { + if (response.error) { + error(response.error); + return; + } + callback(response.path); + + success('File uploaded successfully!'); + setTimeout(function() { + module.hideAlerts(); + $('#upload-picture-modal').modal('hide'); + }, 750); + } + }); + + return false; + }); + } + + module.hideAlerts = function() { + $('#alert-status').addClass('hide'); + $('#alert-success').addClass('hide'); + $('#alert-error').addClass('hide'); + $('#upload-progress-box').addClass('hide'); + } + + return module; +}); \ No newline at end of file diff --git a/public/templates/accountedit.tpl b/public/templates/accountedit.tpl index 2166c69053..acfe8bc4ce 100644 --- a/public/templates/accountedit.tpl +++ b/public/templates/accountedit.tpl @@ -31,41 +31,6 @@ - - + +
+ +
@@ -126,4 +129,5 @@
+
diff --git a/public/templates/admin/settings.tpl b/public/templates/admin/settings.tpl index 9172ba310e..693247efa1 100644 --- a/public/templates/admin/settings.tpl +++ b/public/templates/admin/settings.tpl @@ -11,7 +11,8 @@
-
+
+

diff --git a/public/templates/footer.tpl b/public/templates/footer.tpl index 39bdc9eca0..85d380fbc2 100644 --- a/public/templates/footer.tpl +++ b/public/templates/footer.tpl @@ -21,6 +21,40 @@
+
diff --git a/public/templates/header.tpl b/public/templates/header.tpl index 100d2d71df..a88a02339e 100644 --- a/public/templates/header.tpl +++ b/public/templates/header.tpl @@ -43,7 +43,7 @@
- +

{title}

diff --git a/src/posts.js b/src/posts.js index ef285a8bcd..e1d30a677c 100644 --- a/src/posts.js +++ b/src/posts.js @@ -177,10 +177,16 @@ var RDB = require('./redis.js'), multi.exec(function (err, replies) { async.map(replies, function(postData, _callback) { if (postData) { - postData.relativeTime = new Date(parseInt(postData.timestamp,10)).toISOString(); + postData.post_rep = postData.reputation; postData['edited-class'] = postData.editor !== '' ? '' : 'none'; - postData['relativeEditTime'] = postData.edited !== '0' ? (new Date(parseInt(postData.edited,10)).toISOString()) : ''; + try { + postData.relativeTime = new Date(parseInt(postData.timestamp,10)).toISOString(); + postData['relativeEditTime'] = postData.edited !== '0' ? (new Date(parseInt(postData.edited,10)).toISOString()) : ''; + } catch(e) { + winston.err('invalid time value'); + } + if (postData.uploadedImages) { try { diff --git a/src/routes/admin.js b/src/routes/admin.js index 28d0044849..afdb47adbc 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -8,7 +8,8 @@ var user = require('./../user.js'), plugins = require('../plugins'), winston = require('winston'), nconf = require('nconf'), - fs = require('fs'); + fs = require('fs'), + path = require('path'); (function (Admin) { Admin.isAdmin = function (req, res, next) { @@ -78,6 +79,54 @@ var user = require('./../user.js'), res.send(header + app.create_route('admin/index') + templates['admin/footer']); }); }); + + app.post('/uploadlogo', Admin.isAdmin, 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 = 'site-logo' + extension; + var uploadPath = path.join(process.cwd(), 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); + + res.json({ + path: nconf.get('upload_url') + filename + }); + }); + + os.on('error', function (err) { + fs.unlinkSync(tempPath); + winston.err(err); + }); + + is.pipe(os); + }); }); @@ -89,7 +138,7 @@ var user = require('./../user.js'), plugins.ready(function() { plugins.fireHook('filter:admin.create_routes', custom_routes, function(err, custom_routes) { var routes = custom_routes.routes; - + for (var route in routes) { if (routes.hasOwnProperty(route)) { app[routes[route].method || 'get']('/admin' + routes[route].route, function(req, res) { @@ -98,10 +147,10 @@ var user = require('./../user.js'), res.send(header + options.content + templates['admin/footer']); }); }); - }); + }); } } - }); + }); }); app.namespace('/api/admin', function () { diff --git a/src/routes/user.js b/src/routes/user.js index d31f2b1ba7..62b8560b97 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -425,7 +425,7 @@ var user = require('./../user.js'), posts.getPostsByUid(userData.theirid, 0, 9, function (posts) { userData.posts = posts.filter(function (p) { - return p.deleted !== "1"; + return p && p.deleted !== "1"; }); userData.isFollowing = isFollowing; if (!userData.profileviews) From b29616fbd82e66f05f4b074b246fcc449f5c8485 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 22 Oct 2013 18:10:51 -0400 Subject: [PATCH 03/21] adding link to notifications page in notifications dropdown --- public/src/forum/footer.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/public/src/forum/footer.js b/public/src/forum/footer.js index b577647aa6..4c05432027 100644 --- a/public/src/forum/footer.js +++ b/public/src/forum/footer.js @@ -126,6 +126,13 @@ notifEl.innerHTML = '
You have no notifications'; notifFrag.appendChild(notifEl); } + + // Add dedicated link to /notifications + notifEl.removeAttribute('data-nid'); + notifEl.className = 'pagelink'; + notifEl.innerHTML = 'See all Notifications'; + notifFrag.appendChild(notifEl); + notifList.appendChild(notifFrag); if (data.unread.length > 0) notifIcon.className = 'icon-circle active'; From 17083dc5e61efb8fa5b72e7854cb753adc2df859 Mon Sep 17 00:00:00 2001 From: Baris Soner Usakli Date: Tue, 22 Oct 2013 19:41:34 -0400 Subject: [PATCH 04/21] closes #417 --- public/src/templates.js | 30 ++++++++++++++++-------------- public/templates/topic.tpl | 17 +++++++++-------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/public/src/templates.js b/public/src/templates.js index a7e4510210..4f9055d0ad 100644 --- a/public/src/templates.js +++ b/public/src/templates.js @@ -172,25 +172,27 @@ template_data['relative_path'] = RELATIVE_PATH; translator.translate(templates[tpl_url].parse(template_data), function (translatedTemplate) { - document.getElementById('content').innerHTML = translatedTemplate; + + $('#content').html(translatedTemplate); jQuery('#content [template-variable]').each(function (index, element) { var value = null; - - switch (element.getAttribute('template-type')) { - case 'boolean': - value = (element.value === 'true' || element.value === '1') ? true : false; - break; - case 'int': // Intentional fall-through - case 'integer': - value = parseInt(element.value); - break; - default: - value = element.value; - break; + console.log($(element).attr('value')); + console.log($(element).attr('template-variable')); + switch ($(element).attr('template-type')) { + case 'boolean': + value = ($(element).val() === 'true' || $(element).val() === '1') ? true : false; + break; + case 'int': // Intentional fall-through + case 'integer': + value = parseInt($(element).val()); + break; + default: + value = $(element).val(); + break; } - templates.set(element.getAttribute('template-variable'), value); + templates.set($(element).attr('template-variable'), value); }); if (callback) { diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl index 1d9346a1ab..a929812637 100644 --- a/public/templates/topic.tpl +++ b/public/templates/topic.tpl @@ -1,3 +1,12 @@ + + + + + + + + +
- - - - - - - - From 87744302baf902aad784ff16250f0b66670dfed4 Mon Sep 17 00:00:00 2001 From: Baris Soner Usakli Date: Tue, 22 Oct 2013 19:45:06 -0400 Subject: [PATCH 05/21] fixed button tags in topic.tpl --- public/templates/topic.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl index a929812637..bd26d4f271 100644 --- a/public/templates/topic.tpl +++ b/public/templates/topic.tpl @@ -206,8 +206,8 @@ From 55e990f71d5b3953f851b4be3703bbee46209861 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 22 Oct 2013 21:20:56 -0400 Subject: [PATCH 06/21] fixes #433 - looks like someone removed the code that floated pinned topics to the top... --- src/categories.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/categories.js b/src/categories.js index 9833720896..6a67d34775 100644 --- a/src/categories.js +++ b/src/categories.js @@ -87,6 +87,11 @@ var RDB = require('./redis.js'), function getTopics(next) { topics.getTopicsByTids(tids, current_user, function(topicsData) { + // Float pinned topics to the top of the list + topicsData = topicsData.sort(function(a, b) { + return parseInt(b.pinned, 10) - parseInt(a.pinned, 10); + }); + next(null, topicsData); }, category_id); } From ab1015b11e37331200244b5e59c3a219e078c672 Mon Sep 17 00:00:00 2001 From: Baris Soner Usakli Date: Tue, 22 Oct 2013 21:47:09 -0400 Subject: [PATCH 07/21] #433 --- src/categories.js | 5 ----- src/posts.js | 9 +++++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/categories.js b/src/categories.js index 6a67d34775..9833720896 100644 --- a/src/categories.js +++ b/src/categories.js @@ -87,11 +87,6 @@ var RDB = require('./redis.js'), function getTopics(next) { topics.getTopicsByTids(tids, current_user, function(topicsData) { - // Float pinned topics to the top of the list - topicsData = topicsData.sort(function(a, b) { - return parseInt(b.pinned, 10) - parseInt(a.pinned, 10); - }); - next(null, topicsData); }, category_id); } diff --git a/src/posts.js b/src/posts.js index 68172644f1..ae6c5f53e5 100644 --- a/src/posts.js +++ b/src/posts.js @@ -365,13 +365,18 @@ var RDB = require('./redis.js'), RDB.incr('totalpostcount'); - topics.getTopicField(tid, 'cid', function(err, cid) { + topics.getTopicFields(tid, ['cid', 'pinned'], function(err, topicData) { + RDB.handle(err); + var cid = topicData.cid; + feed.updateTopic(tid); RDB.zadd('categories:recent_posts:cid:' + cid, timestamp, pid); - RDB.zadd('categories:' + cid + ':tid', timestamp, tid); + + if(topicData.pinned === '0') + RDB.zadd('categories:' + cid + ':tid', timestamp, tid); RDB.scard('cid:' + cid + ':active_users', function(err, amount) { if (amount > 10) { From 25e6f729211887f1ec0a98eedfbe82d62d0883ee Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 23 Oct 2013 12:16:48 -0400 Subject: [PATCH 08/21] closes #434 --- public/src/modules/chat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index 0921f6d5a1..aad7331faf 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -86,8 +86,8 @@ define(['taskbar'], function(taskbar) { } function center(chatModal) { - chatModal.css("position","absolute"); - chatModal.css("top", Math.max(0, (($(window).height() - $(chatModal).outerHeight()) / 2) + $(window).scrollTop()) + "px"); + chatModal.css("position", "fixed"); + chatModal.css("top", "100px"); chatModal.css("left", Math.max(0, (($(window).width() - $(chatModal).outerWidth()) / 2) + $(window).scrollLeft()) + "px"); return chatModal; } From 790df903acc1de4ec7c8c1495df71cde0bfa65a7 Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 23 Oct 2013 12:26:24 -0400 Subject: [PATCH 09/21] added view count to topics --- src/topics.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/topics.js b/src/topics.js index ec86fde245..ceb8f7e3ae 100644 --- a/src/topics.js +++ b/src/topics.js @@ -353,6 +353,7 @@ var RDB = require('./redis.js'), return callback(new Error('Topic tid \'' + tid + '\' not found')); Topics.markAsRead(tid, current_user); + Topics.increaseViewCount(tid); function getTopicData(next) { Topics.getTopicData(tid, function(topicData) { @@ -399,6 +400,7 @@ var RDB = require('./redis.js'), 'pinned': topicData.pinned, 'slug': topicData.slug, 'postcount': topicData.postcount, + 'viewcount': topicData.viewcount, 'topic_id': tid, 'expose_tools': privileges.editable ? 1 : 0, 'posts': topicPosts, @@ -681,6 +683,7 @@ var RDB = require('./redis.js'), 'timestamp': timestamp, 'lastposttime': 0, 'postcount': 0, + 'viewcount': 0, 'locked': 0, 'deleted': 0, 'pinned': 0 @@ -741,6 +744,10 @@ var RDB = require('./redis.js'), RDB.hincrby('topic:' + tid, 'postcount', 1); } + Topics.increaseViewCount = function(tid) { + RDB.hincrby('topic:' + tid, 'viewcount', 1); + } + Topics.isLocked = function(tid, callback) { Topics.getTopicField(tid, 'locked', function(err, locked) { callback(locked); From 1691c747270b6169b3fb474477b69edf3f24ac03 Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 23 Oct 2013 14:39:46 -0400 Subject: [PATCH 10/21] testing breadcrumb images --- public/src/forum/topic.js | 78 +++++++++++++++++++++++++++++++++++++-- public/src/templates.js | 5 +-- src/websockets.js | 13 ++++--- 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 42c6d8e6ab..e7bb1fe1bf 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -351,10 +351,82 @@ define(function() { socket.on('api:get_users_in_room', function(data) { - var activeEl = $('#thread_active_users'); - if (activeEl.length) - activeEl.html(data); + if(data) { + var activeEl = $('#thread_active_users'); + function createUserIcon(uid, picture, userslug, username) { + if(!activeEl.find("[href='/user/"+ data.users[i].userslug + "']").length) { + var userIcon = $(''); + userIcon.css('height', '24px'); + + var userLink = $('').append(userIcon); + userLink.attr('data-uid', uid); + + userLink.tooltip({ + placement: 'left', + title: username + }); + + return userLink; + } + } + + // remove users that are no longer here + activeEl.children().each(function(index, element) { + if(element) { + var uid = $(element).attr('data-uid'); + for(var i=0; i 8) { + break; + } + } + + var remainingUsers = data.users.length - 9; + remainingUsers = remainingUsers < 0 ? 0 : remainingUsers; + var anonymousCount = parseInt(data.anonymousCount, 10); + activeEl.find('.anon').remove(); + if(anonymousCount || remainingUsers) { + + var anonLink = $(''); + anonLink.css('padding', '5px'); + activeEl.append(anonLink); + + var title = ''; + if(remainingUsers && anonymousCount) + title = remainingUsers + ' more user(s) and ' + anonymousCount + ' guest(s)'; + else if(remainingUsers) + title = remainingUsers + ' more user(s)'; + else + title = anonymousCount + ' guest(s)'; + + anonLink.tooltip({ + placement: 'left', + title: title + }); + } + } app.populate_online_users(); }); diff --git a/public/src/templates.js b/public/src/templates.js index 4f9055d0ad..cb153ed10d 100644 --- a/public/src/templates.js +++ b/public/src/templates.js @@ -172,13 +172,12 @@ template_data['relative_path'] = RELATIVE_PATH; translator.translate(templates[tpl_url].parse(template_data), function (translatedTemplate) { - + $('#content').html(translatedTemplate); jQuery('#content [template-variable]').each(function (index, element) { var value = null; - console.log($(element).attr('value')); - console.log($(element).attr('template-variable')); + switch ($(element).attr('template-type')) { case 'boolean': value = ($(element).val() === 'true' || $(element).val() === '1') ? true : false; diff --git a/src/websockets.js b/src/websockets.js index 0bce3e76b4..0aadc0abe4 100644 --- a/src/websockets.js +++ b/src/websockets.js @@ -157,8 +157,7 @@ module.exports.init = function(io) { for (var i = 0; i < clients.length; ++i) { var hs = clients[i].handshake; - - if (hs && !users[sessionID]) { + if (hs && clients[i].state.user.uid === 0) { ++anonCount; } } @@ -185,11 +184,13 @@ module.exports.init = function(io) { if (uids.length === 0) { - io.sockets. in (roomName).emit('api:get_users_in_room', userList([], anonymousCount, 0)); + io.sockets. in (roomName).emit('api:get_users_in_room', { users: [], anonymousCount:0 }); } else { - user.getMultipleUserFields(uids, ['username', 'userslug'], function(err, users) { - if (!err) - io.sockets. in (roomName).emit('api:get_users_in_room', userList(users, anonymousCount, users.length)); + user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], function(err, users) { + //if (!err) + //io.sockets. in (roomName).emit('api:get_users_in_room', userList(users, anonymousCount, users.length)); + if(!err) + io.sockets. in (roomName).emit('api:get_users_in_room', { users: users, anonymousCount:anonymousCount }); }); } } From 0565b7b8c81d0d35cb6acb2dbd7ea48946181b7f Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 23 Oct 2013 15:00:06 -0400 Subject: [PATCH 11/21] moved css out --- public/src/forum/topic.js | 8 +++----- public/templates/topic.tpl | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index e7bb1fe1bf..a9b70c7966 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -352,12 +352,11 @@ define(function() { socket.on('api:get_users_in_room', function(data) { if(data) { - var activeEl = $('#thread_active_users'); + var activeEl = $('.thread_active_users'); function createUserIcon(uid, picture, userslug, username) { if(!activeEl.find("[href='/user/"+ data.users[i].userslug + "']").length) { var userIcon = $(''); - userIcon.css('height', '24px'); var userLink = $('').append(userIcon); userLink.attr('data-uid', uid); @@ -406,11 +405,10 @@ define(function() { var remainingUsers = data.users.length - 9; remainingUsers = remainingUsers < 0 ? 0 : remainingUsers; var anonymousCount = parseInt(data.anonymousCount, 10); - activeEl.find('.anon').remove(); + activeEl.find('.anonymous-box').remove(); if(anonymousCount || remainingUsers) { - var anonLink = $(''); - anonLink.css('padding', '5px'); + var anonLink = $(''); activeEl.append(anonLink); var title = ''; diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl index bd26d4f271..e09d94f9d0 100644 --- a/public/templates/topic.tpl +++ b/public/templates/topic.tpl @@ -18,7 +18,7 @@
  • {topic_name}
  • - +
      From c640c550fd80b8f779d469bf55a1446f14f0c8f1 Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 23 Oct 2013 15:12:19 -0400 Subject: [PATCH 12/21] removed old browsing code from websockets.js --- src/websockets.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/websockets.js b/src/websockets.js index 0aadc0abe4..36df253f1a 100644 --- a/src/websockets.js +++ b/src/websockets.js @@ -168,27 +168,10 @@ module.exports.init = function(io) { var anonymousCount = getAnonymousCount(roomName); - function userList(users, anonymousCount, userCount) { - var usernames = []; - - for (var i = 0, ii = users.length; i < ii; ++i) { - usernames[i] = '' + '' + users[i].username + ''; - } - - var joiner = anonymousCount + userCount == 1 ? 'is' : 'are', - userList = anonymousCount > 0 ? usernames.concat(util.format('%d guest%s', anonymousCount, anonymousCount > 1 ? 's' : '')) : usernames, - lastUser = userList.length > 1 ? ' and ' + userList.pop() : ''; - - return util.format('%s%s %s browsing this thread', userList.join(', '), lastUser, joiner); - } - - if (uids.length === 0) { io.sockets. in (roomName).emit('api:get_users_in_room', { users: [], anonymousCount:0 }); } else { user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], function(err, users) { - //if (!err) - //io.sockets. in (roomName).emit('api:get_users_in_room', userList(users, anonymousCount, users.length)); if(!err) io.sockets. in (roomName).emit('api:get_users_in_room', { users: users, anonymousCount:anonymousCount }); }); From 24592cc69620475a5d60fc02c8a00d58f231863c Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 23 Oct 2013 15:24:43 -0400 Subject: [PATCH 13/21] fixed the anon-box in users/online to show inline --- public/src/forum/users.js | 9 +++++---- public/templates/users.tpl | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/public/src/forum/users.js b/public/src/forum/users.js index d16aac8497..8d57e1e5fc 100644 --- a/public/src/forum/users.js +++ b/public/src/forum/users.js @@ -65,9 +65,9 @@ define(function() { var html = templates.prepare(templates['users'].blocks['users']).parse({ users: data }), - userListEl = document.querySelector('#users-inner-container'); + userListEl = $('#users-inner-container'); - userListEl.innerHTML = html; + userListEl.html(html); if (data && data.length === 0) { @@ -94,8 +94,9 @@ define(function() { users: users }); if(emptyContainer) - $('#users-inner-container').empty(); + $('#users-inner-container .registered-user').remove(); $('#users-inner-container').append(html); + $('#users-inner-container .anon-user').appendTo($('#users-inner-container')); } function loadMoreUsers() { @@ -111,7 +112,7 @@ define(function() { } if (set) { - startLoading(set, $('#users-inner-container').children().length); + startLoading(set, $('#users-inner-container .registered-user').children().length); } } diff --git a/public/templates/users.tpl b/public/templates/users.tpl index a223ad2b82..6cddd91e47 100644 --- a/public/templates/users.tpl +++ b/public/templates/users.tpl @@ -40,18 +40,19 @@ - -
      - - - -
      - +
    From 45feef58843ac59107f9207a51c21ffad475b78e Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 23 Oct 2013 15:45:00 -0400 Subject: [PATCH 14/21] closes #421 --- public/src/translator.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/public/src/translator.js b/public/src/translator.js index 37f4486feb..103ccb124f 100644 --- a/public/src/translator.js +++ b/public/src/translator.js @@ -46,7 +46,7 @@ translator.translate = function (data, callback) { var keys = data.match(/\[\[.*?\]\]/g), loading = 0; - + function insertLanguage(text, key, value, variables) { if (value) { for (var i = 1, ii = variables.length; i < ii; i++) { @@ -56,7 +56,7 @@ text = text.replace(key, value); } - + return text; } @@ -74,14 +74,13 @@ data = insertLanguage(data, keys[key], files.loaded[languageFile][parsedKey], variables); } else { loading++; - - (function (languageKey, parsedKey) { + (function (languageKey, parsedKey, languageFile, variables) { translator.load(languageFile, function (languageData) { data = insertLanguage(data, languageKey, languageData[parsedKey], variables); loading--; checkComplete(); }); - }(keys[key], parsedKey)); + }(keys[key], parsedKey, languageFile, variables)); } } From 549017d035a8155332d610de62730bbce99b2be2 Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 23 Oct 2013 16:27:33 -0400 Subject: [PATCH 15/21] cleaned up getCategories --- src/categories.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/categories.js b/src/categories.js index 9833720896..95baee275e 100644 --- a/src/categories.js +++ b/src/categories.js @@ -335,8 +335,6 @@ var RDB = require('./redis.js'), return; } - // var categories = []; - function getCategory(cid, callback) { Categories.getCategoryData(cid, function(err, categoryData) { if (err) { @@ -348,7 +346,6 @@ var RDB = require('./redis.js'), Categories.hasReadCategory(cid, current_user, function(hasRead) { categoryData.badgeclass = (parseInt(categoryData.topic_count, 10) === 0 || (hasRead && current_user !== 0)) ? '' : 'badge-important'; - // categories.push(categoryData); callback(null, categoryData); }); }); @@ -362,11 +359,8 @@ var RDB = require('./redis.js'), } categories = categories.filter(function(category) { - // Remove categories that have errored out - if (category) return true; - else return false; + return !!category; }).sort(function(a, b) { - // Sort categories into their defined order return parseInt(a.order, 10) - parseInt(b.order, 10); }); From 63d49463da426d75b8a2bae90d2e0061735f9e3e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 24 Oct 2013 08:10:58 -0400 Subject: [PATCH 16/21] removed deprecated /plugins folder, updated vanilla package info to always load the latest latest version - closes #438 --- package.json | 2 +- plugins/.gitignore | 0 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 plugins/.gitignore diff --git a/package.json b/package.json index 4c7cac2705..39aa024bdc 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "validator": "~1.5.1", "nodebb-plugin-mentions": "~0.1.12", "nodebb-plugin-markdown": "~0.1.7", - "nodebb-theme-vanilla": "0.0.3", + "nodebb-theme-vanilla": "git://github.com/designcreateplay/nodebb-theme-vanilla.git#HEAD", "nodebb-theme-cerulean": "0.0.3" }, "optionalDependencies": { diff --git a/plugins/.gitignore b/plugins/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 From 53b12f50a788e2234fe614c30dbcaea765fb111a Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 24 Oct 2013 08:35:32 -0400 Subject: [PATCH 17/21] updating git url for vanilla theme --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 39aa024bdc..4cc5543bb3 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "validator": "~1.5.1", "nodebb-plugin-mentions": "~0.1.12", "nodebb-plugin-markdown": "~0.1.7", - "nodebb-theme-vanilla": "git://github.com/designcreateplay/nodebb-theme-vanilla.git#HEAD", + "nodebb-theme-vanilla": "designcreateplay/nodebb-theme-vanilla", "nodebb-theme-cerulean": "0.0.3" }, "optionalDependencies": { From f9f0bd8685f16c452548fc1139ef601ff55133d9 Mon Sep 17 00:00:00 2001 From: Baris Soner Usakli Date: Thu, 24 Oct 2013 23:32:25 -0400 Subject: [PATCH 18/21] closes #445 --- public/templates/admin/settings.tpl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/public/templates/admin/settings.tpl b/public/templates/admin/settings.tpl index 693247efa1..8e23e945c7 100644 --- a/public/templates/admin/settings.tpl +++ b/public/templates/admin/settings.tpl @@ -24,10 +24,8 @@

    Privilege Thresholds

    Use privilege thresholds to manage how much reputation a user must gain to receive moderator access.


    - Manage Thread

    - Moderate Users

    - Create Pinned Topics

    - + Manage Thread

    + Manage Content

    From 27f421587ec446f050db7602935096bde7970a9f Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Fri, 25 Oct 2013 09:57:02 -0400 Subject: [PATCH 19/21] closes #444 --- public/src/translator.js | 15 +++++++++++++++ src/favourites.js | 20 +++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/public/src/translator.js b/public/src/translator.js index 103ccb124f..237969f609 100644 --- a/public/src/translator.js +++ b/public/src/translator.js @@ -30,6 +30,7 @@ languageFile = parsedKey[0]; parsedKey = parsedKey[1]; + translator.load(languageFile, function (languageData) { if (callback) { callback(languageData[parsedKey]); @@ -39,6 +40,20 @@ }); }; + translator.mget = function (keys, callback) { + + var async = require('async'); + + function getKey(key, callback) { + translator.get(key, function(value) { + callback(null, value); + }); + } + + async.map(keys, getKey, callback); + } + + /* * TODO: Not fully converted to server side yet, ideally server should be able to parse whole templates on demand if necessary * fix: translator.load should determine if server side and immediately return appropriate language file. diff --git a/src/favourites.js b/src/favourites.js index d104654469..6e6bd40990 100644 --- a/src/favourites.js +++ b/src/favourites.js @@ -8,17 +8,15 @@ var RDB = require('./redis.js'), Favourites.favourite = function (pid, room_id, uid, socket) { if (uid === 0) { - var not_logged_in = { - message: translator.get('topic:favourites.not_logged_in.message'), - title: translator.get('topic:favourites.not_logged_in.title') - }; - - socket.emit('event:alert', { - alert_id: 'post_favourite', - title: not_logged_in.title, - message: not_logged_in.message, - type: 'danger', - timeout: 5000 + + translator.mget(['topic:favourites.not_logged_in.message', 'topic:favourites.not_logged_in.title'], function(err, results) { + socket.emit('event:alert', { + alert_id: 'post_favourite', + title: results[1], + message: results[0], + type: 'danger', + timeout: 5000 + }); }); return; } From 04ee1d137d8fcd41efbeb04f2a219cefe5d421fe Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Fri, 25 Oct 2013 11:05:06 -0400 Subject: [PATCH 20/21] fixed unread and recent new post/topic notifications --- public/src/forum/recent.js | 4 ++-- public/src/forum/unread.js | 4 ++-- public/templates/recent.tpl | 2 +- public/templates/unread.tpl | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/public/src/forum/recent.js b/public/src/forum/recent.js index 8186a69e59..50e53792a9 100644 --- a/public/src/forum/recent.js +++ b/public/src/forum/recent.js @@ -34,7 +34,7 @@ define(function() { }); $('#new-topics-alert').on('click', function() { - $(this).hide(); + $(this).addClass('hide'); }); socket.on('event:new_topic', function(data) { @@ -77,7 +77,7 @@ define(function() { text += ' Click here to reload.'; - $('#new-topics-alert').html(text).fadeIn('slow'); + $('#new-topics-alert').html(text).removeClass('hide').fadeIn('slow'); } Recent.onTopicsLoaded = function(topics) { diff --git a/public/src/forum/unread.js b/public/src/forum/unread.js index 329cfff3ff..13a940a91f 100644 --- a/public/src/forum/unread.js +++ b/public/src/forum/unread.js @@ -15,7 +15,7 @@ define(function() { newPostCount = 0; $('#new-topics-alert').on('click', function() { - $(this).hide(); + $(this).addClass('hide'); }); socket.on('event:new_topic', function(data) { @@ -44,7 +44,7 @@ define(function() { text += ' Click here to reload.'; - $('#new-topics-alert').html(text).fadeIn('slow'); + $('#new-topics-alert').html(text).removeClass('hide').fadeIn('slow'); } socket.on('event:new_post', function(data) { diff --git a/public/templates/recent.tpl b/public/templates/recent.tpl index 80c6904401..97a2c062dc 100644 --- a/public/templates/recent.tpl +++ b/public/templates/recent.tpl @@ -13,7 +13,7 @@
    -
    +
    diff --git a/public/templates/unread.tpl b/public/templates/unread.tpl index 6d1ec7dcca..0f3b92bb2a 100644 --- a/public/templates/unread.tpl +++ b/public/templates/unread.tpl @@ -5,16 +5,16 @@
    - -
    -
    -
    [[unread:no_unread_topics]]
    + +
    +
    +
      From a662330b1b0565efb115483909518b41da000546 Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Fri, 25 Oct 2013 12:08:50 -0400 Subject: [PATCH 21/21] fixed users page lists --- public/src/forum/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/forum/users.js b/public/src/forum/users.js index 8d57e1e5fc..da85fcc8ab 100644 --- a/public/src/forum/users.js +++ b/public/src/forum/users.js @@ -112,7 +112,7 @@ define(function() { } if (set) { - startLoading(set, $('#users-inner-container .registered-user').children().length); + startLoading(set, $('#users-inner-container').children('.registered-user').length); } }