Merge remote-tracking branch 'origin/master' into user-blocking

v1.18.x
Julian Lam 7 years ago
commit 3951bb9532

@ -73,9 +73,9 @@
"nodebb-plugin-spam-be-gone": "0.5.3",
"nodebb-rewards-essentials": "0.0.11",
"nodebb-theme-lavender": "5.0.4",
"nodebb-theme-persona": "8.0.10",
"nodebb-theme-persona": "8.0.11",
"nodebb-theme-slick": "1.2.1",
"nodebb-theme-vanilla": "9.0.7",
"nodebb-theme-vanilla": "9.0.8",
"nodebb-widget-essentials": "4.0.2",
"nodemailer": "4.4.1",
"passport": "^0.4.0",

@ -44,6 +44,8 @@
"alert.package-manager-unreachable": "<p>NodeBB could not reach the package manager, an upgrade is not suggested at this time.</p>",
"alert.incompatible": "<p>Your version of NodeBB (v%1) is only cleared to upgrade to v%2 of this plugin. Please update your NodeBB if you wish to install a newer version of this plugin.</p>",
"alert.possibly-incompatible": "<div class=\"alert alert-warning\"><p><strong>No Compatibility Information Found</strong></p><p>This plugin did not specify a specific version for installation given your NodeBB version. Full compatibility cannot be guaranteed, and may cause your NodeBB to no longer start properly.</p></div><p>In the event that NodeBB cannot boot properly:</p><pre><code>$ ./nodebb reset plugin=\"%1\"</code></pre><p>Continue installation of latest version of this plugin?</p>",
"alert.reorder": "Plugins Re-ordered",
"alert.reorder-success": "Please rebuild and restart your NodeBB to fully complete the process.",
"license.title": "Plugin License Information",
"license.intro": "The plugin <strong>%1</strong> is licensed under the %2. Please read and understand the license terms prior to activating this plugin.",

@ -150,5 +150,7 @@
"diffs.title": "Post Edit History",
"diffs.description": "This post has <strong>%1</strong> revisions. Click one of the revisions below to see the post content at that point in time.",
"diffs.no-revisions-description": "This post has <strong>%1</strong> revisions."
"diffs.no-revisions-description": "This post has <strong>%1</strong> revisions.",
"diffs.current-revision": "current revision",
"diffs.original-revision": "original revision"
}

@ -3,7 +3,7 @@
"sorting.post-default": "默认帖子排序",
"sorting.oldest-to-newest": "从旧到新",
"sorting.newest-to-oldest": "从新到旧",
"sorting.most-votes": "最多投票",
"sorting.most-votes": "最多赞同",
"sorting.most-posts": "最多回复",
"sorting.topic-default": "默认主题排序",
"length": "帖子长度",

@ -53,7 +53,7 @@
"topics": "主题",
"posts": "帖子",
"best": "最佳",
"votes": "投票",
"votes": "赞同",
"upvoters": "顶的人",
"upvoted": "顶",
"downvoters": "踩的人",

@ -118,7 +118,7 @@
"sort_by": "排序",
"oldest_to_newest": "从旧到新",
"newest_to_oldest": "从新到旧",
"most_votes": "最多投票",
"most_votes": "最多赞同",
"most_posts": "最多回复",
"stale.title": "接受建议并创建新主题?",
"stale.warning": "您回复的主题已经很古老了,是否发布新主题并引用此主题的内容?",

@ -182,6 +182,19 @@ define('admin/extend/plugins', ['jqueryui', 'translator', 'benchpress'], functio
return app.alertError(err.message);
}
$('#order-active-plugins-modal').modal('hide');
app.alert({
alert_id: 'plugin_reordered',
title: '[[admin/extend/plugins:alert.reorder]]',
message: '[[admin/extend/plugins:alert.reorder-success]]',
type: 'success',
timeout: 5000,
clickfn: function () {
require(['admin/modules/instance'], function (instance) {
instance.rebuildAndRestart();
});
},
});
});
});

