mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
feat: column based view on wide priv. tables (#9699)
* feat: column based view on wide priv. tables * fix: add group/user * feat: copy buttons to work on visible privs * feat: show what's being copied in modal * feat: optional title and message for category selector modal
This commit is contained in:
@@ -51,10 +51,13 @@
|
|||||||
"alert.saved": "Privilege changes saved and applied",
|
"alert.saved": "Privilege changes saved and applied",
|
||||||
"alert.confirm-discard": "Are you sure you wish to discard your privilege changes?",
|
"alert.confirm-discard": "Are you sure you wish to discard your privilege changes?",
|
||||||
"alert.discarded": "Privilege changes discarded",
|
"alert.discarded": "Privilege changes discarded",
|
||||||
"alert.confirm-copyToAll": "Are you sure you wish to apply this privilege set to <strong>all categories</strong>?",
|
"alert.confirm-copyToAll": "Are you sure you wish to apply this set of <strong>%1</strong> to <strong>all categories</strong>?",
|
||||||
"alert.confirm-copyToAllGroup": "Are you sure you wish to apply this group's privilege set to <strong>all categories</strong>?",
|
"alert.confirm-copyToAllGroup": "Are you sure you wish to apply this group's set of <strong>%1</strong> to <strong>all categories</strong>?",
|
||||||
"alert.confirm-copyToChildren": "Are you sure you wish to apply this privilege set to <strong>all descendant (child) categories</strong>?",
|
"alert.confirm-copyToChildren": "Are you sure you wish to apply this set of <strong>%1</strong> to <strong>all descendant (child) categories</strong>?",
|
||||||
"alert.confirm-copyToChildrenGroup": "Are you sure you wish to apply this group's privilege set to <strong>all descendant (child) categories</strong>?",
|
"alert.confirm-copyToChildrenGroup": "Are you sure you wish to apply this group's set of <strong>%1</strong> to <strong>all descendant (child) categories</strong>?",
|
||||||
"alert.no-undo": "<em>This action cannot be undone.</em>",
|
"alert.no-undo": "<em>This action cannot be undone.</em>",
|
||||||
"alert.admin-warning": "Administrators implicitly get all privileges"
|
"alert.admin-warning": "Administrators implicitly get all privileges",
|
||||||
|
"alert.copyPrivilegesFrom-title": "Select a category to copy from",
|
||||||
|
"alert.copyPrivilegesFrom-warning": "This will copy <strong>%1</strong> from the selected category.",
|
||||||
|
"alert.copyPrivilegesFromGroup-warning": "This will copy this group's set of <strong>%1</strong> from the selected category."
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,8 @@ define('admin/manage/privileges', [
|
|||||||
var Privileges = {};
|
var Privileges = {};
|
||||||
|
|
||||||
var cid;
|
var cid;
|
||||||
|
// number of columns to skip in category privilege tables
|
||||||
|
const SKIP_PRIV_COLS = 3;
|
||||||
|
|
||||||
Privileges.init = function () {
|
Privileges.init = function () {
|
||||||
cid = isNaN(parseInt(ajaxify.data.selectedCategory.cid, 10)) ? 'admin' : ajaxify.data.selectedCategory.cid;
|
cid = isNaN(parseInt(ajaxify.data.selectedCategory.cid, 10)) ? 'admin' : ajaxify.data.selectedCategory.cid;
|
||||||
@@ -33,6 +35,7 @@ define('admin/manage/privileges', [
|
|||||||
Privileges.setupPrivilegeTable();
|
Privileges.setupPrivilegeTable();
|
||||||
|
|
||||||
highlightRow();
|
highlightRow();
|
||||||
|
$('.privilege-filters button:last-child').click();
|
||||||
};
|
};
|
||||||
|
|
||||||
Privileges.setupPrivilegeTable = function () {
|
Privileges.setupPrivilegeTable = function () {
|
||||||
@@ -100,39 +103,43 @@ define('admin/manage/privileges', [
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.privilege-table-container').on('click', '[data-action="search.user"]', Privileges.addUserToPrivilegeTable);
|
const $privTableCon = $('.privilege-table-container');
|
||||||
$('.privilege-table-container').on('click', '[data-action="search.group"]', Privileges.addGroupToPrivilegeTable);
|
$privTableCon.on('click', '[data-action="search.user"]', Privileges.addUserToPrivilegeTable);
|
||||||
$('.privilege-table-container').on('click', '[data-action="copyToChildren"]', function () {
|
$privTableCon.on('click', '[data-action="search.group"]', Privileges.addGroupToPrivilegeTable);
|
||||||
|
$privTableCon.on('click', '[data-action="copyToChildren"]', function () {
|
||||||
throwConfirmModal('copyToChildren', Privileges.copyPrivilegesToChildren.bind(null, cid, ''));
|
throwConfirmModal('copyToChildren', Privileges.copyPrivilegesToChildren.bind(null, cid, ''));
|
||||||
});
|
});
|
||||||
$('.privilege-table-container').on('click', '[data-action="copyToChildrenGroup"]', function () {
|
$privTableCon.on('click', '[data-action="copyToChildrenGroup"]', function () {
|
||||||
var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
|
var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
|
||||||
throwConfirmModal('copyToChildrenGroup', Privileges.copyPrivilegesToChildren.bind(null, cid, groupName));
|
throwConfirmModal('copyToChildrenGroup', Privileges.copyPrivilegesToChildren.bind(null, cid, groupName));
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.privilege-table-container').on('click', '[data-action="copyPrivilegesFrom"]', function () {
|
$privTableCon.on('click', '[data-action="copyPrivilegesFrom"]', function () {
|
||||||
Privileges.copyPrivilegesFromCategory(cid, '');
|
Privileges.copyPrivilegesFromCategory(cid, '');
|
||||||
});
|
});
|
||||||
$('.privilege-table-container').on('click', '[data-action="copyPrivilegesFromGroup"]', function () {
|
$privTableCon.on('click', '[data-action="copyPrivilegesFromGroup"]', function () {
|
||||||
var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
|
var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
|
||||||
Privileges.copyPrivilegesFromCategory(cid, groupName);
|
Privileges.copyPrivilegesFromCategory(cid, groupName);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.privilege-table-container').on('click', '[data-action="copyToAll"]', function () {
|
$privTableCon.on('click', '[data-action="copyToAll"]', function () {
|
||||||
throwConfirmModal('copyToAll', Privileges.copyPrivilegesToAllCategories.bind(null, cid, ''));
|
throwConfirmModal('copyToAll', Privileges.copyPrivilegesToAllCategories.bind(null, cid, ''));
|
||||||
});
|
});
|
||||||
$('.privilege-table-container').on('click', '[data-action="copyToAllGroup"]', function () {
|
$privTableCon.on('click', '[data-action="copyToAllGroup"]', function () {
|
||||||
var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
|
var groupName = $(this).parents('[data-group-name]').attr('data-group-name');
|
||||||
throwConfirmModal('copyToAllGroup', Privileges.copyPrivilegesToAllCategories.bind(null, cid, groupName));
|
throwConfirmModal('copyToAllGroup', Privileges.copyPrivilegesToAllCategories.bind(null, cid, groupName));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$privTableCon.on('click', '.privilege-filters > button', filterPrivileges);
|
||||||
|
|
||||||
mousetrap.bind('ctrl+s', function (ev) {
|
mousetrap.bind('ctrl+s', function (ev) {
|
||||||
throwConfirmModal('save', Privileges.commit);
|
throwConfirmModal('save', Privileges.commit);
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
function throwConfirmModal(method, onConfirm) {
|
function throwConfirmModal(method, onConfirm) {
|
||||||
bootbox.confirm('[[admin/manage/privileges:alert.confirm-' + method + ']]<br /><br />[[admin/manage/privileges:alert.no-undo]]', function (ok) {
|
const privilegeSubset = getPrivilegeSubset();
|
||||||
|
bootbox.confirm(`[[admin/manage/privileges:alert.confirm-${method}, ${privilegeSubset}]]<br /><br />[[admin/manage/privileges:alert.no-undo]]`, function (ok) {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
onConfirm.call();
|
onConfirm.call();
|
||||||
}
|
}
|
||||||
@@ -175,9 +182,16 @@ define('admin/manage/privileges', [
|
|||||||
ajaxify.data.privileges = { ...ajaxify.data.privileges, ...privileges };
|
ajaxify.data.privileges = { ...ajaxify.data.privileges, ...privileges };
|
||||||
var tpl = parseInt(cid, 10) ? 'admin/partials/privileges/category' : 'admin/partials/privileges/global';
|
var tpl = parseInt(cid, 10) ? 'admin/partials/privileges/category' : 'admin/partials/privileges/global';
|
||||||
app.parseAndTranslate(tpl, { privileges }).then((html) => {
|
app.parseAndTranslate(tpl, { privileges }).then((html) => {
|
||||||
|
// Get currently selected filters
|
||||||
|
const btnIndices = $('.privilege-filters button.btn-warning').map((idx, el) => $(el).index()).get();
|
||||||
$('.privilege-table-container').html(html);
|
$('.privilege-table-container').html(html);
|
||||||
Privileges.exposeAssumedPrivileges();
|
Privileges.exposeAssumedPrivileges();
|
||||||
checkboxRowSelector.updateAll();
|
document.querySelectorAll('.privilege-filters').forEach((con, i) => {
|
||||||
|
// Three buttons, placed in reverse order
|
||||||
|
const lastIdx = $('.privilege-filters').first().find('button').length - 1;
|
||||||
|
const idx = btnIndices[i] === undefined ? lastIdx : btnIndices[i];
|
||||||
|
con.querySelectorAll('button')[idx].click();
|
||||||
|
});
|
||||||
|
|
||||||
hightlightRowByDataAttr('data-group-name', groupToHighlight);
|
hightlightRowByDataAttr('data-group-name', groupToHighlight);
|
||||||
});
|
});
|
||||||
@@ -254,7 +268,8 @@ define('admin/manage/privileges', [
|
|||||||
};
|
};
|
||||||
|
|
||||||
Privileges.copyPrivilegesToChildren = function (cid, group) {
|
Privileges.copyPrivilegesToChildren = function (cid, group) {
|
||||||
socket.emit('admin.categories.copyPrivilegesToChildren', { cid: cid, group: group }, function (err) {
|
const filter = getPrivilegeFilter();
|
||||||
|
socket.emit('admin.categories.copyPrivilegesToChildren', { cid, group, filter }, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return app.alertError(err.message);
|
return app.alertError(err.message);
|
||||||
}
|
}
|
||||||
@@ -263,12 +278,20 @@ define('admin/manage/privileges', [
|
|||||||
};
|
};
|
||||||
|
|
||||||
Privileges.copyPrivilegesFromCategory = function (cid, group) {
|
Privileges.copyPrivilegesFromCategory = function (cid, group) {
|
||||||
|
const privilegeSubset = getPrivilegeSubset();
|
||||||
|
const message = '<br>' +
|
||||||
|
(group ? `[[admin/manage/privileges:alert.copyPrivilegesFromGroup-warning, ${privilegeSubset}]]` :
|
||||||
|
`[[admin/manage/privileges:alert.copyPrivilegesFrom-warning, ${privilegeSubset}]]`) +
|
||||||
|
'<br><br>[[admin/manage/privileges:alert.no-undo]]';
|
||||||
categorySelector.modal({
|
categorySelector.modal({
|
||||||
|
title: '[[admin/manage/privileges:alert.copyPrivilegesFrom-title]]',
|
||||||
|
message,
|
||||||
localCategories: [],
|
localCategories: [],
|
||||||
showLinks: true,
|
showLinks: true,
|
||||||
onSubmit: function (selectedCategory) {
|
onSubmit: function (selectedCategory) {
|
||||||
socket.emit('admin.categories.copyPrivilegesFrom', {
|
socket.emit('admin.categories.copyPrivilegesFrom', {
|
||||||
toCid: cid,
|
toCid: cid,
|
||||||
|
filter: getPrivilegeFilter(),
|
||||||
fromCid: selectedCategory.cid,
|
fromCid: selectedCategory.cid,
|
||||||
group: group,
|
group: group,
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
@@ -282,7 +305,8 @@ define('admin/manage/privileges', [
|
|||||||
};
|
};
|
||||||
|
|
||||||
Privileges.copyPrivilegesToAllCategories = function (cid, group) {
|
Privileges.copyPrivilegesToAllCategories = function (cid, group) {
|
||||||
socket.emit('admin.categories.copyPrivilegesToAllCategories', { cid: cid, group: group }, function (err) {
|
const filter = getPrivilegeFilter();
|
||||||
|
socket.emit('admin.categories.copyPrivilegesToAllCategories', { cid, group, filter }, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return app.alertError(err.message);
|
return app.alertError(err.message);
|
||||||
}
|
}
|
||||||
@@ -369,9 +393,11 @@ define('admin/manage/privileges', [
|
|||||||
},
|
},
|
||||||
}, function (html) {
|
}, function (html) {
|
||||||
var tbodyEl = document.querySelector('.privilege-table tbody');
|
var tbodyEl = document.querySelector('.privilege-table tbody');
|
||||||
|
const btnIdx = $('.privilege-filters').first().find('button.btn-warning').index();
|
||||||
tbodyEl.append(html.get(0));
|
tbodyEl.append(html.get(0));
|
||||||
Privileges.exposeAssumedPrivileges();
|
Privileges.exposeAssumedPrivileges();
|
||||||
hightlightRowByDataAttr('data-group-name', group);
|
hightlightRowByDataAttr('data-group-name', group);
|
||||||
|
document.querySelector('.privilege-filters').querySelectorAll('button')[btnIdx].click();
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -406,11 +432,46 @@ define('admin/manage/privileges', [
|
|||||||
});
|
});
|
||||||
|
|
||||||
var tbodyEl = document.querySelectorAll('.privilege-table tbody');
|
var tbodyEl = document.querySelectorAll('.privilege-table tbody');
|
||||||
|
const btnIdx = $('.privilege-filters').last().find('button.btn-warning').index();
|
||||||
tbodyEl[1].append(html.get(0));
|
tbodyEl[1].append(html.get(0));
|
||||||
Privileges.exposeAssumedPrivileges();
|
Privileges.exposeAssumedPrivileges();
|
||||||
hightlightRowByDataAttr('data-uid', user.uid);
|
hightlightRowByDataAttr('data-uid', user.uid);
|
||||||
|
document.querySelectorAll('.privilege-filters')[1].querySelectorAll('button')[btnIdx].click();
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterPrivileges(ev) {
|
||||||
|
const [startIdx, endIdx] = ev.target.getAttribute('data-filter').split(',').map(i => parseInt(i, 10));
|
||||||
|
const rows = $(ev.target).closest('table')[0].querySelectorAll('thead tr:last-child, tbody tr ');
|
||||||
|
rows.forEach((tr) => {
|
||||||
|
tr.querySelectorAll('td, th').forEach((el, idx) => {
|
||||||
|
const offset = el.tagName.toUpperCase() === 'TH' ? 1 : 0;
|
||||||
|
if (idx < (SKIP_PRIV_COLS - offset)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
el.classList.toggle('hidden', !(idx >= (startIdx - offset) && idx <= (endIdx - offset)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
checkboxRowSelector.updateAll();
|
||||||
|
$(ev.target).siblings('button').toArray().forEach(btn => btn.classList.remove('btn-warning'));
|
||||||
|
ev.target.classList.add('btn-warning');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrivilegeFilter() {
|
||||||
|
const indices = document.querySelector('.privilege-filters .btn-warning')
|
||||||
|
.getAttribute('data-filter')
|
||||||
|
.split(',')
|
||||||
|
.map(i => parseInt(i, 10));
|
||||||
|
indices[0] -= SKIP_PRIV_COLS;
|
||||||
|
indices[1] = indices[1] - SKIP_PRIV_COLS + 1;
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrivilegeSubset() {
|
||||||
|
const currentPrivFilter = document.querySelector('.privilege-filters .btn-warning');
|
||||||
|
const filterText = currentPrivFilter ? currentPrivFilter.textContent.toLocaleLowerCase() : '';
|
||||||
|
return filterText.indexOf('privileges') > -1 ? filterText : `${filterText} privileges`.trim();
|
||||||
|
}
|
||||||
|
|
||||||
return Privileges;
|
return Privileges;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ define('admin/modules/checkboxRowSelector', function () {
|
|||||||
if (self.toggling) {
|
if (self.toggling) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const checkboxes = $checkboxEl.closest('tr').find('input:not([disabled])').toArray();
|
const checkboxes = $checkboxEl.closest('tr').find('input:not([disabled]):visible').toArray();
|
||||||
const $toggler = $(checkboxes.shift());
|
const $toggler = $(checkboxes.shift());
|
||||||
const rowState = checkboxes.length && checkboxes.every(el => el.checked);
|
const rowState = checkboxes.length && checkboxes.every(el => el.checked);
|
||||||
$toggler.prop('checked', rowState);
|
$toggler.prop('checked', rowState);
|
||||||
@@ -35,7 +35,7 @@ define('admin/modules/checkboxRowSelector', function () {
|
|||||||
function toggleAll($checkboxEl) {
|
function toggleAll($checkboxEl) {
|
||||||
self.toggling = true;
|
self.toggling = true;
|
||||||
const state = $checkboxEl.prop('checked');
|
const state = $checkboxEl.prop('checked');
|
||||||
$checkboxEl.closest('tr').find('input:not(.checkbox-helper)').each((idx, el) => {
|
$checkboxEl.closest('tr').find('input:not(.checkbox-helper):visible').each((idx, el) => {
|
||||||
const $checkbox = $(el);
|
const $checkbox = $(el);
|
||||||
if ($checkbox.prop('checked') === state) {
|
if ($checkbox.prop('checked') === state) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ define('categorySelector', [
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
options.onSelect = options.onSelect || function () {};
|
options.onSelect = options.onSelect || function () {};
|
||||||
options.onSubmit = options.onSubmit || function () {};
|
options.onSubmit = options.onSubmit || function () {};
|
||||||
app.parseAndTranslate('admin/partials/categories/select-category', {}, function (html) {
|
app.parseAndTranslate('admin/partials/categories/select-category', { message: options.message }, function (html) {
|
||||||
var modal = bootbox.dialog({
|
var modal = bootbox.dialog({
|
||||||
title: '[[modules:composer.select_category]]',
|
title: options.title || '[[modules:composer.select_category]]',
|
||||||
message: html,
|
message: html,
|
||||||
buttons: {
|
buttons: {
|
||||||
save: {
|
save: {
|
||||||
|
|||||||
@@ -199,13 +199,19 @@ module.exports = function (Categories) {
|
|||||||
cache.del(`cid:${toCid}:tag:whitelist`);
|
cache.del(`cid:${toCid}:tag:whitelist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
Categories.copyPrivilegesFrom = async function (fromCid, toCid, group) {
|
Categories.copyPrivilegesFrom = async function (fromCid, toCid, group, filter = []) {
|
||||||
group = group || '';
|
group = group || '';
|
||||||
|
let privsToCopy;
|
||||||
|
if (group) {
|
||||||
|
privsToCopy = privileges.categories.groupPrivilegeList.slice(...filter);
|
||||||
|
} else {
|
||||||
|
const privs = privileges.categories.privilegeList.slice();
|
||||||
|
const halfIdx = privs.length / 2;
|
||||||
|
privsToCopy = privs.slice(0, halfIdx).slice(...filter).concat(privs.slice(halfIdx).slice(...filter));
|
||||||
|
}
|
||||||
|
|
||||||
const data = await plugins.hooks.fire('filter:categories.copyPrivilegesFrom', {
|
const data = await plugins.hooks.fire('filter:categories.copyPrivilegesFrom', {
|
||||||
privileges: group ?
|
privileges: privsToCopy,
|
||||||
privileges.categories.groupPrivilegeList.slice() :
|
|
||||||
privileges.categories.privilegeList.slice(),
|
|
||||||
fromCid: fromCid,
|
fromCid: fromCid,
|
||||||
toCid: toCid,
|
toCid: toCid,
|
||||||
group: group,
|
group: group,
|
||||||
|
|||||||
@@ -73,15 +73,15 @@ Categories.copyPrivilegesToChildren = async function (socket, data) {
|
|||||||
const children = result[0];
|
const children = result[0];
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await copyPrivilegesToChildrenRecursive(data.cid, child, data.group);
|
await copyPrivilegesToChildrenRecursive(data.cid, child, data.group, data.filter);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function copyPrivilegesToChildrenRecursive(parentCid, category, group) {
|
async function copyPrivilegesToChildrenRecursive(parentCid, category, group, filter) {
|
||||||
await categories.copyPrivilegesFrom(parentCid, category.cid, group);
|
await categories.copyPrivilegesFrom(parentCid, category.cid, group, filter);
|
||||||
for (const child of category.children) {
|
for (const child of category.children) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await copyPrivilegesToChildrenRecursive(parentCid, child, group);
|
await copyPrivilegesToChildrenRecursive(parentCid, child, group, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ Categories.copySettingsFrom = async function (socket, data) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Categories.copyPrivilegesFrom = async function (socket, data) {
|
Categories.copyPrivilegesFrom = async function (socket, data) {
|
||||||
await categories.copyPrivilegesFrom(data.fromCid, data.toCid, data.group);
|
await categories.copyPrivilegesFrom(data.fromCid, data.toCid, data.group, data.filter);
|
||||||
};
|
};
|
||||||
|
|
||||||
Categories.copyPrivilegesToAllCategories = async function (socket, data) {
|
Categories.copyPrivilegesToAllCategories = async function (socket, data) {
|
||||||
@@ -98,6 +98,6 @@ Categories.copyPrivilegesToAllCategories = async function (socket, data) {
|
|||||||
cids = cids.filter(cid => parseInt(cid, 10) !== parseInt(data.cid, 10));
|
cids = cids.filter(cid => parseInt(cid, 10) !== parseInt(data.cid, 10));
|
||||||
for (const toCid of cids) {
|
for (const toCid of cids) {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await categories.copyPrivilegesFrom(data.cid, toCid, data.group);
|
await categories.copyPrivilegesFrom(data.cid, toCid, data.group, data.filter);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,4 +19,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
{{{ if message }}}
|
||||||
|
<div>{message}</div>
|
||||||
|
{{{ end }}}
|
||||||
@@ -2,21 +2,14 @@
|
|||||||
<table class="table table-striped privilege-table">
|
<table class="table table-striped privilege-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="privilege-table-header">
|
<tr class="privilege-table-header">
|
||||||
<th colspan="3"></th>
|
<th class="privilege-filters btn-toolbar" colspan="100">
|
||||||
<th class="arrowed" colspan="3">
|
<!-- IF privileges.columnCountGroupOther -->
|
||||||
[[admin/manage/categories:privileges.section-viewing]]
|
<button type="button" data-filter="19,99" class="btn btn-default pull-right">[[admin/manage/categories:privileges.section-other]]</button>
|
||||||
|
<!-- END -->
|
||||||
|
<button type="button" data-filter="16,18" class="btn btn-default pull-right">[[admin/manage/categories:privileges.section-moderation]]</button>
|
||||||
|
<button type="button" data-filter="6,15" class="btn btn-default pull-right">[[admin/manage/categories:privileges.section-posting]]</button>
|
||||||
|
<button type="button" data-filter="3,5" class="btn btn-default pull-right">[[admin/manage/categories:privileges.section-viewing]]</button>
|
||||||
</th>
|
</th>
|
||||||
<th class="arrowed" colspan="10">
|
|
||||||
[[admin/manage/categories:privileges.section-posting]]
|
|
||||||
</th>
|
|
||||||
<th class="arrowed" colspan="3">
|
|
||||||
[[admin/manage/categories:privileges.section-moderation]]
|
|
||||||
</th>
|
|
||||||
<!-- IF privileges.columnCountGroupOther -->
|
|
||||||
<th class="arrowed" colspan="{privileges.columnCountGroupOther}">
|
|
||||||
[[admin/manage/categories:privileges.section-other]]
|
|
||||||
</th>
|
|
||||||
<!-- END -->
|
|
||||||
</tr><tr><!-- zebrastripe reset --></tr>
|
</tr><tr><!-- zebrastripe reset --></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">[[admin/manage/categories:privileges.section-group]]</th>
|
<th colspan="2">[[admin/manage/categories:privileges.section-group]]</th>
|
||||||
@@ -92,21 +85,14 @@
|
|||||||
<table class="table table-striped privilege-table">
|
<table class="table table-striped privilege-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="privilege-table-header">
|
<tr class="privilege-table-header">
|
||||||
<th colspan="3"></th>
|
<th class="privilege-filters btn-toolbar" colspan="100">
|
||||||
<th class="arrowed" colspan="3">
|
<!-- IF privileges.columnCountUserOther -->
|
||||||
[[admin/manage/categories:privileges.section-viewing]]
|
<button type="button" data-filter="19,99" class="btn btn-default pull-right">[[admin/manage/categories:privileges.section-other]]</button>
|
||||||
|
<!-- END -->
|
||||||
|
<button type="button" data-filter="16,18" class="btn btn-default pull-right">[[admin/manage/categories:privileges.section-moderation]]</button>
|
||||||
|
<button type="button" data-filter="6,15" class="btn btn-default pull-right">[[admin/manage/categories:privileges.section-posting]]</button>
|
||||||
|
<button type="button" data-filter="3,5" class="btn btn-default pull-right">[[admin/manage/categories:privileges.section-viewing]]</button>
|
||||||
</th>
|
</th>
|
||||||
<th class="arrowed" colspan="10">
|
|
||||||
[[admin/manage/categories:privileges.section-posting]]
|
|
||||||
</th>
|
|
||||||
<th class="arrowed" colspan="3">
|
|
||||||
[[admin/manage/categories:privileges.section-moderation]]
|
|
||||||
</th>
|
|
||||||
<!-- IF privileges.columnCountUserOther -->
|
|
||||||
<th class="arrowed" colspan="{privileges.columnCountUserOther}">
|
|
||||||
[[admin/manage/categories:privileges.section-other]]
|
|
||||||
</th>
|
|
||||||
<!-- END -->
|
|
||||||
</tr><tr><!-- zebrastripe reset --></tr>
|
</tr><tr><!-- zebrastripe reset --></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">[[admin/manage/categories:privileges.section-user]]</th>
|
<th colspan="2">[[admin/manage/categories:privileges.section-user]]</th>
|
||||||
|
|||||||
Reference in New Issue
Block a user