diff --git a/.gitignore b/.gitignore index 478600f89f..c6ab6e2a8d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,7 @@ public/css/*.css *.swp Vagrantfile .vagrant -provision.sh \ No newline at end of file +provision.sh +*.komodoproject + +feeds/recent.rss diff --git a/README.md b/README.md index 2d3bab3918..fc4f0b468c 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ - # NodeBB **NodeBB** is a robust Node.js driven forum built on a redis database. It is powered by web sockets, and is compatible down to IE8. * [NodeBB Homepage](http://www.nodebb.org/ "NodeBB") * [Demo & Meta Discussion](http://try.nodebb.org) +* [Wiki Guides](https://github.com/designcreateplay/NodeBB/wiki) - includes setup for other platforms * [Join us on IRC](https://kiwiirc.com/client/irc.freenode.net/nodebb) - #nodebb on Freenode * [Follow on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter") * [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")  - + ## How can I follow along/contribute? @@ -65,4 +65,4 @@ NodeBB can also be started with helper programs, such as `supervisor` and `forev ## Upgrading NodeBB -Detailed upgrade instructions are listed in [Upgrading NodeBB](https://github.com/designcreateplay/NodeBB/wiki/Upgrading-NodeBB) \ No newline at end of file +Detailed upgrade instructions are listed in [Upgrading NodeBB](https://github.com/designcreateplay/NodeBB/wiki/Upgrading-NodeBB) diff --git a/app.js b/app.js index 2a4fb645ec..395416adf6 100644 --- a/app.js +++ b/app.js @@ -55,7 +55,7 @@ winston.info(''); - if (!nconf.get('help') && !nconf.get('setup') && !nconf.get('upgrade') && fs.existsSync(__dirname + '/config.json')) { + if (!nconf.get('help') && !nconf.get('setup') && !nconf.get('install') && !nconf.get('upgrade') && fs.existsSync(__dirname + '/config.json')) { // Load server-side configs nconf.file({ file: __dirname + '/config.json' @@ -64,6 +64,7 @@ nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/'); nconf.set('upload_url', nconf.get('url') + 'uploads/'); + nconf.set('base_dir', __dirname); winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.'); winston.info('NodeBB instance bound to: ' + ((nconf.get('bind_address') === "0.0.0.0" || !nconf.get('bind_address')) ? 'Any address (0.0.0.0)' : nconf.get('bind_address'))); @@ -88,32 +89,45 @@ websockets = require('./src/websockets.js'), posts = require('./src/posts.js'), plugins = require('./src/plugins'), // Don't remove this - plugins initializes itself - Notifications = require('./src/notifications'); + Notifications = require('./src/notifications'), + Upgrade = require('./src/upgrade'); - websockets.init(SocketIO); + Upgrade.check(function(schema_ok) { + if (schema_ok || nconf.get('check-schema') === false) { + websockets.init(SocketIO); - global.templates = {}; - global.translator = translator; + global.templates = {}; + global.translator = translator; - translator.loadServer(); - - var customTemplates = meta.config['theme:templates'] ? path.join(__dirname, 'node_modules', meta.config['theme:id'], meta.config['theme:templates']) : false; + translator.loadServer(); - // todo: replace below with read directory code, derp. - templates.init([ - 'header', 'footer', 'logout', 'outgoing', 'admin/header', 'admin/footer', 'admin/index', - 'emails/reset', 'emails/reset_plaintext', 'emails/email_confirm', 'emails/email_confirm_plaintext', - 'emails/header', 'emails/footer', + var customTemplates = meta.config['theme:templates'] ? path.join(__dirname, 'node_modules', meta.config['theme:id'], meta.config['theme:templates']) : false; - 'noscript/header', 'noscript/home', 'noscript/category', 'noscript/topic' - ], customTemplates); - + // todo: replace below with read directory code, derp. + templates.init([ + 'header', 'footer', 'logout', 'outgoing', 'admin/header', 'admin/footer', 'admin/index', + 'emails/reset', 'emails/reset_plaintext', 'emails/email_confirm', 'emails/email_confirm_plaintext', + 'emails/header', 'emails/footer', - templates.ready(webserver.init); + 'noscript/header', 'noscript/home', 'noscript/category', 'noscript/topic' + ], customTemplates); - Notifications.init(); + + plugins.ready(function() { + templates.ready(webserver.init); + }); + + Notifications.init(); + } else { + winston.warn('Your NodeBB schema is out-of-date. Please run the following command to bring your dataset up to spec:'); + winston.warn(' node app --upgrade'); + winston.warn('To ignore this error (not recommended):'); + winston.warn(' node app --no-check-schema') + process.exit(); + } + }); }); - } else if (nconf.get('setup') || !fs.existsSync(__dirname + '/config.json')) { + } else if (nconf.get('setup') || nconf.get('install') || !fs.existsSync(__dirname + '/config.json')) { // New install, ask setup questions if (nconf.get('setup')) { winston.info('NodeBB Setup Triggered via Command Line'); diff --git a/install/data/categories.json b/install/data/categories.json index 187ddcc3ff..43d394ab19 100644 --- a/install/data/categories.json +++ b/install/data/categories.json @@ -3,84 +3,84 @@ "name": "Announcements", "description": "Announcements regarding our community", "blockclass": "category-blue", - "icon" : "icon-bullhorn", + "icon" : "fa-bullhorn", "order": 1 }, { "name": "General Discussion", "description": "A place to talk about whateeeever you want", "blockclass": "category-blue", - "icon" : "icon-comment", + "icon" : "fa-comment", "order": 2 }, { "name": "NodeBB Development", "description": "NodeBB development news and announcements", "blockclass": "category-blue", - "icon" : "icon-github", + "icon" : "fa-github", "order": 3 }, { "name": "Blogs", "description": "Blog posts from individual members", "blockclass": "category-blue", - "icon" : "icon-pencil", + "icon" : "fa-pencil", "order": 4 }, { "name": "Feature Requests", "description": "Got a feature request you'd like to see? Give us a shout here.", "blockclass": "category-purple", - "icon" : "icon-lightbulb", + "icon" : "fa-lightbulb-o", "order": 5 }, { "name": "Bug Reports", "description": "Having trouble with NodeBB? Let us know...", "blockclass": "category-purple", - "icon" : "icon-cogs", + "icon" : "fa-cogs", "order": 6 }, { "name": "NodeBB Plugins", "description": "Enhance your NodeBB with plugins!", "blockclass": "category-purple", - "icon" : "icon-plus-sign", + "icon" : "fa-plus-square", "order": 7 }, { "name": "NodeBB Link Exchange", "description": "Link exchange", "blockclass": "category-purple", - "icon" : "icon-exchange", + "icon" : "fa-exchange", "order": 8 }, { "name": "News", "description": "News from around the world", "blockclass": "category-darkblue", - "icon" : "icon-globe", + "icon" : "fa-globe", "order": 9 }, { "name": "Movies", "description": "Discuss the latest movies here", "blockclass": "category-darkblue", - "icon" : "icon-film", + "icon" : "fa-film", "order": 10 }, { "name": "Games", "description": "Discuss the latest games here", "blockclass": "category-darkblue", - "icon" : "icon-screenshot", + "icon" : "fa-crosshairs", "order": 11 }, { "name": "Random", "description": "Anything and (almost) everything welcome!", "blockclass": "category-darkblue", - "icon" : "icon-beer", + "icon" : "fa-beer", "order": 12 } ] \ No newline at end of file diff --git a/nodebb b/nodebb index 3733935784..1b43292926 100755 --- a/nodebb +++ b/nodebb @@ -1,6 +1,6 @@ -#!/bin/bash +#!/bin/sh clear echo "Launching NodeBB in \"development\" mode." echo "To run the production build of NodeBB, please use \"forever\"." echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB" -NODE_ENV=development supervisor --extensions 'node|js|tpl' -- app $1 \ No newline at end of file +NODE_ENV=development supervisor --extensions 'node|js|tpl' -- app $1 diff --git a/package.json b/package.json index 1eeaf8e3f7..f7cd299f9c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "nodebb", "license": "GPLv3 or later", "description": "NodeBB Forum", - "version": "0.0.7", + "version": "0.1.1", "homepage": "http://www.nodebb.org", "repository": { "type": "git", @@ -28,7 +28,7 @@ "less-middleware": "0.1.12", "marked": "0.2.8", "bcrypt": "0.7.5", - "async": "0.2.8", + "async": "~0.2.8", "node-imagemagick": "0.1.8", "gravatar": "1.0.6", "nconf": "~0.6.7", @@ -43,7 +43,7 @@ "nodebb-plugin-mentions": "~0.1.14", "nodebb-plugin-markdown": "~0.1.8", "nodebb-theme-vanilla": "designcreateplay/nodebb-theme-vanilla", - "nodebb-theme-cerulean": "0.0.6", + "nodebb-theme-cerulean": "0.0.10", "cron": "~1.0.1" }, "optionalDependencies": { diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000000..5284e59838 Binary files /dev/null and b/public/logo.png differ diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index be38d66057..64c55691e2 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -1,5 +1,6 @@ -var ajaxify = {}; +"use strict"; +var ajaxify = {}; (function ($) { /*global app, templates, utils*/ @@ -23,8 +24,9 @@ var ajaxify = {}; window.onpopstate = function (event) { // "quiet": If set to true, will not call pushState - if (event !== null && event.state && event.state.url !== undefined) + if (event !== null && event.state && event.state.url !== undefined) { ajaxify.go(event.state.url, null, null, true); + } }; var pagination; @@ -32,10 +34,13 @@ var ajaxify = {}; 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'); - app.enter_room('global'); + app.enterRoom('global'); pagination = pagination || document.getElementById('pagination'); - if (pagination) pagination.parentNode.style.display = 'none'; + if (pagination) { + pagination.parentNode.style.display = 'none'; + } + window.onscroll = null; // end @@ -62,37 +67,55 @@ var ajaxify = {}; } if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) { - if (quiet !== true) { - if (window.history && window.history.pushState) { - window.history.pushState({ - "url": url - }, url, RELATIVE_PATH + "/" + url); - } + if (window.history && window.history.pushState) { + window.history[!quiet ? 'pushState' : 'replaceState']({ + url: url + }, url, RELATIVE_PATH + '/' + url); + + $.ajax(RELATIVE_PATH + '/plugins/fireHook', { + type: 'PUT', + data: { + _csrf: $('#csrf_token').val(), + hook: 'page.load', + args: { + template: tpl_url, + url: url, + uid: app.uid + } + } + }); } translator.load(tpl_url); - jQuery('#footer, #content').fadeOut(100); + jQuery('#footer, #content').addClass('ajaxifying'); templates.flush(); templates.load_template(function () { exec_body_scripts(content); require(['forum/' + tpl_url], function(script) { - if (script && script.init) script.init(); + if (script && script.init) { + script.init(); + } }); if (callback) { callback(); } - app.process_page(); + app.processPage(); - jQuery('#content, #footer').stop(true, true).fadeIn(200, function () { - if (window.location.hash) - hash = window.location.hash; - if (hash) - app.scrollToPost(hash.substr(1)); - }); + jQuery('#content, #footer').stop(true, true).removeClass('ajaxifying'); + + if (window.location.hash) { + hash = window.location.hash; + } + + if (hash) { + require(['forum/topic'], function(topic) { + topic.scrollToPost(hash.substr(1)); + }); + } utils.refreshTitle(url); @@ -105,23 +128,27 @@ var ajaxify = {}; }; $('document').ready(function () { - if (!window.history || !window.history.pushState) return; // no ajaxification for old browsers + if (!window.history || !window.history.pushState) { + return; // no ajaxification for old browsers + } content = content || document.getElementById('content'); // Enhancing all anchors to ajaxify... $(document.body).on('click', 'a', function (e) { function hrefEmpty(href) { - return href == 'javascript:;' || href == window.location.href + "#" || href.slice(-1) === "#"; + return href === 'javascript:;' || href === window.location.href + "#" || href.slice(-1) === "#"; } - if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:') + if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:') { return; + } - if(!window.location.pathname.match(/\/(403|404)$/g)) + if(!window.location.pathname.match(/\/(403|404)$/g)) { app.previousUrl = window.location.href; + } - if (this.getAttribute('data-ajaxify') == 'false') { + if (this.getAttribute('data-ajaxify') === 'false') { return; } diff --git a/public/src/app.js b/public/src/app.js index 026c66496c..8f6d8ed433 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -47,7 +47,7 @@ var socket, socket.on('connect', function (data) { if (reconnecting) { - reconnectEl.html(' Connected!'); + reconnectEl.html(' Connected!'); reconnecting = false; setTimeout(function() { @@ -75,7 +75,7 @@ var socket, reconnecting = true; reconnectEl.addClass('active'); - reconnectEl.html(' Reconnecting...'); + reconnectEl.html(' Reconnecting...'); }); socket.on('api:user.get_online_users', function (users) { @@ -88,10 +88,10 @@ var socket, if (uid && jQuery.inArray(uid, users) !== -1) { el.find('i').remove(); - el.prepend(''); + el.prepend(''); } else { el.find('i').remove(); - el.prepend(''); + el.prepend(''); } el.processed = true; @@ -125,7 +125,7 @@ var socket, setTimeout(app.logout, 1000); }); - app.enter_room('global'); + app.enterRoom('global'); } }, async: false @@ -136,7 +136,7 @@ var socket, $.post(RELATIVE_PATH + '/logout', { _csrf: $('#csrf_token').val() }, function() { - window.location = RELATIVE_PATH + '/'; + window.location.href = RELATIVE_PATH + '/'; }); } @@ -186,43 +186,35 @@ var socket, clearTimeout(alert.attr('timeoutId')); startTimeout(alert, params.timeout); } else { - var div = document.createElement('div'), - button = document.createElement('button'), - strong = document.createElement('strong'), - p = document.createElement('p'); + var div = $('
'), + button = $(''), + strong = $('' + title + ''), + p = $('' + params.message + '
'); - p.innerHTML = params.message; - strong.innerHTML = title; + div.append(button) + .append(strong) + .append(p); - div.className = "alert toaster-alert " + "alert-" + params.type; - - div.setAttribute('id', alert_id); - div.appendChild(button); - div.appendChild(strong); - div.appendChild(p); - - button.className = 'close'; - button.innerHTML = '×'; - button.onclick = function (ev) { - div.parentNode.removeChild(div); - } + button.on('click', function () { + div.remove(); + }); if (params.location == null) params.location = 'alert_window'; - jQuery('#' + params.location).prepend(jQuery(div).fadeIn('100')); + $('#' + params.location).prepend(div.fadeIn('100')); if (params.timeout) { startTimeout(div, params.timeout); } if (params.clickfn) { - div.onclick = function () { + div.on('click', function () { params.clickfn(); - jQuery(div).fadeOut(500, function () { - this.remove(); + div.fadeOut(500, function () { + $(this).remove(); }); - } + }); } } } @@ -251,22 +243,23 @@ var socket, }); } - app.current_room = null; - app.enter_room = function (room) { + app.currentRoom = null; + app.enterRoom = function (room) { if (socket) { - if (app.current_room === room) + if (app.currentRoom === room) { return; + } socket.emit('event:enter_room', { 'enter': room, - 'leave': app.current_room + 'leave': app.currentRoom }); - app.current_room = room; + app.currentRoom = room; } }; - app.populate_online_users = function () { + app.populateOnlineUsers = function () { var uids = []; jQuery('.post-row').each(function () { @@ -276,11 +269,9 @@ var socket, socket.emit('api:user.get_online_users', uids); } - app.process_page = function () { - app.populate_online_users(); - - var url = window.location.href, - parts = url.split('/'), + function highlightNavigationLink() { + var path = window.location.pathname, + parts = path.split('/'), active = parts[parts.length - 1]; jQuery('#main-nav li').removeClass('active'); @@ -295,10 +286,27 @@ var socket, } }); } + } + + app.createUserTooltips = function() { + $('img[title].teaser-pic,img[title].user-img').each(function() { + $(this).tooltip({ + placement: 'top', + title: $(this).attr('title') + }); + }); + } + + app.processPage = function () { + app.populateOnlineUsers(); + + highlightNavigationLink(); $('span.timeago').timeago(); $('.post-content img').addClass('img-responsive'); + app.createUserTooltips(); + setTimeout(function () { window.scrollTo(0, 1); // rehide address bar on mobile after page load completes. }, 100); @@ -331,6 +339,28 @@ var socket, } app.openChat = function (username, touid) { + if (username === app.username) { + app.alert({ + type: 'warning', + title: 'Invalid Chat', + message: "You can't chat with yourself!", + timeout: 5000 + }); + + return; + } + + if (!app.username) { + app.alert({ + type: 'danger', + title: 'Not Logged In', + message: 'Please log in to chat with ' + username + '', + timeout: 5000 + }); + + return; + } + require(['chat'], function (chat) { var chatModal; if (!chat.modalExists(touid)) { @@ -343,61 +373,6 @@ var socket, }); } - app.createNewPosts = function (data) { - if (data.posts[0].uid !== app.uid) { - data.posts[0].display_moderator_tools = 'none'; - } - - var html = templates.prepare(templates['topic'].blocks['posts']).parse(data); - translator.translate(html, function(translatedHTML) { - var uniqueid = new Date().getTime(), - tempContainer = jQuery('') - .appendTo("#post-container") - .hide() - .append(translatedHTML) - .fadeIn('slow'); - - for (var x = 0, numPosts = data.posts.length; x < numPosts; x++) { - socket.emit('api:post.privileges', data.posts[x].pid); - } - - tempContainer.replaceWith(tempContainer.contents()); - infiniteLoaderActive = false; - - app.populate_online_users(); - app.addCommasToNumbers(); - $('span.timeago').timeago(); - $('.post-content img').addClass('img-responsive'); - }); - } - - app.infiniteLoaderActive = false; - - app.loadMorePosts = function (tid, callback) { - if (app.infiniteLoaderActive) - return; - app.infiniteLoaderActive = true; - - if ($('#loading-indicator').attr('done') === '0') - $('#loading-indicator').removeClass('hide'); - - socket.emit('api:topic.loadMore', { - tid: tid, - after: document.querySelectorAll('#post-container li[data-pid]').length - }, function (data) { - app.infiniteLoaderActive = false; - if (data.posts.length) { - $('#loading-indicator').attr('done', '0'); - app.createNewPosts(data); - } else { - $('#loading-indicator').attr('done', '1'); - } - $('#loading-indicator').addClass('hide'); - if (callback) - callback(data.posts); - }); - } - app.scrollToTop = function () { $('body,html').animate({ scrollTop: 0 @@ -410,43 +385,6 @@ var socket, }); } - app.scrollToPost = function (pid) { - - if (!pid) - return; - - var container = $(document.body), - scrollTo = $('#post_anchor_' + pid), - tid = $('#post-container').attr('data-tid'); - - function animateScroll() { - $('body,html').animate({ - scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height() - }, 400); - //$('body,html').scrollTop(scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()); - } - - if (!scrollTo.length && tid) { - - var intervalID = setInterval(function () { - app.loadMorePosts(tid, function (posts) { - scrollTo = $('#post_anchor_' + pid); - - if (tid && scrollTo.length) { - animateScroll(); - } - - if (!posts.length || scrollTo.length) - clearInterval(intervalID); - }); - }, 100); - - } else if (tid) { - animateScroll(); - } - - } - jQuery('document').ready(function () { $('#search-form').on('submit', function () { var input = $(this).find('input'); diff --git a/public/src/forum/account.js b/public/src/forum/account.js index 82be082aeb..5056c2a26e 100644 --- a/public/src/forum/account.js +++ b/public/src/forum/account.js @@ -10,9 +10,10 @@ define(['forum/accountheader'], function(header) { $(document).ready(function() { var username = $('.account-username a').html(); - app.enter_room('user/' + theirid); + app.enterRoom('user/' + theirid); app.addCommasToNumbers(); + $('.user-recent-posts img').addClass('img-responsive'); var followBtn = $('#follow-btn'); var unfollowBtn = $('#unfollow-btn'); @@ -71,6 +72,7 @@ define(['forum/accountheader'], function(header) { socket.on('event:new_post', function(data) { var html = templates.prepare(templates['account'].blocks['posts']).parse(data); $('.user-recent-posts').prepend(html); + $('.user-recent-posts span.timeago').timeago(); }); }); @@ -81,10 +83,10 @@ define(['forum/accountheader'], function(header) { if (data.online) { onlineStatus.find('span span').text('online'); - onlineStatus.find('i').attr('class', 'icon-circle'); + onlineStatus.find('i').attr('class', 'fa fa-circle'); } else { onlineStatus.find('span span').text('offline'); - onlineStatus.find('i').attr('class', 'icon-circle-blank'); + onlineStatus.find('i').attr('class', 'fa fa-circle-o'); } }; diff --git a/public/src/forum/accountedit.js b/public/src/forum/accountedit.js index 530261c77d..912bb29b37 100644 --- a/public/src/forum/accountedit.js +++ b/public/src/forum/accountedit.js @@ -1,11 +1,13 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) { - var AccountEdit = {}; + var AccountEdit = {}, + gravatarPicture = '', + uploadedPicture = ''; AccountEdit.init = function() { header.init(); - var gravatarPicture = templates.get('gravatarpicture'); - var uploadedPicture = templates.get('uploadedpicture'); + gravatarPicture = templates.get('gravatarpicture'); + uploadedPicture = templates.get('uploadedpicture'); var selectedImageType = ''; @@ -50,14 +52,14 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) { }); $('#gravatar-box').on('click', function() { - $('#gravatar-box .icon-ok').show(); - $('#uploaded-box .icon-ok').hide(); + $('#gravatar-box .fa-check').show(); + $('#uploaded-box .fa-check').hide(); selectedImageType = 'gravatar'; }); $('#uploaded-box').on('click', function() { - $('#gravatar-box .icon-ok').hide(); - $('#uploaded-box .icon-ok').show(); + $('#gravatar-box .fa-check').hide(); + $('#uploaded-box .fa-check').show(); selectedImageType = 'uploaded'; }); @@ -194,31 +196,33 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) { AccountEdit.updateImages = function() { var currentPicture = $('#user-current-picture').attr('src'); - var gravatarPicture = templates.get('gravatarpicture'); - var uploadedPicture = templates.get('uploadedpicture'); if (gravatarPicture) { $('#user-gravatar-picture').attr('src', gravatarPicture); $('#gravatar-box').show(); - } else + } else { $('#gravatar-box').hide(); + } if (uploadedPicture) { $('#user-uploaded-picture').attr('src', uploadedPicture); $('#uploaded-box').show(); - } else + } else { $('#uploaded-box').hide(); + } - if (currentPicture == gravatarPicture) - $('#gravatar-box .icon-ok').show(); - else - $('#gravatar-box .icon-ok').hide(); + if (currentPicture == gravatarPicture) { + $('#gravatar-box .fa-check').show(); + } else { + $('#gravatar-box .fa-check').hide(); + } - if (currentPicture == uploadedPicture) - $('#uploaded-box .icon-ok').show(); - else - $('#uploaded-box .icon-ok').hide(); + if (currentPicture == uploadedPicture) { + $('#uploaded-box .fa-check').show(); + } else { + $('#uploaded-box .fa-check').hide(); + } } return AccountEdit; diff --git a/public/src/forum/admin/categories.js b/public/src/forum/admin/categories.js index ce3f716312..c848378f75 100644 --- a/public/src/forum/admin/categories.js +++ b/public/src/forum/admin/categories.js @@ -18,7 +18,7 @@ define(function() { } function select_icon(el) { - var selected = el.attr('class').replace(' icon-2x', ''); + var selected = el.attr('class').replace(' fa-2x', ''); jQuery('#icons .selected').removeClass('selected'); if (selected) jQuery('#icons .' + selected).parent().addClass('selected'); @@ -27,9 +27,13 @@ define(function() { bootbox.confirm('' + @@ -69,6 +68,7 @@ define(function () { recent_replies.appendChild(frag); } $('#category_recent_replies span.timeago').timeago(); + app.createUserTooltips(); }); $(window).off('scroll').on('scroll', function (ev) { @@ -94,17 +94,20 @@ define(function () { if (numTopics > 0) { for (var x = 0; x < numTopics; x++) { - if ($(topics[x]).find('.icon-pushpin').length) + if ($(topics[x]).find('.fa-thumb-tack').length) { + if(x === numTopics - 1) { + topic.insertAfter(topics[x]); + } continue; + } topic.insertBefore(topics[x]); - topic.hide().fadeIn('slow'); break; } } else { container.append(topic); - topic.hide().fadeIn('slow'); } + topic.hide().fadeIn('slow'); socket.emit('api:categories.getRecentReplies', templates.get('category_id')); addActiveUser(data); @@ -144,6 +147,10 @@ define(function () { Category.loadMoreTopics = function(cid) { + if (loadingMoreTopics) { + return; + } + loadingMoreTopics = true; socket.emit('api:category.loadMore', { cid: cid, diff --git a/public/src/forum/footer.js b/public/src/forum/footer.js index df9c52ac6f..22aaf69768 100644 --- a/public/src/forum/footer.js +++ b/public/src/forum/footer.js @@ -105,11 +105,14 @@ notifList.appendChild(notifFrag); - if (data.unread.length > 0) notifIcon.className = 'icon-circle active'; - else notifIcon.className = 'icon-circle-blank'; + if (data.unread.length > 0) { + notifIcon.className = 'fa fa-circle active'; + } else { + notifIcon.className = 'fa fa-circle-o'; + } socket.emit('api:notifications.mark_all_read', null, function() { - notifIcon.className = 'icon-circle-blank'; + notifIcon.className = 'fa fa-circle-o'; utils.refreshTitle(); }); }); @@ -136,7 +139,7 @@ }); socket.on('event:new_notification', function() { - document.querySelector('.notifications a i').className = 'icon-circle active'; + document.querySelector('.notifications a i').className = 'fa fa-circle active'; app.alert({ alert_id: 'new_notif', title: 'New notification', diff --git a/public/src/forum/login.js b/public/src/forum/login.js index 96e6c49e94..a414f39e4e 100644 --- a/public/src/forum/login.js +++ b/public/src/forum/login.js @@ -26,17 +26,23 @@ define(function() { '_csrf': $('#csrf-token').val() }; + $('#login').attr('disabled', 'disabled').html('Logging in...'); + $('#login-error-notify').hide(); + $.ajax({ type: "POST", url: RELATIVE_PATH + '/login', data: loginData, success: function(data, textStatus, jqXHR) { + if (!data.success) { $('#login-error-notify').show(); + $('#login').removeAttr('disabled').html('Login'); } else { - $('#login-error-notify').hide(); - - if(!app.previousUrl) { app.previousUrl = '/'; } + $('#login').html('Redirecting...'); + if(!app.previousUrl) { + app.previousUrl = '/'; + } if(app.previousUrl.indexOf('/reset/') != -1) window.location.replace(RELATIVE_PATH + "/?loggedin"); @@ -48,6 +54,7 @@ define(function() { }, error: function(data, textStatus, jqXHR) { $('#login-error-notify').show(); + $('#login').removeAttr('disabled').html('Login'); }, dataType: 'json', async: true, @@ -63,6 +70,12 @@ define(function() { }); document.querySelector('#content input').focus(); + + if(!config.emailSetup) + $('#reset-link').addClass('hide'); + else + $('#reset-link').removeClass('hide'); + }; return Login; diff --git a/public/src/forum/recent.js b/public/src/forum/recent.js index 50e53792a9..934a3e248b 100644 --- a/public/src/forum/recent.js +++ b/public/src/forum/recent.js @@ -8,7 +8,7 @@ define(function() { var active = ''; Recent.init = function() { - app.enter_room('recent_posts'); + app.enterRoom('recent_posts'); ajaxify.register_events([ 'event:new_topic', diff --git a/public/src/forum/register.js b/public/src/forum/register.js index 6270f0c14c..fb1959f5c5 100644 --- a/public/src/forum/register.js +++ b/public/src/forum/register.js @@ -12,7 +12,7 @@ define(function() { password_notify = $('#password-notify'), password_confirm_notify = $('#password-confirm-notify'), validationError = false, - successIcon = ''; + successIcon = ''; $('#referrer').val(app.previousUrl); @@ -151,7 +151,9 @@ define(function() { } register.on('click', function(e) { - if (validateForm()) e.preventDefault(); + if (validateForm()) { + e.preventDefault(); + } }); }; diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index a55be43a53..0f3439aa81 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -1,5 +1,7 @@ define(function() { - var Topic = {}; + var Topic = {}, + infiniteLoaderActive = false; + Topic.init = function() { var expose_tools = templates.get('expose_tools'), @@ -17,16 +19,26 @@ define(function() { google_url = templates.get('google-share-url'); + function fixDeleteStateForPosts() { + var postEls = document.querySelectorAll('#post-container li[data-deleted]'); + for (var x = 0, numPosts = postEls.length; x < numPosts; x++) { + if (postEls[x].getAttribute('data-deleted') === '1') { + toggle_post_delete_state(postEls[x].getAttribute('data-pid')); + } + postEls[x].removeAttribute('data-deleted'); + } + } + + jQuery('document').ready(function() { app.addCommasToNumbers(); + app.enterRoom('topic_' + tid); - var room = 'topic_' + tid, - adminTools = document.getElementById('thread-tools'); - - app.enter_room(room); - + if($('#post-container .posts .post-row').length > 1) { + $('.topic-main-buttons').removeClass('hide').parent().removeClass('hide'); + } $('.twitter-share').on('click', function () { window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no'); @@ -50,11 +62,10 @@ define(function() { if (expose_tools === '1') { var moveThreadModal = $('#move_thread_modal'); - - adminTools.style.visibility = 'inherit'; + $('.thread-tools').removeClass('hide'); // Add events to the thread tools - $('#delete_thread').on('click', function(e) { + $('.delete_thread').on('click', function(e) { if (thread_state.deleted !== '1') { bootbox.confirm('Are you sure you want to delete this thread?', function(confirm) { if (confirm) { @@ -73,7 +84,7 @@ define(function() { return false; }); - $('#lock_thread').on('click', function(e) { + $('.lock_thread').on('click', function(e) { if (thread_state.locked !== '1') { socket.emit('api:topic.lock', { tid: tid @@ -86,7 +97,7 @@ define(function() { return false; }); - $('#pin_thread').on('click', function(e) { + $('.pin_thread').on('click', function(e) { if (thread_state.pinned !== '1') { socket.emit('api:topic.pin', { tid: tid @@ -99,7 +110,7 @@ define(function() { return false; }); - $('#move_thread').on('click', function(e) { + $('.move_thread').on('click', function(e) { moveThreadModal.modal('show'); return false; }); @@ -109,7 +120,6 @@ define(function() { var loadingEl = document.getElementById('categories-loading'); if (loadingEl) { socket.once('api:categories.get', function(data) { - console.log(data); // Render categories var categoriesFrag = document.createDocumentFragment(), categoryEl = document.createElement('li'), @@ -125,8 +135,10 @@ define(function() { categoriesEl.className = 'category-list'; for (x = 0; x < numCategories; x++) { info = data.categories[x]; - categoryEl.className = info.blockclass + (info.disabled === '1' ? ' disabled' : ''); - categoryEl.innerHTML = ' ' + info.name; + categoryEl.style.background = info.bgColor; + categoryEl.style.color = info.color || '#fff'; + categoryEl.className = info.disabled === '1' ? ' disabled' : ''; + categoryEl.innerHTML = ' ' + info.name; categoryEl.setAttribute('data-cid', info.cid); categoriesFrag.appendChild(categoryEl.cloneNode(true)); } @@ -148,7 +160,7 @@ define(function() { commitEl.disabled = true; $(cancelEl).fadeOut(250); $(moveThreadModal).find('.modal-header button').fadeOut(250); - commitEl.innerHTML = 'Moving '; + commitEl.innerHTML = 'Moving '; socket.once('api:topic.move', function(data) { moveThreadModal.modal('hide'); @@ -182,15 +194,11 @@ define(function() { }); } - // Fix delete state for this thread's posts - var postEls = document.querySelectorAll('#post-container li[data-deleted]'); - for (var x = 0, numPosts = postEls.length; x < numPosts; x++) { - if (postEls[x].getAttribute('data-deleted') === '1') toggle_post_delete_state(postEls[x].getAttribute('data-pid')); - postEls[x].removeAttribute('data-deleted'); - } + fixDeleteStateForPosts(); + // Follow Thread State - var followEl = $('.main-post .follow'), + var followEl = $('.posts .follow'), set_follow_state = function(state, quiet) { if (state && !followEl.hasClass('btn-success')) { followEl.addClass('btn-success'); @@ -246,7 +254,7 @@ define(function() { var bookmark = localStorage.getItem('topic:' + tid + ':bookmark'); if(bookmark) { - app.scrollToPost(parseInt(bookmark, 10)); + Topic.scrollToPost(parseInt(bookmark, 10)); } $('#post-container').on('click', '.deleted', function(ev) { @@ -258,13 +266,15 @@ define(function() { $(window).off('scroll').on('scroll', function() { var bottom = ($(document).height() - $(window).height()) * 0.9; - if ($(window).scrollTop() > bottom && !app.infiniteLoaderActive && $('#post-container').children().length) { - app.loadMorePosts(tid); + if ($(window).scrollTop() > bottom && !infiniteLoaderActive && $('#post-container').children().length) { + loadMorePosts(tid, function(posts) { + fixDeleteStateForPosts(); + }); } }); } - var reply_fn = function() { + $('.topic').on('click', '.post_reply', function() { var selectionText = '', selection = window.getSelection() || document.getSelection(); @@ -278,9 +288,7 @@ define(function() { cmp.push(tid, null, null, selectionText.length > 0 ? selectionText + '\n\n' : ''); }); } - }; - $('#post-container').on('click', '.post_reply', reply_fn); - $('#post_reply').on('click', reply_fn); + }); $('#post-container').on('click', '.quote', function() { if (thread_state.locked !== '1') { @@ -304,15 +312,15 @@ define(function() { var uid = $(this).parents('li').attr('data-uid'); var element = $(this).find('i'); - if (element.attr('class') == 'icon-star-empty') { + if ($(element).hasClass('fa-star-o')) { socket.emit('api:posts.favourite', { pid: pid, - room_id: app.current_room + room_id: app.currentRoom }); } else { socket.emit('api:posts.unfavourite', { pid: pid, - room_id: app.current_room + room_id: app.currentRoom }); } }); @@ -327,7 +335,7 @@ define(function() { $('#post-container').delegate('.edit', 'click', function(e) { var pid = $(this).parents('li').attr('data-pid'), - main = $(this).parents('.main-post'); + main = $(this).parents('.posts'); require(['composer'], function(cmp) { cmp.push(null, null, pid); @@ -341,13 +349,25 @@ define(function() { confirmDel = confirm((deleteAction ? 'Delete' : 'Restore') + ' this post?'); if (confirmDel) { - deleteAction ? + if(deleteAction) { socket.emit('api:posts.delete', { - pid: pid - }) : - socket.emit('api:posts.restore', { - pid: pid + pid: pid, + tid: tid + }, function(err) { + if(err) { + return app.alertError('Can\'t delete post!'); + } }); + } else { + socket.emit('api:posts.restore', { + pid: pid, + tid: tid + }, function(err) { + if(err) { + return app.alertError('Can\'t restore post!'); + } + }); + } } }); @@ -355,9 +375,6 @@ define(function() { var username = $(this).parents('li.row').attr('data-username'); var touid = $(this).parents('li.row').attr('data-uid'); - if (username === app.username || !app.username) - return; - app.openChat(username, touid); }); @@ -381,12 +398,15 @@ define(function() { var userLink = $('').append(userIcon); userLink.attr('data-uid', uid); + var div = $('
'); + div.append(userLink); + userLink.tooltip({ - placement: 'left', + placement: 'top', title: username }); - return userLink; + return div; } } @@ -428,7 +448,7 @@ define(function() { activeEl.find('.anonymous-box').remove(); if(anonymousCount || remainingUsers) { - var anonLink = $(''); + var anonLink = $('