Merge remote-tracking branch 'refs/remotes/origin/master' into develop

v1.18.x
Barış Soner Uşaklı 7 years ago
commit 7a2d6fe22d

@ -60,12 +60,12 @@
"mousetrap": "^1.6.1",
"mubsub": "^1.4.0",
"nconf": "^0.9.1",
"nodebb-plugin-composer-default": "6.0.11",
"nodebb-plugin-composer-default": "6.0.12",
"nodebb-plugin-dbsearch": "2.0.9",
"nodebb-plugin-emoji": "2.1.0",
"nodebb-plugin-emoji-android": "2.0.0",
"nodebb-plugin-markdown": "8.3.0",
"nodebb-plugin-mentions": "2.2.2",
"nodebb-plugin-mentions": "2.2.3",
"nodebb-plugin-soundpack-default": "1.0.0",
"nodebb-plugin-spam-be-gone": "0.5.1",
"nodebb-rewards-essentials": "0.0.11",
@ -73,7 +73,7 @@
"nodebb-theme-persona": "7.2.20",
"nodebb-theme-slick": "1.1.4",
"nodebb-theme-vanilla": "8.1.9",
"nodebb-widget-essentials": "4.0.1",
"nodebb-widget-essentials": "4.0.2",
"nodemailer": "4.4.1",
"passport": "^0.4.0",
"passport-local": "1.0.0",

@ -2,6 +2,7 @@
"available": "Available Widgets",
"explanation": "Select a widget from the dropdown menu and then drag and drop it into a template's widget area on the left.",
"none-installed": "No widgets found! Activate the essential widgets plugin in the <a href=\"%1\">plugins</a> control panel.",
"clone-from": "Clone widgets from",
"containers.available": "Available Containers",
"containers.explanation": "Drag and drop on top of any active widget",
"containers.none": "None",
@ -14,6 +15,8 @@
"alert.confirm-delete": "Are you sure you wish to delete this widget?",
"alert.updated": "Widgets Updated",
"alert.update-success": "Successfully updated widgets"
"alert.update-success": "Successfully updated widgets",
"alert.clone-success": "Successfully cloned widgets",
"error.select-clone": "Please select a page to clone from"
}

@ -18,7 +18,7 @@
"chat.seven_days": "7天",
"chat.thirty_days": "30天",
"chat.three_months": "3个月",
"chat.delete_message_confirm": "确认删除此消息吗?",
"chat.delete_message_confirm": "你确定删除此消息吗?",
"chat.add-users-to-room": "向此聊天室中添加成员",
"chat.confirm-chat-with-dnd-user": "该用户将其状态设置为DnD请勿打扰。 你还想和他们聊天吗?",
"composer.compose": "编写帮助",

@ -19,6 +19,7 @@
@import "./appearance/themes";
@import "./extend/plugins";
@import "./extend/rewards";
@import "./extend/widgets";
@import "./advanced/database";
@import "./advanced/logs";
@import "./advanced/errors";

@ -38,8 +38,14 @@
background-size: contain;
}
.mdl-card__supporting-text h2 {
margin-bottom: 15px;
.mdl-card__supporting-text {
font-size: 1.5rem;
margin: 0 auto;
.mdl-card__title-text {
display: inline-block;
margin-bottom: 15px;
}
}
}

@ -0,0 +1,19 @@
.page-extend-widgets {
[component="clone"] {
display: flex;
align-items: stretch;
align-content: stretch;
[component="clone/button"] {
flex-grow: 1;
text-align: left;
}
.dropdown-menu {
max-height: 300px;
overflow-y: scroll;
min-width: 250px;
border-radius: 0;
}
}
}

