From 8f972d8cdc38a3691d685eba084d540d48d68183 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 11:38:31 -0500 Subject: [PATCH 01/46] added widgets tab to themes acp --- public/templates/admin/themes.tpl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index 331d85f6e8..7f867eff1c 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -5,6 +5,7 @@
@@ -49,6 +50,9 @@
+
+

Widgets

+
From fa5f528fb5c3620a34d3fb23b576586344227b49 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 11:43:25 -0500 Subject: [PATCH 02/46] filter:widgets.getAreas - allows plugins to define widget locations in tpls --- src/routes/admin.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/routes/admin.js b/src/routes/admin.js index c0afc39b4b..e5d5a48f57 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -410,7 +410,11 @@ var nconf = require('nconf'), }); app.get('/themes', function (req, res) { - res.json(200, {}); + plugins.fireHook('filter:widgets.getAreas', [], function(err, widgets) { + res.json(200, { + widgets: widgets + }); + }); }); app.get('/testing/categories', function (req, res) { From 447cff1995995c4988a975ec91537b17871ffceb Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 12:46:55 -0500 Subject: [PATCH 03/46] got the basic ui, dragging, sorting etc going for widgets acp --- public/src/forum/admin/themes.js | 24 +++++++++++++++++++ public/templates/admin/themes.tpl | 40 +++++++++++++++++++++++++++++-- src/routes/admin.js | 4 ++-- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index 699796e36b..b608ae8646 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -102,6 +102,8 @@ define(['forum/admin/settings'], function(Settings) { tabIndent.config.tab = ' '; tabIndent.render(customCSSEl); + Themes.prepareWidgets(); + Settings.prepare(); } @@ -132,5 +134,27 @@ define(['forum/admin/settings'], function(Settings) { themeContainer.appendChild(themeFrag); } + Themes.prepareWidgets = function() { + $('#widgets .panel').draggable({ + helper: function(e) { + return $(e.target).parents('.panel').clone().addClass('block').width($(e.target.parentNode).width()); + }, + connectToSortable: ".widget-area" + }); + + $('#widgets .widget-area').sortable({ + update: function (event, ui) { + if (!ui.item.hasClass('block')) { + ui.item.addClass('block'); + ui.item.children('.panel-heading').append('
'); + } + + } + }).on('click', '.toggle-widget', function() { + $(this).parents('.panel').children('.panel-body').toggleClass('hidden'); + }); + + }; + return Themes; }); \ No newline at end of file diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index 7f867eff1c..ebd3816fc0 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -9,7 +9,7 @@
-
+

Installed Themes

The following themes are currently installed in this NodeBB instance. @@ -50,8 +50,44 @@

-
+

Widgets

+ +
+
+

Available Widgets

+
+
+
+ HTML Any text, html, or embedded script. +
+ +
+
+
+ Markdown Markdown formatted text +
+ +
+ + + +
+
+ +
+ +

{areas.name}

+
+ +
+ +
+
diff --git a/src/routes/admin.js b/src/routes/admin.js index e5d5a48f57..ceb2074d06 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -410,9 +410,9 @@ var nconf = require('nconf'), }); app.get('/themes', function (req, res) { - plugins.fireHook('filter:widgets.getAreas', [], function(err, widgets) { + plugins.fireHook('filter:widgets.getAreas', [], function(err, areas) { res.json(200, { - widgets: widgets + areas: areas }); }); }); From 9f8f78f6d44d9fdfea9162762745c3d187e81d47 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 13:22:02 -0500 Subject: [PATCH 04/46] client-side saving of widgets --- public/src/forum/admin/themes.js | 28 ++++++++++++++++++++++++++++ public/templates/admin/themes.tpl | 18 ++++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index b608ae8646..1cf7e3a36f 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -153,6 +153,34 @@ define(['forum/admin/settings'], function(Settings) { }).on('click', '.toggle-widget', function() { $(this).parents('.panel').children('.panel-body').toggleClass('hidden'); }); + + $('#widgets .btn[data-template]').on('click', function() { + var btn = $(this), + template = btn.attr('data-template'), + location = btn.attr('data-location'), + area = btn.parents('.area').children('.widget-area'), + widgets = []; + + area.find('.panel[data-widget]').each(function() { + var widget = {}; + widget[this.getAttribute('data-widget')] = $(this).find('form').serializeArray(); + widgets.push(widget); + }); + + socket.emit('admin.themes.widgets.set', { + template: template, + location: location, + widgets: widgets + }, function(err) { + app.alert({ + alert_id: 'admin:widgets', + type: err ? 'danger' : 'success', + title: err ? 'Error' : 'Widgets Updated', + message: err ? err : 'Successfully updated widgets', + timeout: 2500 + }); + }); + }); }; diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index ebd3816fc0..255a3d76fa 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -57,20 +57,24 @@

Available Widgets

-
+
HTML Any text, html, or embedded script.
-
+
Markdown Markdown formatted text
@@ -81,9 +85,11 @@
-

{areas.name}

-
+
+

{areas.name} {areas.template} / {areas.location}

+
+
From 86a8103c152ab7bc5c2f6eb77dccc57067274420 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 15:07:38 -0500 Subject: [PATCH 05/46] saving, updating, deleting widgets; widget dragging improvements --- public/src/forum/admin/themes.js | 84 +++++++++++++++++++++++++++---- public/templates/admin/themes.tpl | 12 +++-- src/routes/admin.js | 14 +++++- src/socket.io/admin.js | 14 +++++- src/widgets.js | 26 ++++++++++ 5 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 src/widgets.js diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index 1cf7e3a36f..eedbc58fa4 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -142,16 +142,29 @@ define(['forum/admin/settings'], function(Settings) { connectToSortable: ".widget-area" }); + function appendToggle(el) { + if (!el.hasClass('block')) { + el.addClass('block') + .children('.panel-heading') + .append('
 
'); + } + } + $('#widgets .widget-area').sortable({ update: function (event, ui) { - if (!ui.item.hasClass('block')) { - ui.item.addClass('block'); - ui.item.children('.panel-heading').append('
'); - } - - } + appendToggle(ui.item); + }, + connectWith: "div" }).on('click', '.toggle-widget', function() { $(this).parents('.panel').children('.panel-body').toggleClass('hidden'); + }).on('click', '.delete-widget', function() { + var panel = $(this).parents('.panel'); + + bootbox.confirm('Are you sure you wish to delete this widget?', function(confirm) { + if (confirm) { + panel.remove(); + } + }); }); $('#widgets .btn[data-template]').on('click', function() { @@ -162,12 +175,24 @@ define(['forum/admin/settings'], function(Settings) { widgets = []; area.find('.panel[data-widget]').each(function() { - var widget = {}; - widget[this.getAttribute('data-widget')] = $(this).find('form').serializeArray(); - widgets.push(widget); + var widgetData = {}, + data = $(this).find('form').serializeArray(); + + for (var d in data) { + if (data.hasOwnProperty(d)) { + if (data[d].name) { + widgetData[data[d].name] = data[d].value; + } + } + } + + widgets.push({ + widget: this.getAttribute('data-widget'), + data: widgetData + }); }); - socket.emit('admin.themes.widgets.set', { + socket.emit('admin.widgets.set', { template: template, location: location, widgets: widgets @@ -181,7 +206,46 @@ define(['forum/admin/settings'], function(Settings) { }); }); }); + + function populateWidget(widget, data) { + widget.find('input, textarea').each(function() { + var input = $(this), + value = data[input.attr('name')]; + + if (this.type === 'checkbox') { + input.attr('checked', !!value); + } else { + input.val(value); + } + }); + + return widget; + } + $.get(RELATIVE_PATH + '/api/admin/themes', function(data) { + var areas = data.areas; + + for (var a in areas) { + if (areas.hasOwnProperty(a)) { + var area = areas[a], + widgetArea = $('#widgets .area [data-template="' + area.template + '"][data-location="' + area.location + '"]').parents('.area').find('.widget-area'); + + console.log('data', area.data); + for (var i in area.data) { + if (area.data.hasOwnProperty(i)) { + var data = area.data[i], + widgetEl = $('.available-widgets [data-widget="' + data.widget + '"]').clone(); + + + widgetArea.append(populateWidget(widgetEl, data.data)); + appendToggle(widgetEl); + } + } + + + } + } + }); }; return Themes; diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index 255a3d76fa..b33e7796fd 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -54,7 +54,7 @@

Widgets

-
+

Available Widgets

@@ -67,13 +67,17 @@
-
+
- Markdown Markdown formatted text + Text Markdown formatted text
diff --git a/src/routes/admin.js b/src/routes/admin.js index ceb2074d06..fa60980dcf 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -2,6 +2,7 @@ var nconf = require('nconf'), fs = require('fs'), path = require('path'), winston = require('winston'), + async = require('async'), db = require('./../database'), user = require('./../user'), @@ -11,6 +12,7 @@ var nconf = require('nconf'), categories = require('./../categories'), meta = require('../meta'), plugins = require('../plugins'), + widgets = require('../widgets'), image = require('./../image'), file = require('./../file'), Languages = require('../languages'), @@ -411,9 +413,17 @@ var nconf = require('nconf'), app.get('/themes', function (req, res) { plugins.fireHook('filter:widgets.getAreas', [], function(err, areas) { - res.json(200, { - areas: areas + async.each(areas, function(area, next) { + widgets.getArea(area.template, area.location, function(err, areaData) { + area.data = areaData; + next(err); + }); + }, function(err) { + res.json(200, { + areas: areas, + }); }); + }); }); diff --git a/src/socket.io/admin.js b/src/socket.io/admin.js index da1de17596..21f3d8bf11 100644 --- a/src/socket.io/admin.js +++ b/src/socket.io/admin.js @@ -3,6 +3,7 @@ var groups = require('../groups'), meta = require('../meta'), plugins = require('../plugins'), + widgets = require('../widgets'), user = require('../user'), topics = require('../topics'), categories = require('../categories'), @@ -255,10 +256,11 @@ SocketAdmin.categories.groupsList = function(socket, cid, callback) { }); }; -/* Themes & Plugins */ +/* Themes, Widgets, and Plugins */ SocketAdmin.themes = {}; SocketAdmin.plugins = {}; +SocketAdmin.widgets = {}; SocketAdmin.themes.getInstalled = function(socket, data, callback) { meta.themes.get(callback); @@ -269,7 +271,7 @@ SocketAdmin.themes.set = function(socket, data, callback) { return callback(new Error('invalid data')); } meta.themes.set(data, callback); -} +}; SocketAdmin.plugins.toggle = function(socket, plugin_id) { plugins.toggleActive(plugin_id, function(status) { @@ -277,6 +279,14 @@ SocketAdmin.plugins.toggle = function(socket, plugin_id) { }); }; +SocketAdmin.widgets.set = function(socket, data, callback) { + if(!data) { + return callback(new Error('invalid data')); + } + + widgets.setArea(data, callback); +}; + /* Configs */ SocketAdmin.config = {}; diff --git a/src/widgets.js b/src/widgets.js new file mode 100644 index 0000000000..5c506619af --- /dev/null +++ b/src/widgets.js @@ -0,0 +1,26 @@ +var async = require('async'), + winston = require('winston'), + db = require('./database'); + + +(function(Widgets) { + + Widgets.setArea = function(data, callback) { + if (!data.location || !data.template) { + callback({ + error: 'Missing location and template data' + }) + } + + db.setObjectField('widgets:' + data.template, data.location, JSON.stringify(data.widgets), function(err) { + callback(err); + }); + }; + + Widgets.getArea = function(template, location, callback) { + db.getObjectField('widgets:' + template, location, function(err, widgets) { + callback(err, JSON.parse(widgets)); + }) + }; + +}(exports)); \ No newline at end of file From 26b0db3bea9b027ede1969c885a37a707236843c Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 15:14:49 -0500 Subject: [PATCH 06/46] let plugins.js allow widgets to utilize hooks --- src/plugins.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins.js b/src/plugins.js index d2b7a6cc98..9614777524 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -375,8 +375,10 @@ var fs = require('fs'), dirs = dirs.map(function(file) { return path.join(npmPluginPath, file); }).filter(function(file) { - var stats = fs.statSync(file); - if (stats.isDirectory() && file.substr(npmPluginPath.length + 1, 14) === 'nodebb-plugin-') return true; + var stats = fs.statSync(file), + isPlugin = file.substr(npmPluginPath.length + 1, 14) === 'nodebb-plugin-' || file.substr(npmPluginPath.length + 1, 14) === 'nodebb-widget-'; + + if (stats.isDirectory() && isPlugin) return true; else return false; }); From f4ad1bdeae181a5b93a9756a1ab35269b7efa415 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 15:43:05 -0500 Subject: [PATCH 07/46] console.log --- public/src/forum/admin/themes.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index eedbc58fa4..90b74f7ee0 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -159,7 +159,7 @@ define(['forum/admin/settings'], function(Settings) { $(this).parents('.panel').children('.panel-body').toggleClass('hidden'); }).on('click', '.delete-widget', function() { var panel = $(this).parents('.panel'); - + bootbox.confirm('Are you sure you wish to delete this widget?', function(confirm) { if (confirm) { panel.remove(); @@ -230,7 +230,6 @@ define(['forum/admin/settings'], function(Settings) { var area = areas[a], widgetArea = $('#widgets .area [data-template="' + area.template + '"][data-location="' + area.location + '"]').parents('.area').find('.widget-area'); - console.log('data', area.data); for (var i in area.data) { if (area.data.hasOwnProperty(i)) { var data = area.data[i], From 4e1b3506e8c4368d1e9936e0662ae146cf8a766e Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 16:11:16 -0500 Subject: [PATCH 08/46] allow plugins/widgets to define widgets; moved sample widgets out of core and into nodebb-widget-essentials --- public/src/forum/admin/themes.js | 1 - public/templates/admin/themes.tpl | 23 ++++------------------- src/routes/admin.js | 15 +++++++++++---- src/widgets.js | 14 +++++++------- 4 files changed, 22 insertions(+), 31 deletions(-) diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index 90b74f7ee0..37180be94b 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -235,7 +235,6 @@ define(['forum/admin/settings'], function(Settings) { var data = area.data[i], widgetEl = $('.available-widgets [data-widget="' + data.widget + '"]').clone(); - widgetArea.append(populateWidget(widgetEl, data.data)); appendToggle(widgetEl); } diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index b33e7796fd..861dbaee37 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -57,32 +57,17 @@

Available Widgets

-
-
- HTML Any text, html, or embedded script. -
- -
-
+ +
- Text Markdown formatted text + {widgets.name} {widgets.description}
- -
diff --git a/src/routes/admin.js b/src/routes/admin.js index fa60980dcf..4213cd15a6 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -412,18 +412,25 @@ var nconf = require('nconf'), }); app.get('/themes', function (req, res) { - plugins.fireHook('filter:widgets.getAreas', [], function(err, areas) { - async.each(areas, function(area, next) { + async.parallel({ + areas: function(next) { + plugins.fireHook('filter:widgets.getAreas', [], next); + }, + widgets: function(next) { + plugins.fireHook('filter:widgets.getWidgets', [], next); + } + }, function(err, data) { + async.each(data.areas, function(area, next) { widgets.getArea(area.template, area.location, function(err, areaData) { area.data = areaData; next(err); }); }, function(err) { res.json(200, { - areas: areas, + areas: data.areas, + widgets: data.widgets }); }); - }); }); diff --git a/src/widgets.js b/src/widgets.js index 5c506619af..5e9e754d2d 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -5,11 +5,17 @@ var async = require('async'), (function(Widgets) { + Widgets.getArea = function(template, location, callback) { + db.getObjectField('widgets:' + template, location, function(err, widgets) { + callback(err, JSON.parse(widgets)); + }) + }; + Widgets.setArea = function(data, callback) { if (!data.location || !data.template) { callback({ error: 'Missing location and template data' - }) + }); } db.setObjectField('widgets:' + data.template, data.location, JSON.stringify(data.widgets), function(err) { @@ -17,10 +23,4 @@ var async = require('async'), }); }; - Widgets.getArea = function(template, location, callback) { - db.getObjectField('widgets:' + template, location, function(err, widgets) { - callback(err, JSON.parse(widgets)); - }) - }; - }(exports)); \ No newline at end of file From 37d673028a190cc026991cd8231a8a0482be5a38 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 17:07:19 -0500 Subject: [PATCH 09/46] added async to client side --- public/src/modules/vendor/async.js | 958 +++++++++++++++++++++++++++++ 1 file changed, 958 insertions(+) create mode 100644 public/src/modules/vendor/async.js diff --git a/public/src/modules/vendor/async.js b/public/src/modules/vendor/async.js new file mode 100644 index 0000000000..1eebb153fd --- /dev/null +++ b/public/src/modules/vendor/async.js @@ -0,0 +1,958 @@ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + } + })); + }); + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _each(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor !== Array) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (test()) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (!test()) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain) cargo.drain(); + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.compose = function (/* functions... */) { + var fns = Array.prototype.reverse.call(arguments); + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // AMD / RequireJS + if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // Node.js + else if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // included directly via \ No newline at end of file diff --git a/public/templates/home.tpl b/public/templates/home.tpl index 0d64db4a35..6551c55339 100644 --- a/public/templates/home.tpl +++ b/public/templates/home.tpl @@ -1,7 +1,3 @@ -
- {motd} -
- diff --git a/src/categories.js b/src/categories.js index 640122598d..dbafd55c4d 100644 --- a/src/categories.js +++ b/src/categories.js @@ -71,12 +71,6 @@ var db = require('./database'), Categories.getModerators(category_id, next); } - function getSidebars(next) { - plugins.fireHook('filter:category.build_sidebars', [], function(err, sidebars) { - next(err, sidebars); - }); - } - function getPageCount(next) { Categories.getPageCount(category_id, current_user, next); } @@ -86,7 +80,6 @@ var db = require('./database'), 'topics': getTopics, 'active_users': getActiveUsers, 'moderators': getModerators, - 'sidebars': getSidebars, 'pageCount': getPageCount }, function(err, results) { if(err) { @@ -106,7 +99,6 @@ var db = require('./database'), 'nextStart': results.topics.nextStart, 'pageCount': results.pageCount, 'disableSocialButtons': meta.config.disableSocialButtons !== undefined ? parseInt(meta.config.disableSocialButtons, 10) !== 0 : false, - 'sidebars': results.sidebars }; callback(null, category); From cb986186a1c8c755f90302517b6e7372c129f272 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 18:53:28 -0500 Subject: [PATCH 19/46] removing recent replies code + tpls from the core in favour of widget system --- public/src/forum/category.js | 30 ------------------------------ public/templates/category.tpl | 22 ++++++++++++++-------- public/templates/recentreplies.tpl | 14 -------------- src/widgets.js | 5 +++-- 4 files changed, 17 insertions(+), 54 deletions(-) delete mode 100644 public/templates/recentreplies.tpl diff --git a/public/src/forum/category.js b/public/src/forum/category.js index fd4b6efe42..faf2375095 100644 --- a/public/src/forum/category.js +++ b/public/src/forum/category.js @@ -37,8 +37,6 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { socket.on('event:new_topic', Category.onNewTopic); - socket.emit('categories.getRecentReplies', cid, renderRecentReplies); - enableInfiniteLoading(); }; @@ -84,7 +82,6 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { } topic.hide().fadeIn('slow'); - socket.emit('categories.getRecentReplies', templates.get('category_id'), renderRecentReplies); addActiveUser(data); @@ -159,32 +156,5 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { }); } - function renderRecentReplies(err, posts) { - if (err || !posts || posts.length === 0) { - return; - } - - var recentReplies = $('#category_recent_replies'); - - templates.preload_template('recentreplies', function() { - - templates['recentreplies'].parse({posts:[]}); - - var html = templates.prepare(templates['recentreplies'].blocks['posts']).parse({ - posts: posts - }); - - translator.translate(html, function(translatedHTML) { - translatedHTML = $(translatedHTML); - translatedHTML.find('img').addClass('img-responsive'); - - recentReplies.html(translatedHTML); - - $('#category_recent_replies span.timeago').timeago(); - app.createUserTooltips(); - }); - }); - }; - return Category; }); \ No newline at end of file diff --git a/public/templates/category.tpl b/public/templates/category.tpl index 56ed2766df..c8e3c59640 100644 --- a/public/templates/category.tpl +++ b/public/templates/category.tpl @@ -97,20 +97,26 @@
-
+
+
-
[[category:sidebar.recent_replies]]
-
-
    +
    {widgets.title}
    +
    + {widgets.html}
    + +
    +
    [[category:sidebar.active_participants]]
    -
    - - - +
    +
    + + +
    diff --git a/public/templates/recentreplies.tpl b/public/templates/recentreplies.tpl deleted file mode 100644 index 121211c3d6..0000000000 --- a/public/templates/recentreplies.tpl +++ /dev/null @@ -1,14 +0,0 @@ - - -
  • - - - - {posts.username} -

    {posts.content}

    - - [[category:posted]] - - -
  • - diff --git a/src/widgets.js b/src/widgets.js index ac848a0b33..d7898c465a 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -21,9 +21,10 @@ var async = require('async'), uid: uid, area: area, data: widget.data - }, function(err, html){ + }, function(err, data){ rendered.push({ - html: html + html: data.html, + title: data.title }); next(err); From 835b4d61a2e23babeba0d0be22c75b320c4b2943 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 19:07:56 -0500 Subject: [PATCH 20/46] removed active_users + moderator sidebar code from core in favour of widget system --- public/templates/category.tpl | 24 ------------------------ src/categories.js | 17 ----------------- 2 files changed, 41 deletions(-) diff --git a/public/templates/category.tpl b/public/templates/category.tpl index c8e3c59640..e208ea7dfc 100644 --- a/public/templates/category.tpl +++ b/public/templates/category.tpl @@ -107,30 +107,6 @@
    - -
    -
    -
    [[category:sidebar.active_participants]]
    -
    -
    - - -
    -
    -
    - - -
    -
    [[category:sidebar.moderators]]
    -
    - - - -
    -
    - -
    diff --git a/src/categories.js b/src/categories.js index dbafd55c4d..0e47e7b1a8 100644 --- a/src/categories.js +++ b/src/categories.js @@ -58,19 +58,6 @@ var db = require('./database'), Categories.getCategoryTopics(category_id, start, end, current_user, next); } - function getActiveUsers(next) { - Categories.getActiveUsers(category_id, function(err, uids) { - if(err) { - return next(err); - } - user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], next); - }); - } - - function getModerators(next) { - Categories.getModerators(category_id, next); - } - function getPageCount(next) { Categories.getPageCount(category_id, current_user, next); } @@ -78,8 +65,6 @@ var db = require('./database'), async.parallel({ 'category': getCategoryData, 'topics': getTopics, - 'active_users': getActiveUsers, - 'moderators': getModerators, 'pageCount': getPageCount }, function(err, results) { if(err) { @@ -93,8 +78,6 @@ var db = require('./database'), 'disabled': results.category.disabled, 'topic_row_size': 'col-md-9', 'category_id': category_id, - 'active_users': results.active_users, - 'moderators': results.moderators, 'topics': results.topics.topics, 'nextStart': results.topics.nextStart, 'pageCount': results.pageCount, From 305ec0da281d7c86661197cf57b47ce774757ffd Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 19:10:56 -0500 Subject: [PATCH 21/46] removed unused language strings from previous sidebar --- public/language/en_GB/category.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/public/language/en_GB/category.json b/public/language/en_GB/category.json index d29e23eb95..861c7b4ec6 100644 --- a/public/language/en_GB/category.json +++ b/public/language/en_GB/category.json @@ -1,9 +1,6 @@ { "new_topic_button": "New Topic", "no_topics": "There are no topics in this category.
    Why don't you try posting one?", - "sidebar.recent_replies": "Recent Replies", - "sidebar.active_participants": "Active Participants", - "sidebar.moderators": "Moderators", "posts": "posts", "views": "views", "posted": "posted", From fa4555e26e2dba3a0638114bc5efbad6d7d420b2 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 19:15:04 -0500 Subject: [PATCH 22/46] moved addActiveUser code to widget-essentials --- public/src/forum/category.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/public/src/forum/category.js b/public/src/forum/category.js index faf2375095..810adaa78f 100644 --- a/public/src/forum/category.js +++ b/public/src/forum/category.js @@ -83,8 +83,6 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { topic.hide().fadeIn('slow'); - addActiveUser(data); - socket.emit('categories.getPageCount', templates.get('category_id'), function(err, newPageCount) { pagination.recreatePaginationLinks(newPageCount); }); @@ -94,21 +92,6 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { }); } - function addActiveUser(data) { - var activeUser = $('.category-sidebar .active-users').find('a[data-uid="' + data.uid + '"]'); - if(!activeUser.length) { - var newUser = templates.prepare(templates['category'].blocks['active_users']).parse({ - active_users: [{ - uid: data.uid, - username: data.username, - userslug: data.userslug, - picture: data.teaser_userpicture - }] - }); - $(newUser).appendTo($('.category-sidebar .active-users')); - } - } - Category.onTopicsLoaded = function(topics) { var html = templates.prepare(templates['category'].blocks['topics']).parse({ topics: topics From 18369fae7e72e403b871a0af3732607a7948bc69 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 19:19:25 -0500 Subject: [PATCH 23/46] fixed bug with sorting of widgets --- src/widgets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets.js b/src/widgets.js index d7898c465a..9f865b02fa 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -16,7 +16,7 @@ var async = require('async'), var rendered = []; Widgets.getArea(area.template, area.location, function(err, widgets) { - async.each(widgets, function(widget, next) { + async.eachSeries(widgets, function(widget, next) { plugins.fireHook('filter:widget.render:' + widget.widget, { uid: uid, area: area, From 599027f2d31f28c69bdb43302c7eb6dcbce65d35 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Wed, 19 Feb 2014 19:28:21 -0500 Subject: [PATCH 24/46] send full url to widgets as well so they can parse based on path --- public/src/ajaxify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 94eaba4fb6..4790649b7b 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -120,7 +120,7 @@ var ajaxify = {}; async.each(widgetLocations, function(location, next) { var area = $('#content [widget-area="' + location + '"]'); - socket.emit('widgets.render', {template: tpl_url + '.tpl', location: location}, function(err, renderedWidgets) { + socket.emit('widgets.render', {template: tpl_url + '.tpl', url: url, location: location}, function(err, renderedWidgets) { area.html(templates.prepare(area.html()).parse({widgets: renderedWidgets})).removeClass('hidden'); next(err); }); From 502886c3b9b0fb20c0c0d2dbb9785e56096cee40 Mon Sep 17 00:00:00 2001 From: MrWaffle Date: Thu, 20 Feb 2014 19:18:23 +0100 Subject: [PATCH 25/46] Fix crash when there would be no widgets --- src/widgets.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widgets.js b/src/widgets.js index 9f865b02fa..7c8f221444 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -37,6 +37,9 @@ var async = require('async'), Widgets.getArea = function(template, location, callback) { db.getObjectField('widgets:' + template, location, function(err, widgets) { + if (!widgets) { + return callback(err, []); + } callback(err, JSON.parse(widgets)); }) }; From 0b3fa0c838902b3b9d665554aefcb9a72229fa84 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 15:28:37 -0500 Subject: [PATCH 26/46] upgrade.js - add recentreplies, activeusers, and moderator widgets to the sidebar as default --- src/upgrade.js | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/upgrade.js b/src/upgrade.js index 2d6f2545d0..e0dc8e1974 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -19,7 +19,7 @@ var db = require('./database'), Upgrade.check = function(callback) { // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema - var latestSchema = new Date(2014, 1, 19, 18, 15).getTime(); + var latestSchema = new Date(2014, 1, 20, 15, 30).getTime(); db.get('schemaDate', function(err, value) { if (parseInt(value, 10) >= latestSchema) { @@ -717,6 +717,34 @@ Upgrade.upgrade = function(callback) { winston.info('[2014/2/19] Updating MOTD to use the HTML widget - skipped'); next(); } + }, + function(next) { + thisSchemaDate = new Date(2014, 1, 20, 15, 30).getTime(); + + if (schemaDate < thisSchemaDate) { + updatesMade = true; + + db.setObjectField('widgets:category.tpl', 'sidebar', JSON.stringify([ + { + "widget": "recentreplies", + "data": {} + }, + { + "widget": "activeusers", + "data": {} + }, + { + "widget": "moderators", + "data": {} + } + ]), function(err) { + winston.info('[2014/2/20] Updated MOTD to use the HTML widget.'); + next(err); + }); + } else { + winston.info('[2014/2/20] Updating MOTD to use the HTML widget - skipped'); + next(); + } } // Add new schema updates here // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 17!!! From ae009e04bdf2aff5723cfeaeeb7e5b37f296c030 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 15:30:26 -0500 Subject: [PATCH 27/46] added widgets-essentials to deps --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 424f97d689..13c056b555 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "validator": "~3.2.1", "nodebb-plugin-mentions": "~0.4", "nodebb-plugin-markdown": "~0.3", + "nodebb-widgets-essentials": "~0.2", "nodebb-theme-vanilla": "~0.0.13", "nodebb-theme-cerulean": "~0.0.12", "nodebb-theme-lavender": "~0.0", From 068402c8ace54bb5509793eb93229e3442936f31 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 15:31:42 -0500 Subject: [PATCH 28/46] wrong upgrade message --- src/upgrade.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/upgrade.js b/src/upgrade.js index e0dc8e1974..866c079513 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -738,11 +738,11 @@ Upgrade.upgrade = function(callback) { "data": {} } ]), function(err) { - winston.info('[2014/2/20] Updated MOTD to use the HTML widget.'); + winston.info('[2014/2/20] Adding Recent Replies, Active Users, and Moderator widgets to category sidebar.'); next(err); }); } else { - winston.info('[2014/2/20] Updating MOTD to use the HTML widget - skipped'); + winston.info('[2014/2/20] Adding Recent Replies, Active Users, and Moderator widgets to category sidebar - skipped'); next(); } } From c39a951727b91e13b5c86d00978dc13c47f7ad1f Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 15:33:21 -0500 Subject: [PATCH 29/46] fixed widget-essentials dep --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 13c056b555..c206886d0d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "validator": "~3.2.1", "nodebb-plugin-mentions": "~0.4", "nodebb-plugin-markdown": "~0.3", - "nodebb-widgets-essentials": "~0.2", + "nodebb-widget-essentials": "~0.2", "nodebb-theme-vanilla": "~0.0.13", "nodebb-theme-cerulean": "~0.0.12", "nodebb-theme-lavender": "~0.0", From 3896cbd7320266203faa480be4404cb95b3bbf77 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 15:39:52 -0500 Subject: [PATCH 30/46] and fixed it again --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c206886d0d..bc2eb9ed5d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "validator": "~3.2.1", "nodebb-plugin-mentions": "~0.4", "nodebb-plugin-markdown": "~0.3", - "nodebb-widget-essentials": "~0.2", + "nodebb-widget-essentials": "~0.0", "nodebb-theme-vanilla": "~0.0.13", "nodebb-theme-cerulean": "~0.0.12", "nodebb-theme-lavender": "~0.0", From b821dc70cff11515b9bdfcfc6a8c3d65be2505d6 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 16:03:25 -0500 Subject: [PATCH 31/46] moved Forum Stats widget out of core and into widget-essentials --- public/src/forum/home.js | 27 --------------------------- public/templates/home.tpl | 23 ----------------------- 2 files changed, 50 deletions(-) diff --git a/public/src/forum/home.js b/public/src/forum/home.js index c38568bd6c..cc6bd63fdf 100644 --- a/public/src/forum/home.js +++ b/public/src/forum/home.js @@ -3,33 +3,6 @@ define(function() { home.init = function() { - ajaxify.register_events([ - 'user.count', - 'meta.getUsageStats', - 'user.getActiveUsers' - ]); - - socket.emit('user.count', updateUserCount); - socket.on('user.count', updateUserCount); - - function updateUserCount(err, data) { - $('#stats_users').html(utils.makeNumberHumanReadable(data.count)).attr('title', data.count); - } - - socket.emit('meta.getUsageStats', updateUsageStats); - socket.on('meta.getUsageStats', updateUsageStats); - - function updateUsageStats(err, data) { - $('#stats_topics').html(utils.makeNumberHumanReadable(data.topics)).attr('title', data.topics); - $('#stats_posts').html(utils.makeNumberHumanReadable(data.posts)).attr('title', data.posts); - } - - socket.emit('user.getActiveUsers', updateActiveUsers); - socket.on('user.getActiveUsers', updateActiveUsers); - - function updateActiveUsers(err, data) { - $('#stats_online').html(data.users); - } } return home; diff --git a/public/templates/home.tpl b/public/templates/home.tpl index c997ba9685..59e03b9dab 100644 --- a/public/templates/home.tpl +++ b/public/templates/home.tpl @@ -48,26 +48,3 @@
    - - From 1b557d4141cf427b7916cf6d104955d66794c0e4 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 16:14:24 -0500 Subject: [PATCH 32/46] upgrade.js - add forum stats widget to homepage footer --- public/templates/home.tpl | 8 ++++++++ src/upgrade.js | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/public/templates/home.tpl b/public/templates/home.tpl index 59e03b9dab..dac82f3a8f 100644 --- a/public/templates/home.tpl +++ b/public/templates/home.tpl @@ -48,3 +48,11 @@
    + + \ No newline at end of file diff --git a/src/upgrade.js b/src/upgrade.js index 866c079513..cf98d86062 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -745,6 +745,26 @@ Upgrade.upgrade = function(callback) { winston.info('[2014/2/20] Adding Recent Replies, Active Users, and Moderator widgets to category sidebar - skipped'); next(); } + }, + function(next) { + thisSchemaDate = new Date(2014, 1, 20, 16, 15).getTime(); + + if (schemaDate < thisSchemaDate) { + updatesMade = true; + + db.setObjectField('widgets:home.tpl', 'footer', JSON.stringify([ + { + "widget": "forumstats", + "data": {} + } + ]), function(err) { + winston.info('[2014/2/20] Adding Forum Stats Widget to the Homepage Footer.'); + next(err); + }); + } else { + winston.info('[2014/2/20] Adding Forum Stats Widget to the Homepage Footer - skipped'); + next(); + } } // Add new schema updates here // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 17!!! From 5acf296adafc1a4f6a906ce7977c44a414e54407 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 17:12:56 -0500 Subject: [PATCH 33/46] added containers; drag on top of widgets to set a custom container --- public/src/forum/admin/themes.js | 20 +++++++++-- public/templates/admin/themes.tpl | 59 +++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index 37180be94b..f80159fc00 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -135,18 +135,34 @@ define(['forum/admin/settings'], function(Settings) { } Themes.prepareWidgets = function() { - $('#widgets .panel').draggable({ + $('#widgets .available-widgets .panel').draggable({ helper: function(e) { return $(e.target).parents('.panel').clone().addClass('block').width($(e.target.parentNode).width()); }, connectToSortable: ".widget-area" }); + $('#widgets .available-containers .containers > [data-container]').draggable({ + helper: function(e) { + var target = $(e.target); + target = target.attr('data-container') ? target : target.parents('[data-container]'); + + return target.clone().addClass('block').width(target.width()).css('opacity', '0.5'); + } + }); + function appendToggle(el) { if (!el.hasClass('block')) { el.addClass('block') + .droppable({ + drop: function(event, ui) { + $(this).find('.panel-heading small').html(ui.draggable.attr('data-container')); + }, + hoverClass: "panel-info" + }) .children('.panel-heading') - .append('
     
    '); + .append('
     
    ') + .children('small').html(''); } } diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index 861dbaee37..22d423c844 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -54,25 +54,7 @@

    Widgets

    -
    -

    Available Widgets

    -
    - -
    -
    - {widgets.name} {widgets.description} -
    - -
    - -
    -
    - -
    +

    {areas.name} {areas.template} / {areas.location}

    @@ -82,6 +64,45 @@
    +
    +
    +

    Available Widgets

    +
    + +
    +
    + {widgets.name} {widgets.description} +
    + +
    + +
    +
    + +
    +

    Available Containers

    +
    +
    + None +
    +
    + Well +
    +
    +
    + Panel Header +
    +
    + Panel Body +
    +
    +
    +
    +
    From ef65f510a52110816a7c949c85e90e75a387de28 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 17:57:41 -0500 Subject: [PATCH 34/46] fomatting --- public/src/ajaxify.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 4790649b7b..2505113ce2 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -121,7 +121,10 @@ var ajaxify = {}; var area = $('#content [widget-area="' + location + '"]'); socket.emit('widgets.render', {template: tpl_url + '.tpl', url: url, location: location}, function(err, renderedWidgets) { - area.html(templates.prepare(area.html()).parse({widgets: renderedWidgets})).removeClass('hidden'); + area.html(templates.prepare(area.html()).parse({ + widgets: renderedWidgets + })).removeClass('hidden'); + next(err); }); }, function(err) { From 80ce4db76463de0ec3f903877ac5a3f52f95f440 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 17:58:12 -0500 Subject: [PATCH 35/46] add container field and title field to all widgets by default --- public/src/forum/admin/themes.js | 9 ++++++--- public/templates/admin/themes.tpl | 6 +++--- src/routes/admin.js | 6 ++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index f80159fc00..0e33f70cc2 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -142,10 +142,10 @@ define(['forum/admin/settings'], function(Settings) { connectToSortable: ".widget-area" }); - $('#widgets .available-containers .containers > [data-container]').draggable({ + $('#widgets .available-containers .containers > [data-container-html]').draggable({ helper: function(e) { var target = $(e.target); - target = target.attr('data-container') ? target : target.parents('[data-container]'); + target = target.attr('data-container-html') ? target : target.parents('[data-container-html]'); return target.clone().addClass('block').width(target.width()).css('opacity', '0.5'); } @@ -156,7 +156,10 @@ define(['forum/admin/settings'], function(Settings) { el.addClass('block') .droppable({ drop: function(event, ui) { - $(this).find('.panel-heading small').html(ui.draggable.attr('data-container')); + var el = $(this); + + el.find('.panel-body .container-html').val(ui.draggable.attr('data-container-html')); + el.find('.panel-body').removeClass('hidden'); }, hoverClass: "panel-info" }) diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index 22d423c844..7cb7611fa8 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -86,13 +86,13 @@

    Available Containers

    -
    +
    None
    -
    +
    Well
    -
    +
    Panel Header
    diff --git a/src/routes/admin.js b/src/routes/admin.js index 7d214b2135..8af4d4b6b2 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -429,6 +429,12 @@ var nconf = require('nconf'), next(err); }); }, function(err) { + for (var w in data.widgets) { + if (data.widgets.hasOwnProperty(w)) { + data.widgets[w].content += "

    "; + } + } + res.json(200, { areas: data.areas, widgets: data.widgets From 68b9e36218b5719516f2b6364cbbaa2f77bfbb8f Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 18:10:06 -0500 Subject: [PATCH 36/46] rendering widget's container --- src/widgets.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/widgets.js b/src/widgets.js index 7c8f221444..b6de26752a 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -1,7 +1,8 @@ var async = require('async'), winston = require('winston'), plugins = require('./plugins'), - db = require('./database'); + db = require('./database'), + templates = require('./../public/src/templates'); (function(Widgets) { @@ -21,10 +22,16 @@ var async = require('async'), uid: uid, area: area, data: widget.data - }, function(err, data){ + }, function(err, html){ + if (widget.data.container && widget.data.container.match('{body}')) { + html = templates.prepare(widget.data.container).parse({ + title: widget.data.title, + body: html + }); + } + rendered.push({ - html: data.html, - title: data.title + html: html }); next(err); From 8543d2d437d99c78495a8161b5db6a3c827a4f41 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 18:31:16 -0500 Subject: [PATCH 37/46] deprecated hard-coded panels in category sidebar, now you can set custom containers in widget ACP --- public/templates/category.tpl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/public/templates/category.tpl b/public/templates/category.tpl index e208ea7dfc..36c5bfa393 100644 --- a/public/templates/category.tpl +++ b/public/templates/category.tpl @@ -99,12 +99,7 @@
    -
    -
    {widgets.title}
    -
    - {widgets.html} -
    -
    + {widgets.html}
    From ccf529ccca0e91186cf7f1f51b7bb7128d65ac45 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 18:45:38 -0500 Subject: [PATCH 38/46] updated upgrade script to add titles and container to category sidebar widgets --- src/upgrade.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/upgrade.js b/src/upgrade.js index cf98d86062..3ae31cf13f 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -724,18 +724,29 @@ Upgrade.upgrade = function(callback) { if (schemaDate < thisSchemaDate) { updatesMade = true; + var container = '
    {title}
    {body}
    '; + db.setObjectField('widgets:category.tpl', 'sidebar', JSON.stringify([ { "widget": "recentreplies", - "data": {} + "data": { + "title": "Recent Replies", + "container": container + } }, { "widget": "activeusers", - "data": {} + "data": { + "title": "Active Users", + "container": container + } }, { "widget": "moderators", - "data": {} + "data": { + "title": "Moderators", + "container": container + } } ]), function(err) { winston.info('[2014/2/20] Adding Recent Replies, Active Users, and Moderator widgets to category sidebar.'); From 2131506d59fce8ffbb0447e3c25bac5b9d498a60 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 18:50:17 -0500 Subject: [PATCH 39/46] widgets - user friendly instructions --- public/templates/admin/themes.tpl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index 7cb7611fa8..ac84011d44 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -66,7 +66,7 @@
    -

    Available Widgets

    +

    Available Widgets Drag and drop widgets into templates

    @@ -82,9 +82,9 @@
    - +
    -

    Available Containers

    +

    Available Containers Drag and drop on top of any widget

    None @@ -92,6 +92,9 @@
    Well
    +
    + Jumbotron +
    Panel Header From e28589bea811dbedac5846fdad2ac76020510324 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 19:22:34 -0500 Subject: [PATCH 40/46] added jumbotron, alert widgets + color picker for alert and panel --- public/src/forum/admin/themes.js | 19 +++++++++++++++++++ public/templates/admin/themes.tpl | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/public/src/forum/admin/themes.js b/public/src/forum/admin/themes.js index 0e33f70cc2..a3b22983b1 100644 --- a/public/src/forum/admin/themes.js +++ b/public/src/forum/admin/themes.js @@ -263,6 +263,25 @@ define(['forum/admin/settings'], function(Settings) { } } }); + + $('.color-selector').on('click', '.btn', function() { + var btn = $(this), + selector = btn.parents('.color-selector'), + container = selector.parents('[data-container-html]'), + classList = []; + + selector.children().each(function() { + classList.push($(this).attr('data-class')); + }); + + container + .removeClass(classList.join(' ')) + .addClass(btn.attr('data-class')); + + container.attr('data-container-html', container.attr('data-container-html') + .replace(/class="[a-zA-Z0-9-\s]+"/, 'class="' + container[0].className.replace(' pointer ui-draggable', '') + '"') + ); + }); }; return Themes; diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index ac84011d44..c7a3f3e6f1 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -98,11 +98,29 @@
    Panel Header +
    + + + + + + +
    Panel Body
    + +
    + Alert +
    + + + + +
    +
    From 596a622197090ac6c8a0c28a773d4a7ba6d69599 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 19:25:40 -0500 Subject: [PATCH 41/46] updated vanilla dep to 0.0.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bc2eb9ed5d..165fc4dd08 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "nodebb-plugin-mentions": "~0.4", "nodebb-plugin-markdown": "~0.3", "nodebb-widget-essentials": "~0.0", - "nodebb-theme-vanilla": "~0.0.13", + "nodebb-theme-vanilla": "~0.0.14", "nodebb-theme-cerulean": "~0.0.12", "nodebb-theme-lavender": "~0.0", "cron": "~1.0.1", From 9a5be0b33489b323a8b33af6c25a1989e56ac8c5 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 19:39:22 -0500 Subject: [PATCH 42/46] updated lavender dep to 0.0.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 165fc4dd08..60fa2e8aaa 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "nodebb-widget-essentials": "~0.0", "nodebb-theme-vanilla": "~0.0.14", "nodebb-theme-cerulean": "~0.0.12", - "nodebb-theme-lavender": "~0.0", + "nodebb-theme-lavender": "~0.0.21", "cron": "~1.0.1", "semver": "~2.2.1", "string": "~1.7.0", From fc866e47466ac2d214663cf8ab177b8f4698a6c7 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 19:48:08 -0500 Subject: [PATCH 43/46] added notice to admins to check out the widgets panel IF motd is not set. upgraded motd to widget for lavender --- src/upgrade.js | 60 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/src/upgrade.js b/src/upgrade.js index 3ae31cf13f..587bf72623 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -19,7 +19,7 @@ var db = require('./database'), Upgrade.check = function(callback) { // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema - var latestSchema = new Date(2014, 1, 20, 15, 30).getTime(); + var latestSchema = new Date(2014, 1, 20, 19, 45).getTime(); db.get('schemaDate', function(err, value) { if (parseInt(value, 10) >= latestSchema) { @@ -692,27 +692,21 @@ Upgrade.upgrade = function(callback) { if (schemaDate < thisSchemaDate) { updatesMade = true; - if (Meta.config['motd']) { - db.setObjectField('widgets:home.tpl', 'motd', JSON.stringify([ - { - "widget": "html", - "data": { - "html": Meta.config['motd'] - } + db.setObjectField('widgets:home.tpl', 'motd', JSON.stringify([ + { + "widget": "html", + "data": { + "html": Meta.config['motd'] || "Welcome to NodeBB, if you are an administrator of this forum visit the Themes ACP to modify and add widgets." } - ]), function(err) { - Meta.configs.remove('motd'); - Meta.configs.remove('motd_class'); - Meta.configs.remove('show_motd'); - - winston.info('[2014/2/19] Updated MOTD to use the HTML widget.'); - next(err); - }); - } else { - winston.info('[2014/2/19] Updating MOTD to use the HTML widget - skipped'); - next(); - } + } + ]), function(err) { + Meta.configs.remove('motd'); + Meta.configs.remove('motd_class'); + Meta.configs.remove('show_motd'); + winston.info('[2014/2/19] Updated MOTD to use the HTML widget.'); + next(err); + }); } else { winston.info('[2014/2/19] Updating MOTD to use the HTML widget - skipped'); next(); @@ -776,6 +770,32 @@ Upgrade.upgrade = function(callback) { winston.info('[2014/2/20] Adding Forum Stats Widget to the Homepage Footer - skipped'); next(); } + }, + function(next) { + thisSchemaDate = new Date(2014, 1, 20, 19, 45).getTime(); + + if (schemaDate < thisSchemaDate) { + updatesMade = true; + + var container = '
    {title}
    {body}
    '; + + db.setObjectField('widgets:home.tpl', 'sidebar', JSON.stringify([ + { + "widget": "html", + "data": { + "html": Meta.config['motd'] || "Welcome to NodeBB, if you are an administrator of this forum visit the Themes ACP to modify and add widgets.", + "container": container, + "title": "MOTD" + } + } + ]), function(err) { + winston.info('[2014/2/20] Updating Lavender MOTD'); + next(err); + }); + } else { + winston.info('[2014/2/20] Updating Lavender MOTD - skipped'); + next(); + } } // Add new schema updates here // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 17!!! From 5de6ea0d979bbcf211c127a904ffc2e588fd96e3 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 19:57:25 -0500 Subject: [PATCH 44/46] updated cerulean dep to 0.0.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 60fa2e8aaa..2dd6ff5718 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "nodebb-plugin-markdown": "~0.3", "nodebb-widget-essentials": "~0.0", "nodebb-theme-vanilla": "~0.0.14", - "nodebb-theme-cerulean": "~0.0.12", + "nodebb-theme-cerulean": "~0.0.13", "nodebb-theme-lavender": "~0.0.21", "cron": "~1.0.1", "semver": "~2.2.1", From d140fa33dd14cb727c46166065178a0aa16cebdf Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 20 Feb 2014 20:06:14 -0500 Subject: [PATCH 45/46] fixing tab default + removing two calls to code.jquery.com --- public/templates/admin/header.tpl | 3 +-- public/templates/admin/themes.tpl | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/public/templates/admin/header.tpl b/public/templates/admin/header.tpl index b5a4848b7a..1916453ccb 100644 --- a/public/templates/admin/header.tpl +++ b/public/templates/admin/header.tpl @@ -7,7 +7,7 @@ var RELATIVE_PATH = "{relative_path}"; - + @@ -34,7 +34,6 @@ } }); - diff --git a/public/templates/admin/themes.tpl b/public/templates/admin/themes.tpl index c7a3f3e6f1..95501268de 100644 --- a/public/templates/admin/themes.tpl +++ b/public/templates/admin/themes.tpl @@ -9,7 +9,7 @@
    -
    +

    Installed Themes

    The following themes are currently installed in this NodeBB instance. @@ -50,7 +50,7 @@

    -
    +

    Widgets

    From 8059a838708bc79f39fb463fe86cbac27d50387a Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 20 Feb 2014 20:23:30 -0500 Subject: [PATCH 46/46] activate widget-essentials --- src/upgrade.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/upgrade.js b/src/upgrade.js index 587bf72623..3e8d5f1b97 100644 --- a/src/upgrade.js +++ b/src/upgrade.js @@ -19,7 +19,7 @@ var db = require('./database'), Upgrade.check = function(callback) { // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema - var latestSchema = new Date(2014, 1, 20, 19, 45).getTime(); + var latestSchema = new Date(2014, 1, 20, 20, 20).getTime(); db.get('schemaDate', function(err, value) { if (parseInt(value, 10) >= latestSchema) { @@ -796,6 +796,21 @@ Upgrade.upgrade = function(callback) { winston.info('[2014/2/20] Updating Lavender MOTD - skipped'); next(); } + }, + function(next) { + thisSchemaDate = new Date(2014, 1, 20, 20, 20).getTime(); + + if (schemaDate < thisSchemaDate) { + updatesMade = true; + + db.setAdd('plugins:active', 'nodebb-widget-essentials', function(err) { + winston.info('[2014/2/20] Activating NodeBB Essential Widgets'); + next(err); + }); + } else { + winston.info('[2014/2/20] Activating NodeBB Essential Widgets - skipped'); + next(); + } } // Add new schema updates here // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 17!!!