@ -15,6 +15,8 @@ define('forum/topic/diffs', ['forum/topic/images', 'benchpress', 'translator'],
return app.alertError(err.message);
}
timestamps.unshift(Date.now());
Benchpress.parse('partials/modals/post_history', {
diffs: timestamps.map(function (timestamp) {
timestamp = parseInt(timestamp, 10);

@ -9,6 +9,7 @@ var meta = require('../../meta');
var plugins = require('../../plugins');
var privileges = require('../../privileges');
var categories = require('../../categories');
var notifications = require('../../notifications');
var db = require('../../database');
var helpers = require('../helpers');
var accountHelpers = require('./helpers');
@ -180,15 +181,6 @@ settingsController.get = function (req, res, callback) {
};
function getNotificationSettings(userData, callback) {
var types = [
'notificationType_upvote',
'notificationType_new-topic',
'notificationType_new-reply',
'notificationType_follow',
'notificationType_new-chat',
'notificationType_group-invite',
];
var privilegedTypes = [];
async.waterfall([
@ -206,8 +198,7 @@ function getNotificationSettings(userData, callback) {
privilegedTypes.push('notificationType_new-user-flag');
}
plugins.fireHook('filter:user.notificationTypes', {
userData: userData,
types: types,
types: notifications.baseTypes.slice(),
privilegedTypes: privilegedTypes,
}, next);
},

@ -4,7 +4,7 @@ var async = require('async');
var meta = require('../../meta');
var emailer = require('../../emailer');
var plugins = require('../../plugins');
var notifications = require('../../notifications');
var settingsController = module.exports;
@ -45,32 +45,12 @@ function renderEmail(req, res, next) {
}
function renderUser(req, res, next) {
var types = [
'notificationType_upvote',
'notificationType_new-topic',
'notificationType_new-reply',
'notificationType_follow',
'notificationType_new-chat',
'notificationType_group-invite',
];
var privilegedTypes = [
'notificationType_new-register',
'notificationType_post-queue',
'notificationType_new-post-flag',
'notificationType_new-user-flag',
];
async.waterfall([
function (next) {
plugins.fireHook('filter:user.notificationTypes', {
userData: {},
types: types,
privilegedTypes: privilegedTypes,
}, next);
notifications.getAllNotificationTypes(next);
},
function (results) {
var notificationSettings = results.types.concat(results.privilegedTypes).map(function (type) {
function (notificationTypes) {
var notificationSettings = notificationTypes.map(function (type) {
return {
name: type,
label: '[[notifications:' + type + ']]',

@ -11,6 +11,7 @@ var _ = require('lodash');
var plugins = require('../plugins');
var file = require('../file');
var db = require('../database');
var viewsPath = nconf.get('views_dir');
@ -44,20 +45,22 @@ function processImports(paths, templatePath, source, callback) {
}
Templates.processImports = processImports;
function getTemplateDirs(callback) {
var pluginTemplates = _.values(plugins.pluginsData)
.filter(function (pluginData) {
return !pluginData.id.startsWith('nodebb-theme-');
})
.map(function (pluginData) {
return path.join(__dirname, '../../node_modules/', pluginData.id, pluginData.templates || 'templates');
});
function getTemplateDirs(activePlugins, callback) {
var pluginTemplates = activePlugins.map(function (id) {
if (id.startsWith('nodebb-theme-')) {
return nconf.get('theme_templates_path');
}
if (!plugins.pluginsData[id]) {
return '';
}
return path.join(__dirname, '../../node_modules/', id, plugins.pluginsData[id].templates || 'templates');
}).filter(Boolean);
var themeConfig = require(nconf.get('theme_config'));
var theme = themeConfig.baseTheme;
var themePath;
var themeTemplates = [nconf.get('theme_templates_path')];
var themeTemplates = [];
while (theme) {
themePath = path.join(nconf.get('themes_path'), theme);
themeConfig = require(path.join(themePath, 'theme.json'));
@ -118,6 +121,9 @@ function compile(callback) {
function (next) {
mkdirp(viewsPath, function (err) { next(err); });
},
function (next) {
db.getSortedSetRange('plugins:active', 0, -1, next);
},
getTemplateDirs,
getTemplateFiles,
function (files, next) {

@ -17,6 +17,36 @@ var emailer = require('./emailer');
var Notifications = module.exports;
Notifications.baseTypes = [
'notificationType_upvote',
'notificationType_new-topic',
'notificationType_new-reply',
'notificationType_follow',
'notificationType_new-chat',
'notificationType_group-invite',
];
Notifications.privilegedTypes = [
'notificationType_new-register',
'notificationType_post-queue',
'notificationType_new-post-flag',
'notificationType_new-user-flag',
];
Notifications.getAllNotificationTypes = function (callback) {
async.waterfall([
function (next) {
plugins.fireHook('filter:user.notificationTypes', {
types: Notifications.baseTypes.slice(),
privilegedTypes: Notifications.privilegedTypes.slice(),
}, next);
},
function (results, next) {
next(null, results.types.concat(results.privilegedTypes));
},
], callback);
};
Notifications.startJobs = function () {
winston.verbose('[notifications.init] Registering jobs.');
new cron('*/30 * * * *', Notifications.prune, null, true);

@ -27,7 +27,7 @@ Diffs.get = function (pid, since, callback) {
function (timestamps, next) {
// Pass those made after `since`, and create keys
const keys = timestamps.filter(function (timestamp) {
return (parseInt(timestamp, 10) || 0) > since;
return (parseInt(timestamp, 10) || 0) >= since;
}).map(function (timestamp) {
return 'diff:' + pid + '.' + timestamp;
});

@ -59,7 +59,7 @@ function postReply(socket, data, callback) {
next(null, postData);
websockets.in('uid_' + socket.uid).emit('event:new_post', result);
socket.emit('event:new_post', result);
user.updateOnlineUsers(socket.uid);

@ -9,7 +9,13 @@ module.exports = {
name: 'Delete accidentally long-lived sessions',
timestamp: Date.UTC(2017, 3, 16),
method: function (callback) {
var configJSON = require('../../../config.json');
var configJSON;
try {
configJSON = require('../../../config.json') || { [process.env.database]: true };
} catch (err) {
configJSON = { [process.env.database]: true };
}
var isRedisSessionStore = configJSON.hasOwnProperty('redis');
var progress = this.progress;

@ -8,7 +8,12 @@ module.exports = {
name: 'Change the schema of simple keys so they don\'t use value field (mongodb only)',
timestamp: Date.UTC(2017, 11, 18),
method: function (callback) {
var configJSON = require('../../../config.json');
var configJSON;
try {
configJSON = require('../../../config.json') || { [process.env.database]: true, database: process.env.database };
} catch (err) {
configJSON = { [process.env.database]: true, database: process.env.database };
}
var isMongo = configJSON.hasOwnProperty('mongo') && configJSON.database === 'mongo';
var progress = this.progress;
if (!isMongo) {

@ -6,6 +6,7 @@ var async = require('async');
var meta = require('../meta');
var db = require('../database');
var plugins = require('../plugins');
var notifications = require('../notifications');
module.exports = function (User) {
User.getSettings = function (uid, callback) {
@ -81,12 +82,14 @@ module.exports = function (User) {
settings.delayImageLoading = parseInt(getSetting(settings, 'delayImageLoading', 1), 10) === 1;
settings.bootswatchSkin = settings.bootswatchSkin || meta.config.bootswatchSkin || 'default';
settings.scrollToMyPost = parseInt(getSetting(settings, 'scrollToMyPost', 1), 10) === 1;
settings.notificationType_upvote = getSetting(settings, 'notificationType_upvote', 'notification');
settings['notificationType_new-topic'] = getSetting(settings, 'notificationType_new-topic', 'notification');
settings['notificationType_new-reply'] = getSetting(settings, 'notificationType_new-reply', 'notification');
settings.notificationType_follow = getSetting(settings, 'notificationType_follow', 'notification');
settings['notificationType_new-chat'] = getSetting(settings, 'notificationType_new-chat', 'notification');
settings['notificationType_group-invite'] = getSetting(settings, 'notificationType_group-invite', 'notification');
notifications.getAllNotificationTypes(next);
},
function (notificationTypes, next) {
notificationTypes.forEach(function (notificationType) {
settings[notificationType] = getSetting(settings, notificationType, 'notification');
});
next(null, settings);
},
], callback);
@ -139,26 +142,20 @@ module.exports = function (User) {
upvoteNotifFreq: data.upvoteNotifFreq,
};
var notificationTypes = [
'notificationType_upvote', 'notificationType_new-topic', 'notificationType_new-reply',
'notificationType_follow', 'notificationType_new-chat', 'notificationType_group-invite',
'notificationType_new-register', 'notificationType_post-queue', 'notificationType_new-post-flag',
'notificationType_new-user-flag',
];
notificationTypes.forEach(function (notificationType) {
if (data[notificationType]) {
settings[notificationType] = data[notificationType];
}
});
if (data.bootswatchSkin) {
settings.bootswatchSkin = data.bootswatchSkin;
}
async.waterfall([
function (next) {
notifications.getAllNotificationTypes(next);
},
function (notificationTypes, next) {
notificationTypes.forEach(function (notificationType) {
if (data[notificationType]) {
settings[notificationType] = data[notificationType];
}
});
plugins.fireHook('filter:user.saveSettings', { settings: settings, data: data }, next);
},
function (result, next) {

@ -1,6 +1,6 @@
<script>
window.addEventListener('load', function () {
define('/assets/templates/500.js', function () {
define(config.relative_path + '/assets/templates/500.js', function () {
function compiled(helpers, context, get, iter, helper) {
return '<div class="alert alert-danger">\n\t<strong>[[global:500.title]]</strong>\n\t<p>[[global:500.message]]</p>\n\t<p>' +
helpers.__escape(get(context && context['path'])) + '</p>\n\t' +

@ -1080,14 +1080,12 @@ describe('Topic\'s', function () {
});
it('should mark topic notifications read', function (done) {
var socketPosts = require('../src/socket.io/posts');
async.waterfall([
function (next) {
socketTopics.follow({ uid: adminUid }, tid, next);
},
function (next) {
socketPosts.reply({ uid: uid }, { content: 'some content', tid: tid }, next);
topics.reply({ uid: uid, timestamp: Date.now(), content: 'some content', tid: tid }, next);
},
function (data, next) {
setTimeout(next, 2500);

Loading…
Cancel
Save