@ -25,6 +25,7 @@ define('admin/extend/widgets', ['jqueryui'], function () {
$('#widget-selector').trigger('change');
loadWidgetData();
setupCloneButton();
};
function prepareWidgets() {
@ -224,5 +225,51 @@ define('admin/extend/widgets', ['jqueryui'], function () {
});
}
function setupCloneButton() {
var clone = $('[component="clone"]');
var cloneBtn = $('[component="clone/button"]');
clone.find('.dropdown-menu li').on('click', function () {
var template = $(this).find('a').text();
cloneBtn.translateHtml('[[admin/extend/widgets:clone-from]] <strong>' + template + '</strong>');
cloneBtn.attr('data-template', template);
});
cloneBtn.on('click', function () {
var template = cloneBtn.attr('data-template');
if (!template) {
return app.alertError('[[admin/extend/widgets:error.select-clone]]');
}
var currentTemplate = $('#active-widgets .active.tab-pane[data-template] .area');
var templateToClone = $('#active-widgets .tab-pane[data-template="' + template + '"] .area');
var currentAreas = currentTemplate.map(function () {
return $(this).attr('data-location');
}).get();
var areasToClone = templateToClone.map(function () {
var location = $(this).attr('data-location');
return currentAreas.indexOf(location) !== -1 ? location : undefined;
}).get().filter(function (i) { return i; });
function clone(location) {
$('#active-widgets .tab-pane[data-template="' + template + '"] [data-location="' + location + '"]').each(function () {
$(this).find('[data-widget]').each(function () {
var widget = $(this).clone(true);
$('#active-widgets .active.tab-pane[data-template]:not([data-template="global"]) [data-location="' + location + '"] .widget-area').append(widget);
});
});
}
for (var i = 0, ii = areasToClone.length; i < ii; i++) {
var location = areasToClone[i];
clone(location);
}
app.alertSuccess('[[admin/extend/widgets:alert.clone-success]]');
});
}
return Widgets;
});

