mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-12 08:55:47 +01:00
closes #2779
This commit is contained in:
@@ -99,6 +99,48 @@ define('admin/manage/category', [
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.copy-settings').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
socket.emit('admin.categories.getNames', function(err, categories) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
templates.parse('admin/partials/categories/select-category', {
|
||||||
|
categories: categories
|
||||||
|
}, function(html) {
|
||||||
|
function submit() {
|
||||||
|
var formData = modal.find('form').serializeObject();
|
||||||
|
|
||||||
|
socket.emit('admin.categories.copySettingsFrom', {fromCid: formData['select-cid'], toCid: ajaxify.data.category.cid}, function(err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
app.alertSuccess('Settings Copied!');
|
||||||
|
ajaxify.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.modal('hide');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modal = bootbox.dialog({
|
||||||
|
title: 'Select a Category',
|
||||||
|
message: html,
|
||||||
|
buttons: {
|
||||||
|
save: {
|
||||||
|
label: 'Copy',
|
||||||
|
className: 'btn-primary',
|
||||||
|
callback: submit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.find('form').on('submit', submit);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$('.upload-button').on('click', function() {
|
$('.upload-button').on('click', function() {
|
||||||
var inputEl = $(this);
|
var inputEl = $(this);
|
||||||
var cid = inputEl.attr('data-cid');
|
var cid = inputEl.attr('data-cid');
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async'),
|
var async = require('async');
|
||||||
db = require('../database'),
|
|
||||||
privileges = require('../privileges'),
|
var db = require('../database');
|
||||||
plugins = require('../plugins'),
|
var privileges = require('../privileges');
|
||||||
utils = require('../../public/src/utils');
|
var groups = require('../groups');
|
||||||
|
var plugins = require('../plugins');
|
||||||
|
var utils = require('../../public/src/utils');
|
||||||
|
|
||||||
module.exports = function(Categories) {
|
module.exports = function(Categories) {
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ module.exports = function(Categories) {
|
|||||||
db.incrObjectField('global', 'nextCid', next);
|
db.incrObjectField('global', 'nextCid', next);
|
||||||
},
|
},
|
||||||
function(cid, next) {
|
function(cid, next) {
|
||||||
|
data.name = data.name || 'Category ' + cid;
|
||||||
var slug = cid + '/' + utils.slugify(data.name);
|
var slug = cid + '/' + utils.slugify(data.name);
|
||||||
var order = data.order || cid; // If no order provided, place it at the end
|
var order = data.order || cid; // If no order provided, place it at the end
|
||||||
var colours = Categories.assignColours();
|
var colours = Categories.assignColours();
|
||||||
@@ -58,6 +61,12 @@ module.exports = function(Categories) {
|
|||||||
], next);
|
], next);
|
||||||
},
|
},
|
||||||
function(results, next) {
|
function(results, next) {
|
||||||
|
if (data.cloneFromCid && parseInt(data.cloneFromCid, 10)) {
|
||||||
|
return Categories.copySettingsFrom(data.cloneFromCid, category.cid, next);
|
||||||
|
}
|
||||||
|
next(null, category);
|
||||||
|
},
|
||||||
|
function(category, next) {
|
||||||
plugins.fireHook('action:category.create', category);
|
plugins.fireHook('action:category.create', category);
|
||||||
next(null, category);
|
next(null, category);
|
||||||
}
|
}
|
||||||
@@ -65,10 +74,94 @@ module.exports = function(Categories) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Categories.assignColours = function() {
|
Categories.assignColours = function() {
|
||||||
var backgrounds = ['#AB4642', '#DC9656', '#F7CA88', '#A1B56C', '#86C1B9', '#7CAFC2', '#BA8BAF', '#A16946'],
|
var backgrounds = ['#AB4642', '#DC9656', '#F7CA88', '#A1B56C', '#86C1B9', '#7CAFC2', '#BA8BAF', '#A16946'];
|
||||||
text = ['#fff', '#fff', '#333', '#fff', '#333', '#fff', '#fff', '#fff'],
|
var text = ['#fff', '#fff', '#333', '#fff', '#333', '#fff', '#fff', '#fff'];
|
||||||
index = Math.floor(Math.random() * backgrounds.length);
|
var index = Math.floor(Math.random() * backgrounds.length);
|
||||||
|
|
||||||
return [backgrounds[index], text[index]];
|
return [backgrounds[index], text[index]];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Categories.copySettingsFrom = function(fromCid, toCid, callback) {
|
||||||
|
var destination;
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
async.parallel({
|
||||||
|
source: async.apply(db.getObject, 'category:' + fromCid),
|
||||||
|
destination: async.apply(db.getObject, 'category:' + toCid)
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (results, next) {
|
||||||
|
if (!results.source) {
|
||||||
|
return next(new Error('[[error:invalid-cid]]'));
|
||||||
|
}
|
||||||
|
destination = results.destination;
|
||||||
|
|
||||||
|
var tasks = [];
|
||||||
|
if (parseInt(results.source.parentCid, 10)) {
|
||||||
|
tasks.push(async.apply(db.sortedSetAdd, 'cid:' + results.source.parentCid + ':children', results.source.order, toCid));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination && parseInt(destination.parentCid, 10)) {
|
||||||
|
tasks.push(async.apply(db.sortedSetRemove, 'cid:' + destination.parentCid + ':children', toCid));
|
||||||
|
}
|
||||||
|
|
||||||
|
destination.description = results.source.description;
|
||||||
|
destination.descriptionParsed = results.source.descriptionParsed;
|
||||||
|
destination.icon = results.source.icon;
|
||||||
|
destination.bgColor = results.source.bgColor;
|
||||||
|
destination.color = results.source.color;
|
||||||
|
destination.link = results.source.link;
|
||||||
|
destination.numRecentReplies = results.source.numRecentReplies;
|
||||||
|
destination.class = results.source.class;
|
||||||
|
destination.imageClass = results.source.imageClass;
|
||||||
|
destination.parentCid = results.source.parentCid || 0;
|
||||||
|
|
||||||
|
tasks.push(async.apply(db.setObject, 'category:' + toCid, destination));
|
||||||
|
|
||||||
|
async.series(tasks, next);
|
||||||
|
},
|
||||||
|
function (results, next) {
|
||||||
|
Categories.copyPrivilegesFrom(fromCid, toCid, next);
|
||||||
|
}
|
||||||
|
], function(err) {
|
||||||
|
callback(err, destination);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Categories.copyPrivilegesFrom = function(fromCid, toCid, callback) {
|
||||||
|
var privilegeList = [
|
||||||
|
'find', 'read', 'topics:create', 'topics:reply', 'purge', 'mods',
|
||||||
|
'groups:find', 'groups:read', 'groups:topics:create', 'groups:topics:reply', 'groups:purge', 'groups:moderate'
|
||||||
|
];
|
||||||
|
|
||||||
|
async.each(privilegeList, function(privilege, next) {
|
||||||
|
copyPrivilege(privilege, fromCid, toCid, next);
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
function copyPrivilege(privilege, fromCid, toCid, callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
db.getSortedSetRange('group:cid:' + toCid + ':privileges:' + privilege + ':members', 0, -1, next);
|
||||||
|
},
|
||||||
|
function (currentMembers, next) {
|
||||||
|
async.eachSeries(currentMembers, function(member, next) {
|
||||||
|
groups.leave('cid:' + toCid + ':privileges:' + privilege, member, next);
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
db.getSortedSetRange('group:cid:' + fromCid + ':privileges:' + privilege + ':members', 0, -1, next);
|
||||||
|
},
|
||||||
|
function (members, next) {
|
||||||
|
if (!members || !members.length) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
async.eachSeries(members, function(member, next) {
|
||||||
|
groups.join('cid:' + toCid + ':privileges:' + privilege, member, next);
|
||||||
|
}, next);
|
||||||
|
}
|
||||||
|
], callback);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var async = require('async'),
|
var async = require('async');
|
||||||
|
|
||||||
db = require('../../database'),
|
var db = require('../../database');
|
||||||
groups = require('../../groups'),
|
var groups = require('../../groups');
|
||||||
categories = require('../../categories'),
|
var categories = require('../../categories');
|
||||||
privileges = require('../../privileges'),
|
var privileges = require('../../privileges');
|
||||||
plugins = require('../../plugins'),
|
var plugins = require('../../plugins');
|
||||||
Categories = {};
|
var Categories = {};
|
||||||
|
|
||||||
Categories.create = function(socket, data, callback) {
|
Categories.create = function(socket, data, callback) {
|
||||||
if(!data) {
|
if (!data) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ Categories.purge = function(socket, cid, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Categories.update = function(socket, data, callback) {
|
Categories.update = function(socket, data, callback) {
|
||||||
if(!data) {
|
if (!data) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,4 +108,8 @@ function copyPrivilegesToChildrenRecursive(category, privilegeGroups, callback)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Categories.copySettingsFrom = function(socket, data, callback) {
|
||||||
|
categories.copySettingsFrom(data.fromCid, data.toCid, callback);
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = Categories;
|
module.exports = Categories;
|
||||||
@@ -105,7 +105,8 @@
|
|||||||
<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> (None)</button>
|
<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> (None)</button>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<hr/>
|
||||||
|
<button class="btn btn-info btn-block copy-settings"><i class="fa fa-files-o"></i> Copy Settings From</button>
|
||||||
<hr />
|
<hr />
|
||||||
<button class="btn btn-danger btn-block purge"><i class="fa fa-eraser"></i> Purge Category</button>
|
<button class="btn btn-danger btn-block purge"><i class="fa fa-eraser"></i> Purge Category</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,4 +12,14 @@
|
|||||||
<!-- END categories -->
|
<!-- END categories -->
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="cloneFromCid">(Optional) Clone Settings From Category</label>
|
||||||
|
<select class="form-control" name="cloneFromCid" id="cloneFromCid">
|
||||||
|
<option value=""></option>
|
||||||
|
<!-- BEGIN categories -->
|
||||||
|
<option value="{categories.cid}">{categories.name}</option>
|
||||||
|
<!-- END categories -->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
10
src/views/admin/partials/categories/select-category.tpl
Normal file
10
src/views/admin/partials/categories/select-category.tpl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<form type="form">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="select-cid">Select Category</label>
|
||||||
|
<select class="form-control" name="select-cid" id="select-cid">
|
||||||
|
<!-- BEGIN categories -->
|
||||||
|
<option value="{categories.cid}">{categories.name}</option>
|
||||||
|
<!-- END categories -->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
Reference in New Issue
Block a user