@ -67,7 +67,8 @@ define('admin/general/navigation', ['translator', 'iconSelect', 'benchpress', 'j
data.enabled = false;
data.index = (parseInt($('#enabled').children().last().attr('data-index'), 10) || 0) + 1;
data.title = translator.escape(data.title);
data.text = translator.escape(data.text);
Benchpress.parse('admin/general/navigation', 'navigation', { navigation: [data] }, function (li) {
translator.translate(li, function (li) {
li = $(translator.unescape(li));

@ -279,7 +279,7 @@ module.exports = function (db, module) {
callback = callback || helpers.noop;
value = parseInt(value, 10);
if (!key || isNaN(value)) {
return callback();
return callback(null, null);
}
var data = {};

@ -117,14 +117,18 @@ module.exports = function (redisClient, module) {
};
module.incrObjectField = function (key, field, callback) {
redisClient.hincrby(key, field, 1, callback);
module.incrObjectFieldBy(key, field, 1, callback);
};
module.decrObjectField = function (key, field, callback) {
redisClient.hincrby(key, field, -1, callback);
module.incrObjectFieldBy(key, field, -1, callback);
};
module.incrObjectFieldBy = function (key, field, value, callback) {
value = parseInt(value, 10);
if (!key || isNaN(value)) {
return callback(null, null);
}
redisClient.hincrby(key, field, value, callback);
};
};

@ -24,8 +24,8 @@ module.exports = function (Topics) {
}, next);
},
function (results, next) {
var tids = results.tagTids.concat(results.searchTids).concat(results.categoryTids);
tids = _.uniq(tids).filter(function (_tid) {
var tids = _.shuffle(_.uniq(results.tagTids.concat(results.searchTids).concat(results.categoryTids)));
tids = tids.filter(function (_tid) {
return parseInt(_tid, 10) !== parseInt(tid, 10);
});
@ -59,10 +59,10 @@ module.exports = function (Topics) {
function getSearchTids(tid, callback) {
async.waterfall([
function (next) {
Topics.getTopicField(tid, 'title', next);
Topics.getTopicFields(tid, ['title', 'cid'], next);
},
function (title, next) {
search.searchQuery('topic', title, [], [], next);
function (topicData, next) {
search.searchQuery('topic', topicData.title, [topicData.cid], [], next);
},
], callback);
}

@ -1,5 +1,5 @@
<div id="skins" class="skins">
<div class="directory row" id="bootstrap_themes">
<div class="directory row text-center" id="bootstrap_themes">
<i class="fa fa-refresh fa-spin"></i> [[admin/appearance/skins:loading]]
</div>

@ -1,5 +1,5 @@
<div id="themes" class="themes">
<div class="directory row" id="installed_themes">
<div class="directory row text-center" id="installed_themes">
<i class="fa fa-refresh fa-spin"></i> [[admin/appearance/themes:checking-for-installed]]
</div>
</div>

@ -59,6 +59,20 @@
</div>
<!-- END availableWidgets -->
</div>
<div class="btn-group" component="clone">
<button type="button" class="btn btn-primary" component="clone/button">[[admin/extend/widgets:clone-from]] ...</button>
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right">
<!-- BEGIN templates -->
<!-- IF !@first -->
<li><a href="#">{templates.template}</a></li>
<!-- END -->
<!-- END templates -->
</ul>
</div>
</div>
</div>
</div>

@ -1,174 +1,169 @@
<div class="row">
<form role="form" class="category" data-cid="{category.cid}">
<div class="row">
<div class="col-md-3 pull-right">
<select id="category-selector" class="form-control">
<!-- BEGIN allCategories -->
<option value="{allCategories.value}" <!-- IF allCategories.selected -->selected<!-- ENDIF allCategories.selected -->>{allCategories.text}</option>
<!-- END allCategories -->
</select>
</div>
<form role="form" class="category" data-cid="{category.cid}">
<div class="row">
<div class="col-md-3 pull-right">
<select id="category-selector" class="form-control">
<!-- BEGIN allCategories -->
<option value="{allCategories.value}" <!-- IF allCategories.selected -->selected<!-- ENDIF allCategories.selected -->>{allCategories.text}</option>
<!-- END allCategories -->
</select>
</div>
</div>
<br/>
<br/>
<div class="tab-content">
<div class="tab-pane fade active in row" id="category-settings">
<div class="col-md-9">
<div class="category-settings-form">
<fieldset>
<label for="cid-{category.cid}-name">
[[admin/manage/categories:name]]
</label>
<input id="cid-{category.cid}-name" type="text" class="form-control" placeholder="[[admin/manage/categories:name]]" data-name="name" value="{category.name}" /><br />
<div class="row">
<div class="col-md-9" id="category-settings">
<div class="category-settings-form">
<fieldset>
<label for="cid-{category.cid}-name">
[[admin/manage/categories:name]]
</label>
<input id="cid-{category.cid}-name" type="text" class="form-control" placeholder="[[admin/manage/categories:name]]" data-name="name" value="{category.name}" /><br />
<label for="cid-{category.cid}-description">
[[admin/manage/categories:description]]
</label>
<input id="cid-{category.cid}-description" data-name="description" placeholder="[[admin/manage/categories:description]]" value="{category.description}" class="form-control category_description description" /><br />
</fieldset>
<label for="cid-{category.cid}-description">
[[admin/manage/categories:description]]
</label>
<input id="cid-{category.cid}-description" data-name="description" placeholder="[[admin/manage/categories:description]]" value="{category.description}" class="form-control category_description description" /><br />
</fieldset>
<fieldset class="row">
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-bgColor">
[[admin/manage/categories:bg-color]]
</label>
<input id="cid-{category.cid}-bgColor" placeholder="#0059b2" data-name="bgColor" value="{category.bgColor}" class="form-control category_bgColor" />
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-color">
[[admin/manage/categories:text-color]]
</label>
<input id="cid-{category.cid}-color" placeholder="#fff" data-name="color" value="{category.color}" class="form-control category_color" />
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-imageClass">
[[admin/manage/categories:bg-image-size]]
</label>
<select id="cid-{category.cid}-imageClass" class="form-control" data-name="imageClass" data-value="{category.imageClass}">
<option value="auto">auto</option>
<option value="cover">cover</option>
<option value="contain">contain</option>
</select>
</div>
</div><br />
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-class">
[[admin/manage/categories:custom-class]]
</label>
<input id="cid-{category.cid}-class" type="text" class="form-control" placeholder="col-md-6 col-xs-6" data-name="class" value="{category.class}" />
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-numRecentReplies">
[[admin/manage/categories:num-recent-replies]]
</label>
<input id="cid-{category.cid}-numRecentReplies" type="text" class="form-control" placeholder="2" data-name="numRecentReplies" value="{category.numRecentReplies}" />
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-link">
[[admin/manage/categories:ext-link]]
</label>
<input id="cid-{category.cid}-link" type="text" class="form-control" placeholder="http://domain.com" data-name="link" value="{category.link}" />
</div>
</div>
<div class="col-sm-6 col-xs-12">
<div class="form-group">
<div class="checkbox">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input type="checkbox" class="mdl-switch__input" id="cid-{category.cid}-isSection" data-name="isSection" <!-- IF category.isSection -->checked<!-- ENDIF category.isSection --> />
<span class="mdl-switch__label"><strong>[[admin/manage/categories:is-section]]</strong></span>
</label>
</div>
</div>
<fieldset class="row">
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-bgColor">
[[admin/manage/categories:bg-color]]
</label>
<input id="cid-{category.cid}-bgColor" placeholder="#0059b2" data-name="bgColor" value="{category.bgColor}" class="form-control category_bgColor" />
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-color">
[[admin/manage/categories:text-color]]
</label>
<input id="cid-{category.cid}-color" placeholder="#fff" data-name="color" value="{category.color}" class="form-control category_color" />
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-imageClass">
[[admin/manage/categories:bg-image-size]]
</label>
<select id="cid-{category.cid}-imageClass" class="form-control" data-name="imageClass" data-value="{category.imageClass}">
<option value="auto">auto</option>
<option value="cover">cover</option>
<option value="contain">contain</option>
</select>
</div>
</div><br />
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-class">
[[admin/manage/categories:custom-class]]
</label>
<input id="cid-{category.cid}-class" type="text" class="form-control" placeholder="col-md-6 col-xs-6" data-name="class" value="{category.class}" />
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-numRecentReplies">
[[admin/manage/categories:num-recent-replies]]
</label>
<input id="cid-{category.cid}-numRecentReplies" type="text" class="form-control" placeholder="2" data-name="numRecentReplies" value="{category.numRecentReplies}" />
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="form-group">
<label for="cid-{category.cid}-link">
[[admin/manage/categories:ext-link]]
</label>
<input id="cid-{category.cid}-link" type="text" class="form-control" placeholder="http://domain.com" data-name="link" value="{category.link}" />
</div>
</div>
<div class="col-sm-6 col-xs-12">
<div class="form-group">
<div class="checkbox">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input type="checkbox" class="mdl-switch__input" id="cid-{category.cid}-isSection" data-name="isSection" <!-- IF category.isSection -->checked<!-- ENDIF category.isSection --> />
<span class="mdl-switch__label"><strong>[[admin/manage/categories:is-section]]</strong></span>
</label>
</div>
</fieldset>
<fieldset>
<label for="tag-whitelist">Tag Whitelist</label><br />
<input id="tag-whitelist" type="text" class="form-control" placeholder="Enter category tags here" data-name="tagWhitelist" value="" />
</fieldset>
</div>
</div>
</div>
</fieldset>
<fieldset>
<label for="tag-whitelist">Tag Whitelist</label><br />
<input id="tag-whitelist" type="text" class="form-control" placeholder="Enter category tags here" data-name="tagWhitelist" value="" />
</fieldset>
</div>
</div>
<div class="col-md-3 options acp-sidebar">
<div class="panel panel-default">
<div class="panel-body">
<div class="category-preview" style="
<!-- IF category.backgroundImage -->background-image: url({category.backgroundImage});<!-- ENDIF category.backgroundImage -->
<!-- IF category.bgColor -->background-color: {category.bgColor};<!-- ENDIF category.bgColor -->
<!-- IF category.imageClass -->background-size: {category.imageClass};<!-- ENDIF category.imageClass -->
color: {category.color};
">
<div class="icon">
<i data-name="icon" value="{category.icon}" class="fa {category.icon} fa-2x"></i>
</div>
</div>
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" data-cid="{category.cid}" class="btn btn-default upload-button">
<i class="fa fa-upload"></i>
[[admin/manage/categories:upload-image]]
</button>
</div>
<!-- IF category.image -->
<div class="btn-group">
<button class="btn btn-warning delete-image">
<i data-name="icon" value="fa-times" class="fa fa-times"></i>
[[admin/manage/categories:delete-image]]
</button>
</div>
<!-- ENDIF category.image -->
</div><br />
<div class="col-md-3 options acp-sidebar">
<div class="panel panel-default">
<div class="panel-body">
<div class="category-preview" style="
<!-- IF category.backgroundImage -->background-image: url({category.backgroundImage});<!-- ENDIF category.backgroundImage -->
<!-- IF category.bgColor -->background-color: {category.bgColor};<!-- ENDIF category.bgColor -->
<!-- IF category.imageClass -->background-size: {category.imageClass};<!-- ENDIF category.imageClass -->
color: {category.color};
">
<div class="icon">
<i data-name="icon" value="{category.icon}" class="fa {category.icon} fa-2x"></i>
</div>
</div>
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" data-cid="{category.cid}" class="btn btn-default upload-button">
<i class="fa fa-upload"></i>
[[admin/manage/categories:upload-image]]
</button>
</div>
<!-- IF category.image -->
<div class="btn-group">
<button class="btn btn-warning delete-image">
<i data-name="icon" value="fa-times" class="fa fa-times"></i>
[[admin/manage/categories:delete-image]]
</button>
</div>
<!-- ENDIF category.image -->
</div><br />
<fieldset>
<div class="form-group text-center">
<label for="category-image">
[[admin/manage/categories:category-image]]
</label>
<br/>
<input id="category-image" type="text" class="form-control" placeholder="[[admin/manage/categories:category-image]]" data-name="image" value="{category.image}" />
</div>
</fieldset>
<fieldset>
<div class="form-group text-center">
<label for="category-image">
[[admin/manage/categories:category-image]]
</label>
<br/>
<input id="category-image" type="text" class="form-control" placeholder="[[admin/manage/categories:category-image]]" data-name="image" value="{category.image}" />
</div>
</fieldset>
<fieldset>
<div class="form-group text-center">
<label for="cid-{category.cid}-parentCid">[[admin/manage/categories:parent-category]]</label>
<br/>
<div class="btn-group <!-- IF !category.parent.name -->hide<!-- ENDIF !category.parent.name -->">
<button type="button" class="btn btn-default" data-action="changeParent" data-parentCid="{category.parent.cid}"><i class="fa {category.parent.icon}"></i> {category.parent.name}</button>
<button type="button" class="btn btn-warning" data-action="removeParent" data-parentCid="{category.parent.cid}"><i class="fa fa-times"></i></button>
</div>
<button type="button" class="btn btn-default btn-block <!-- IF category.parent.name -->hide<!-- ENDIF category.parent.name -->" data-action="setParent">
<i class="fa fa-sitemap"></i>
[[admin/manage/categories:parent-category-none]]
</button>
</div>
</fieldset>
<hr/>
<button class="btn btn-info btn-block copy-settings">
<i class="fa fa-files-o"></i> [[admin/manage/categories:copy-settings]]
</button>
<hr />
<button class="btn btn-danger btn-block purge">
<i class="fa fa-eraser"></i> [[admin/manage/categories:purge]]
<fieldset>
<div class="form-group text-center">
<label for="cid-{category.cid}-parentCid">[[admin/manage/categories:parent-category]]</label>
<br/>
<div class="btn-group <!-- IF !category.parent.name -->hide<!-- ENDIF !category.parent.name -->">
<button type="button" class="btn btn-default" data-action="changeParent" data-parentCid="{category.parent.cid}"><i class="fa {category.parent.icon}"></i> {category.parent.name}</button>
<button type="button" class="btn btn-warning" data-action="removeParent" data-parentCid="{category.parent.cid}"><i class="fa fa-times"></i></button>
</div>
<button type="button" class="btn btn-default btn-block <!-- IF category.parent.name -->hide<!-- ENDIF category.parent.name -->" data-action="setParent">
<i class="fa fa-sitemap"></i>
[[admin/manage/categories:parent-category-none]]
</button>
</div>
</div>
</fieldset>
<hr/>
<button class="btn btn-info btn-block copy-settings">
<i class="fa fa-files-o"></i> [[admin/manage/categories:copy-settings]]
</button>
<hr />
<button class="btn btn-danger btn-block purge">
<i class="fa fa-eraser"></i> [[admin/manage/categories:purge]]
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</form>
<button id="save" class="floating-button mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored">
<i class="material-icons">save</i>

@ -1,6 +1,6 @@
<div class="row">
<div class="col-xs-12">
<div class="post-queue panel panel-primary">
<div class="post-queue panel panel-primary preventSlideout">
<div class="panel-heading">
[[admin/manage/post-queue:post-queue]]
</div>

@ -438,5 +438,17 @@ describe('Hash methods', function () {
done();
});
});
it('should return null if value is NaN', function (done) {
db.incrObjectFieldBy('testObject15', 'lastonline', 'notanumber', function (err, newValue) {
assert.ifError(err);
assert.strictEqual(newValue, null);
db.isObjectField('testObject15', 'lastonline', function (err, isField) {
assert.ifError(err);
assert(!isField);
done();
});
});
});
});
});

Loading…
Cancel
Save