mirror of
https://github.com/flarum/framework.git
synced 2025-02-22 08:10:13 +08:00
Improve permissions page
- Introduce the concept of "required permissions" - basically a permission dependency tree. In order for a group to be granted one permission, they must also have another. - Improve redraw performance by not building dropdown menu contents until dropdown is opened ref #904
This commit is contained in:
parent
1177880483
commit
240aa9e83b
167
js/admin/dist/app.js
vendored
167
js/admin/dist/app.js
vendored
@ -16609,6 +16609,22 @@ System.register('flarum/app', ['flarum/App', 'flarum/initializers/store', 'flaru
|
|||||||
|
|
||||||
app.extensionSettings = {};
|
app.extensionSettings = {};
|
||||||
|
|
||||||
|
app.getRequiredPermissions = function (permission) {
|
||||||
|
var required = [];
|
||||||
|
|
||||||
|
if (permission === 'startDiscussion' || permission.indexOf('discussion.') === 0) {
|
||||||
|
required.push('viewDiscussions');
|
||||||
|
}
|
||||||
|
if (permission === 'discussion.delete') {
|
||||||
|
required.push('discussion.hide');
|
||||||
|
}
|
||||||
|
if (permission === 'discussion.deletePosts') {
|
||||||
|
required.push('discussion.editPosts');
|
||||||
|
}
|
||||||
|
|
||||||
|
return required;
|
||||||
|
};
|
||||||
|
|
||||||
_export('default', app);
|
_export('default', app);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -18080,13 +18096,18 @@ System.register('flarum/components/Dropdown', ['flarum/Component', 'flarum/helpe
|
|||||||
}
|
}
|
||||||
|
|
||||||
babelHelpers.createClass(Dropdown, [{
|
babelHelpers.createClass(Dropdown, [{
|
||||||
|
key: 'init',
|
||||||
|
value: function init() {
|
||||||
|
this.showing = false;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
key: 'view',
|
key: 'view',
|
||||||
value: function view() {
|
value: function view() {
|
||||||
var items = this.props.children ? listItems(this.props.children) : [];
|
var items = this.props.children ? listItems(this.props.children) : [];
|
||||||
|
|
||||||
return m(
|
return m(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'ButtonGroup Dropdown dropdown ' + this.props.className + ' itemCount' + items.length },
|
{ className: 'ButtonGroup Dropdown dropdown ' + this.props.className + ' itemCount' + items.length + (this.showing ? ' open' : '') },
|
||||||
this.getButton(),
|
this.getButton(),
|
||||||
this.getMenu(items)
|
this.getMenu(items)
|
||||||
);
|
);
|
||||||
@ -18102,25 +18123,32 @@ System.register('flarum/components/Dropdown', ['flarum/Component', 'flarum/helpe
|
|||||||
// bottom of the viewport. If it does, we will apply class to make it show
|
// bottom of the viewport. If it does, we will apply class to make it show
|
||||||
// above the toggle button instead of below it.
|
// above the toggle button instead of below it.
|
||||||
this.$().on('shown.bs.dropdown', function () {
|
this.$().on('shown.bs.dropdown', function () {
|
||||||
|
_this2.showing = true;
|
||||||
|
|
||||||
|
if (_this2.props.onshow) {
|
||||||
|
_this2.props.onshow();
|
||||||
|
}
|
||||||
|
|
||||||
|
m.redraw();
|
||||||
|
|
||||||
var $menu = _this2.$('.Dropdown-menu');
|
var $menu = _this2.$('.Dropdown-menu');
|
||||||
var isRight = $menu.hasClass('Dropdown-menu--right');
|
var isRight = $menu.hasClass('Dropdown-menu--right');
|
||||||
|
|
||||||
$menu.removeClass('Dropdown-menu--top Dropdown-menu--right');
|
$menu.removeClass('Dropdown-menu--top Dropdown-menu--right');
|
||||||
|
|
||||||
$menu.toggleClass('Dropdown-menu--top', $menu.offset().top + $menu.height() > $(window).scrollTop() + $(window).height());
|
$menu.toggleClass('Dropdown-menu--top', $menu.offset().top + $menu.height() > $(window).scrollTop() + $(window).height());
|
||||||
|
|
||||||
$menu.toggleClass('Dropdown-menu--right', isRight || $menu.offset().left + $menu.width() > $(window).scrollLeft() + $(window).width());
|
$menu.toggleClass('Dropdown-menu--right', isRight || $menu.offset().left + $menu.width() > $(window).scrollLeft() + $(window).width());
|
||||||
|
|
||||||
if (_this2.props.onshow) {
|
|
||||||
_this2.props.onshow();
|
|
||||||
m.redraw();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$().on('hidden.bs.dropdown', function () {
|
this.$().on('hidden.bs.dropdown', function () {
|
||||||
|
_this2.showing = false;
|
||||||
|
|
||||||
if (_this2.props.onhide) {
|
if (_this2.props.onhide) {
|
||||||
_this2.props.onhide();
|
_this2.props.onhide();
|
||||||
m.redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.redraw();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -19513,8 +19541,8 @@ System.register('flarum/components/Page', ['flarum/Component'], function (_expor
|
|||||||
});;
|
});;
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
System.register('flarum/components/PermissionDropdown', ['flarum/components/Dropdown', 'flarum/components/Button', 'flarum/components/Separator', 'flarum/models/Group', 'flarum/components/GroupBadge'], function (_export, _context) {
|
System.register('flarum/components/PermissionDropdown', ['flarum/components/Dropdown', 'flarum/components/Button', 'flarum/components/Separator', 'flarum/models/Group', 'flarum/components/Badge', 'flarum/components/GroupBadge'], function (_export, _context) {
|
||||||
var Dropdown, Button, Separator, Group, GroupBadge, PermissionDropdown;
|
var Dropdown, Button, Separator, Group, Badge, GroupBadge, PermissionDropdown;
|
||||||
|
|
||||||
|
|
||||||
function badgeForId(id) {
|
function badgeForId(id) {
|
||||||
@ -19523,6 +19551,30 @@ System.register('flarum/components/PermissionDropdown', ['flarum/components/Drop
|
|||||||
return group ? GroupBadge.component({ group: group, label: null }) : '';
|
return group ? GroupBadge.component({ group: group, label: null }) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterByRequiredPermissions(groupIds, permission) {
|
||||||
|
app.getRequiredPermissions(permission).forEach(function (required) {
|
||||||
|
var restrictToGroupIds = app.data.permissions[required] || [];
|
||||||
|
|
||||||
|
if (restrictToGroupIds.indexOf(Group.GUEST_ID) !== -1) {
|
||||||
|
// do nothing
|
||||||
|
} else if (restrictToGroupIds.indexOf(Group.MEMBER_ID) !== -1) {
|
||||||
|
groupIds = groupIds.filter(function (id) {
|
||||||
|
return id !== Group.GUEST_ID;
|
||||||
|
});
|
||||||
|
} else if (groupIds.indexOf(Group.MEMBER_ID) !== -1) {
|
||||||
|
groupIds = restrictToGroupIds;
|
||||||
|
} else {
|
||||||
|
groupIds = restrictToGroupIds.filter(function (id) {
|
||||||
|
return groupIds.indexOf(id) !== -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
groupIds = filterByRequiredPermissions(groupIds, required);
|
||||||
|
});
|
||||||
|
|
||||||
|
return groupIds;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setters: [function (_flarumComponentsDropdown) {
|
setters: [function (_flarumComponentsDropdown) {
|
||||||
Dropdown = _flarumComponentsDropdown.default;
|
Dropdown = _flarumComponentsDropdown.default;
|
||||||
@ -19532,6 +19584,8 @@ System.register('flarum/components/PermissionDropdown', ['flarum/components/Drop
|
|||||||
Separator = _flarumComponentsSeparator.default;
|
Separator = _flarumComponentsSeparator.default;
|
||||||
}, function (_flarumModelsGroup) {
|
}, function (_flarumModelsGroup) {
|
||||||
Group = _flarumModelsGroup.default;
|
Group = _flarumModelsGroup.default;
|
||||||
|
}, function (_flarumComponentsBadge) {
|
||||||
|
Badge = _flarumComponentsBadge.default;
|
||||||
}, function (_flarumComponentsGroupBadge) {
|
}, function (_flarumComponentsGroupBadge) {
|
||||||
GroupBadge = _flarumComponentsGroupBadge.default;
|
GroupBadge = _flarumComponentsGroupBadge.default;
|
||||||
}],
|
}],
|
||||||
@ -19552,56 +19606,64 @@ System.register('flarum/components/PermissionDropdown', ['flarum/components/Drop
|
|||||||
this.props.children = [];
|
this.props.children = [];
|
||||||
|
|
||||||
var groupIds = app.data.permissions[this.props.permission] || [];
|
var groupIds = app.data.permissions[this.props.permission] || [];
|
||||||
|
|
||||||
|
groupIds = filterByRequiredPermissions(groupIds, this.props.permission);
|
||||||
|
|
||||||
var everyone = groupIds.indexOf(Group.GUEST_ID) !== -1;
|
var everyone = groupIds.indexOf(Group.GUEST_ID) !== -1;
|
||||||
var members = groupIds.indexOf(Group.MEMBER_ID) !== -1;
|
var members = groupIds.indexOf(Group.MEMBER_ID) !== -1;
|
||||||
var adminGroup = app.store.getById('groups', Group.ADMINISTRATOR_ID);
|
var adminGroup = app.store.getById('groups', Group.ADMINISTRATOR_ID);
|
||||||
|
|
||||||
if (everyone) {
|
if (everyone) {
|
||||||
this.props.label = app.translator.trans('core.admin.permissions_controls.everyone_button');
|
this.props.label = Badge.component({ icon: 'globe' });
|
||||||
} else if (members) {
|
} else if (members) {
|
||||||
this.props.label = app.translator.trans('core.admin.permissions_controls.members_button');
|
this.props.label = Badge.component({ icon: 'user' });
|
||||||
} else {
|
} else {
|
||||||
this.props.label = [badgeForId(Group.ADMINISTRATOR_ID), groupIds.map(badgeForId)];
|
this.props.label = [badgeForId(Group.ADMINISTRATOR_ID), groupIds.map(badgeForId)];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.allowGuest) {
|
if (this.showing) {
|
||||||
|
if (this.props.allowGuest) {
|
||||||
|
this.props.children.push(Button.component({
|
||||||
|
children: [Badge.component({ icon: 'globe' }), ' ', app.translator.trans('core.admin.permissions_controls.everyone_button')],
|
||||||
|
icon: everyone ? 'check' : true,
|
||||||
|
onclick: function onclick() {
|
||||||
|
return _this2.save([Group.GUEST_ID]);
|
||||||
|
},
|
||||||
|
disabled: this.isGroupDisabled(Group.GUEST_ID)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
this.props.children.push(Button.component({
|
this.props.children.push(Button.component({
|
||||||
children: app.translator.trans('core.admin.permissions_controls.everyone_button'),
|
children: [Badge.component({ icon: 'user' }), ' ', app.translator.trans('core.admin.permissions_controls.members_button')],
|
||||||
icon: everyone ? 'check' : true,
|
icon: members ? 'check' : true,
|
||||||
onclick: function onclick() {
|
onclick: function onclick() {
|
||||||
return _this2.save([Group.GUEST_ID]);
|
return _this2.save([Group.MEMBER_ID]);
|
||||||
}
|
},
|
||||||
}));
|
disabled: this.isGroupDisabled(Group.MEMBER_ID)
|
||||||
}
|
}), Separator.component(), Button.component({
|
||||||
|
children: [badgeForId(adminGroup.id()), ' ', adminGroup.namePlural()],
|
||||||
this.props.children.push(Button.component({
|
icon: !everyone && !members ? 'check' : true,
|
||||||
children: app.translator.trans('core.admin.permissions_controls.members_button'),
|
disabled: !everyone && !members,
|
||||||
icon: members ? 'check' : true,
|
|
||||||
onclick: function onclick() {
|
|
||||||
return _this2.save([Group.MEMBER_ID]);
|
|
||||||
}
|
|
||||||
}), Separator.component(), Button.component({
|
|
||||||
children: [GroupBadge.component({ group: adminGroup, label: null }), ' ', adminGroup.namePlural()],
|
|
||||||
icon: !everyone && !members ? 'check' : true,
|
|
||||||
disabled: !everyone && !members,
|
|
||||||
onclick: function onclick(e) {
|
|
||||||
if (e.shiftKey) e.stopPropagation();
|
|
||||||
_this2.save([]);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
[].push.apply(this.props.children, app.store.all('groups').filter(function (group) {
|
|
||||||
return [Group.ADMINISTRATOR_ID, Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()) === -1;
|
|
||||||
}).map(function (group) {
|
|
||||||
return Button.component({
|
|
||||||
children: [GroupBadge.component({ group: group, label: null }), ' ', group.namePlural()],
|
|
||||||
icon: groupIds.indexOf(group.id()) !== -1 ? 'check' : true,
|
|
||||||
onclick: function onclick(e) {
|
onclick: function onclick(e) {
|
||||||
if (e.shiftKey) e.stopPropagation();
|
if (e.shiftKey) e.stopPropagation();
|
||||||
_this2.toggle(group.id());
|
_this2.save([]);
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}));
|
|
||||||
|
[].push.apply(this.props.children, app.store.all('groups').filter(function (group) {
|
||||||
|
return [Group.ADMINISTRATOR_ID, Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()) === -1;
|
||||||
|
}).map(function (group) {
|
||||||
|
return Button.component({
|
||||||
|
children: [badgeForId(group.id()), ' ', group.namePlural()],
|
||||||
|
icon: groupIds.indexOf(group.id()) !== -1 ? 'check' : true,
|
||||||
|
onclick: function onclick(e) {
|
||||||
|
if (e.shiftKey) e.stopPropagation();
|
||||||
|
_this2.toggle(group.id());
|
||||||
|
},
|
||||||
|
disabled: _this2.isGroupDisabled(group.id()) && _this2.isGroupDisabled(Group.MEMBER_ID) && _this2.isGroupDisabled(Group.GUEST_ID)
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return babelHelpers.get(Object.getPrototypeOf(PermissionDropdown.prototype), 'view', this).call(this);
|
return babelHelpers.get(Object.getPrototypeOf(PermissionDropdown.prototype), 'view', this).call(this);
|
||||||
}
|
}
|
||||||
@ -19638,6 +19700,11 @@ System.register('flarum/components/PermissionDropdown', ['flarum/components/Drop
|
|||||||
|
|
||||||
this.save(groupIds);
|
this.save(groupIds);
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'isGroupDisabled',
|
||||||
|
value: function isGroupDisabled(id) {
|
||||||
|
return filterByRequiredPermissions([id], this.props.permission).indexOf(id) === -1;
|
||||||
|
}
|
||||||
}], [{
|
}], [{
|
||||||
key: 'initProps',
|
key: 'initProps',
|
||||||
value: function initProps(props) {
|
value: function initProps(props) {
|
||||||
@ -19749,7 +19816,7 @@ System.register('flarum/components/PermissionGrid', ['flarum/Component', 'flarum
|
|||||||
m(
|
m(
|
||||||
'th',
|
'th',
|
||||||
null,
|
null,
|
||||||
child.icon ? icon(child.icon) : '',
|
icon(child.icon),
|
||||||
child.label
|
child.label
|
||||||
),
|
),
|
||||||
permissionCells(child),
|
permissionCells(child),
|
||||||
@ -19871,10 +19938,10 @@ System.register('flarum/components/PermissionGrid', ['flarum/Component', 'flarum
|
|||||||
value: function moderateItems() {
|
value: function moderateItems() {
|
||||||
var items = new ItemList();
|
var items = new ItemList();
|
||||||
|
|
||||||
items.add('viewPostIps', {
|
items.add('viewIpsPosts', {
|
||||||
icon: 'bullseye',
|
icon: 'bullseye',
|
||||||
label: app.translator.trans('core.admin.permissions.view_post_ips_label'),
|
label: app.translator.trans('core.admin.permissions.view_post_ips_label'),
|
||||||
permission: 'discussion.viewPostIps'
|
permission: 'discussion.viewIpsPosts'
|
||||||
}, 110);
|
}, 110);
|
||||||
|
|
||||||
items.add('renameDiscussions', {
|
items.add('renameDiscussions', {
|
||||||
@ -23100,11 +23167,13 @@ System.register('flarum/utils/string', [], function (_export, _context) {
|
|||||||
_export('slug', slug);
|
_export('slug', slug);
|
||||||
|
|
||||||
function getPlainContent(string) {
|
function getPlainContent(string) {
|
||||||
var dom = $('<div/>').html(string.replace(/(<\/p>|<br>)/g, '$1 '));
|
var html = string.replace(/(<\/p>|<br>)/g, '$1 ').replace(/<img\b[^>]*>/ig, ' ');
|
||||||
|
|
||||||
|
var dom = $('<div/>').html(html);
|
||||||
|
|
||||||
dom.find(getPlainContent.removeSelectors.join(',')).remove();
|
dom.find(getPlainContent.removeSelectors.join(',')).remove();
|
||||||
|
|
||||||
return dom.text();
|
return dom.text().replace(/\s+/g, ' ').trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,4 +14,20 @@ app.initializers.add('boot', boot, -100);
|
|||||||
|
|
||||||
app.extensionSettings = {};
|
app.extensionSettings = {};
|
||||||
|
|
||||||
|
app.getRequiredPermissions = function(permission) {
|
||||||
|
const required = [];
|
||||||
|
|
||||||
|
if (permission === 'startDiscussion' || permission.indexOf('discussion.') === 0) {
|
||||||
|
required.push('viewDiscussions');
|
||||||
|
}
|
||||||
|
if (permission === 'discussion.delete') {
|
||||||
|
required.push('discussion.hide');
|
||||||
|
}
|
||||||
|
if (permission === 'discussion.deletePosts') {
|
||||||
|
required.push('discussion.editPosts');
|
||||||
|
}
|
||||||
|
|
||||||
|
return required;
|
||||||
|
};
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
@ -2,6 +2,7 @@ import Dropdown from 'flarum/components/Dropdown';
|
|||||||
import Button from 'flarum/components/Button';
|
import Button from 'flarum/components/Button';
|
||||||
import Separator from 'flarum/components/Separator';
|
import Separator from 'flarum/components/Separator';
|
||||||
import Group from 'flarum/models/Group';
|
import Group from 'flarum/models/Group';
|
||||||
|
import Badge from 'flarum/components/Badge';
|
||||||
import GroupBadge from 'flarum/components/GroupBadge';
|
import GroupBadge from 'flarum/components/GroupBadge';
|
||||||
|
|
||||||
function badgeForId(id) {
|
function badgeForId(id) {
|
||||||
@ -10,6 +11,27 @@ function badgeForId(id) {
|
|||||||
return group ? GroupBadge.component({group, label: null}) : '';
|
return group ? GroupBadge.component({group, label: null}) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterByRequiredPermissions(groupIds, permission) {
|
||||||
|
app.getRequiredPermissions(permission)
|
||||||
|
.forEach(required => {
|
||||||
|
const restrictToGroupIds = app.data.permissions[required] || [];
|
||||||
|
|
||||||
|
if (restrictToGroupIds.indexOf(Group.GUEST_ID) !== -1) {
|
||||||
|
// do nothing
|
||||||
|
} else if (restrictToGroupIds.indexOf(Group.MEMBER_ID) !== -1) {
|
||||||
|
groupIds = groupIds.filter(id => id !== Group.GUEST_ID);
|
||||||
|
} else if (groupIds.indexOf(Group.MEMBER_ID) !== -1) {
|
||||||
|
groupIds = restrictToGroupIds;
|
||||||
|
} else {
|
||||||
|
groupIds = restrictToGroupIds.filter(id => groupIds.indexOf(id) !== -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
groupIds = filterByRequiredPermissions(groupIds, required);
|
||||||
|
});
|
||||||
|
|
||||||
|
return groupIds;
|
||||||
|
}
|
||||||
|
|
||||||
export default class PermissionDropdown extends Dropdown {
|
export default class PermissionDropdown extends Dropdown {
|
||||||
static initProps(props) {
|
static initProps(props) {
|
||||||
super.initProps(props);
|
super.initProps(props);
|
||||||
@ -21,15 +43,18 @@ export default class PermissionDropdown extends Dropdown {
|
|||||||
view() {
|
view() {
|
||||||
this.props.children = [];
|
this.props.children = [];
|
||||||
|
|
||||||
const groupIds = app.data.permissions[this.props.permission] || [];
|
let groupIds = app.data.permissions[this.props.permission] || [];
|
||||||
|
|
||||||
|
groupIds = filterByRequiredPermissions(groupIds, this.props.permission);
|
||||||
|
|
||||||
const everyone = groupIds.indexOf(Group.GUEST_ID) !== -1;
|
const everyone = groupIds.indexOf(Group.GUEST_ID) !== -1;
|
||||||
const members = groupIds.indexOf(Group.MEMBER_ID) !== -1;
|
const members = groupIds.indexOf(Group.MEMBER_ID) !== -1;
|
||||||
const adminGroup = app.store.getById('groups', Group.ADMINISTRATOR_ID);
|
const adminGroup = app.store.getById('groups', Group.ADMINISTRATOR_ID);
|
||||||
|
|
||||||
if (everyone) {
|
if (everyone) {
|
||||||
this.props.label = app.translator.trans('core.admin.permissions_controls.everyone_button');
|
this.props.label = Badge.component({icon: 'globe'});
|
||||||
} else if (members) {
|
} else if (members) {
|
||||||
this.props.label = app.translator.trans('core.admin.permissions_controls.members_button');
|
this.props.label = Badge.component({icon: 'user'});
|
||||||
} else {
|
} else {
|
||||||
this.props.label = [
|
this.props.label = [
|
||||||
badgeForId(Group.ADMINISTRATOR_ID),
|
badgeForId(Group.ADMINISTRATOR_ID),
|
||||||
@ -37,50 +62,55 @@ export default class PermissionDropdown extends Dropdown {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.allowGuest) {
|
if (this.showing) {
|
||||||
|
if (this.props.allowGuest) {
|
||||||
|
this.props.children.push(
|
||||||
|
Button.component({
|
||||||
|
children: [Badge.component({icon: 'globe'}), ' ', app.translator.trans('core.admin.permissions_controls.everyone_button')],
|
||||||
|
icon: everyone ? 'check' : true,
|
||||||
|
onclick: () => this.save([Group.GUEST_ID]),
|
||||||
|
disabled: this.isGroupDisabled(Group.GUEST_ID)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.props.children.push(
|
this.props.children.push(
|
||||||
Button.component({
|
Button.component({
|
||||||
children: app.translator.trans('core.admin.permissions_controls.everyone_button'),
|
children: [Badge.component({icon: 'user'}), ' ', app.translator.trans('core.admin.permissions_controls.members_button')],
|
||||||
icon: everyone ? 'check' : true,
|
icon: members ? 'check' : true,
|
||||||
onclick: () => this.save([Group.GUEST_ID])
|
onclick: () => this.save([Group.MEMBER_ID]),
|
||||||
|
disabled: this.isGroupDisabled(Group.MEMBER_ID)
|
||||||
|
}),
|
||||||
|
|
||||||
|
Separator.component(),
|
||||||
|
|
||||||
|
Button.component({
|
||||||
|
children: [badgeForId(adminGroup.id()), ' ', adminGroup.namePlural()],
|
||||||
|
icon: !everyone && !members ? 'check' : true,
|
||||||
|
disabled: !everyone && !members,
|
||||||
|
onclick: e => {
|
||||||
|
if (e.shiftKey) e.stopPropagation();
|
||||||
|
this.save([]);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
[].push.apply(
|
||||||
|
this.props.children,
|
||||||
|
app.store.all('groups')
|
||||||
|
.filter(group => [Group.ADMINISTRATOR_ID, Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()) === -1)
|
||||||
|
.map(group => Button.component({
|
||||||
|
children: [badgeForId(group.id()), ' ', group.namePlural()],
|
||||||
|
icon: groupIds.indexOf(group.id()) !== -1 ? 'check' : true,
|
||||||
|
onclick: (e) => {
|
||||||
|
if (e.shiftKey) e.stopPropagation();
|
||||||
|
this.toggle(group.id());
|
||||||
|
},
|
||||||
|
disabled: this.isGroupDisabled(group.id()) && this.isGroupDisabled(Group.MEMBER_ID) && this.isGroupDisabled(Group.GUEST_ID)
|
||||||
|
}))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.children.push(
|
|
||||||
Button.component({
|
|
||||||
children: app.translator.trans('core.admin.permissions_controls.members_button'),
|
|
||||||
icon: members ? 'check' : true,
|
|
||||||
onclick: () => this.save([Group.MEMBER_ID])
|
|
||||||
}),
|
|
||||||
|
|
||||||
Separator.component(),
|
|
||||||
|
|
||||||
Button.component({
|
|
||||||
children: [GroupBadge.component({group: adminGroup, label: null}), ' ', adminGroup.namePlural()],
|
|
||||||
icon: !everyone && !members ? 'check' : true,
|
|
||||||
disabled: !everyone && !members,
|
|
||||||
onclick: e => {
|
|
||||||
if (e.shiftKey) e.stopPropagation();
|
|
||||||
this.save([]);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
[].push.apply(
|
|
||||||
this.props.children,
|
|
||||||
app.store.all('groups')
|
|
||||||
.filter(group => [Group.ADMINISTRATOR_ID, Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()) === -1)
|
|
||||||
.map(group => Button.component({
|
|
||||||
children: [GroupBadge.component({group, label: null}), ' ', group.namePlural()],
|
|
||||||
icon: groupIds.indexOf(group.id()) !== -1 ? 'check' : true,
|
|
||||||
onclick: (e) => {
|
|
||||||
if (e.shiftKey) e.stopPropagation();
|
|
||||||
this.toggle(group.id());
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
return super.view();
|
return super.view();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,4 +142,8 @@ export default class PermissionDropdown extends Dropdown {
|
|||||||
|
|
||||||
this.save(groupIds);
|
this.save(groupIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isGroupDisabled(id) {
|
||||||
|
return filterByRequiredPermissions([id], this.props.permission).indexOf(id) === -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ export default class PermissionGrid extends Component {
|
|||||||
</tr>
|
</tr>
|
||||||
{section.children.map(child => (
|
{section.children.map(child => (
|
||||||
<tr className="PermissionGrid-child">
|
<tr className="PermissionGrid-child">
|
||||||
<th>{child.icon ? icon(child.icon) : ''}{child.label}</th>
|
<th>{icon(child.icon)}{child.label}</th>
|
||||||
{permissionCells(child)}
|
{permissionCells(child)}
|
||||||
<td/>
|
<td/>
|
||||||
</tr>
|
</tr>
|
||||||
|
26
js/forum/dist/app.js
vendored
26
js/forum/dist/app.js
vendored
@ -21457,13 +21457,18 @@ System.register('flarum/components/Dropdown', ['flarum/Component', 'flarum/helpe
|
|||||||
}
|
}
|
||||||
|
|
||||||
babelHelpers.createClass(Dropdown, [{
|
babelHelpers.createClass(Dropdown, [{
|
||||||
|
key: 'init',
|
||||||
|
value: function init() {
|
||||||
|
this.showing = false;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
key: 'view',
|
key: 'view',
|
||||||
value: function view() {
|
value: function view() {
|
||||||
var items = this.props.children ? listItems(this.props.children) : [];
|
var items = this.props.children ? listItems(this.props.children) : [];
|
||||||
|
|
||||||
return m(
|
return m(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'ButtonGroup Dropdown dropdown ' + this.props.className + ' itemCount' + items.length },
|
{ className: 'ButtonGroup Dropdown dropdown ' + this.props.className + ' itemCount' + items.length + (this.showing ? ' open' : '') },
|
||||||
this.getButton(),
|
this.getButton(),
|
||||||
this.getMenu(items)
|
this.getMenu(items)
|
||||||
);
|
);
|
||||||
@ -21479,25 +21484,32 @@ System.register('flarum/components/Dropdown', ['flarum/Component', 'flarum/helpe
|
|||||||
// bottom of the viewport. If it does, we will apply class to make it show
|
// bottom of the viewport. If it does, we will apply class to make it show
|
||||||
// above the toggle button instead of below it.
|
// above the toggle button instead of below it.
|
||||||
this.$().on('shown.bs.dropdown', function () {
|
this.$().on('shown.bs.dropdown', function () {
|
||||||
|
_this2.showing = true;
|
||||||
|
|
||||||
|
if (_this2.props.onshow) {
|
||||||
|
_this2.props.onshow();
|
||||||
|
}
|
||||||
|
|
||||||
|
m.redraw();
|
||||||
|
|
||||||
var $menu = _this2.$('.Dropdown-menu');
|
var $menu = _this2.$('.Dropdown-menu');
|
||||||
var isRight = $menu.hasClass('Dropdown-menu--right');
|
var isRight = $menu.hasClass('Dropdown-menu--right');
|
||||||
|
|
||||||
$menu.removeClass('Dropdown-menu--top Dropdown-menu--right');
|
$menu.removeClass('Dropdown-menu--top Dropdown-menu--right');
|
||||||
|
|
||||||
$menu.toggleClass('Dropdown-menu--top', $menu.offset().top + $menu.height() > $(window).scrollTop() + $(window).height());
|
$menu.toggleClass('Dropdown-menu--top', $menu.offset().top + $menu.height() > $(window).scrollTop() + $(window).height());
|
||||||
|
|
||||||
$menu.toggleClass('Dropdown-menu--right', isRight || $menu.offset().left + $menu.width() > $(window).scrollLeft() + $(window).width());
|
$menu.toggleClass('Dropdown-menu--right', isRight || $menu.offset().left + $menu.width() > $(window).scrollLeft() + $(window).width());
|
||||||
|
|
||||||
if (_this2.props.onshow) {
|
|
||||||
_this2.props.onshow();
|
|
||||||
m.redraw();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$().on('hidden.bs.dropdown', function () {
|
this.$().on('hidden.bs.dropdown', function () {
|
||||||
|
_this2.showing = false;
|
||||||
|
|
||||||
if (_this2.props.onhide) {
|
if (_this2.props.onhide) {
|
||||||
_this2.props.onhide();
|
_this2.props.onhide();
|
||||||
m.redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.redraw();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
@ -29,11 +29,15 @@ export default class Dropdown extends Component {
|
|||||||
props.caretIcon = typeof props.caretIcon !== 'undefined' ? props.caretIcon : 'caret-down';
|
props.caretIcon = typeof props.caretIcon !== 'undefined' ? props.caretIcon : 'caret-down';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.showing = false;
|
||||||
|
}
|
||||||
|
|
||||||
view() {
|
view() {
|
||||||
const items = this.props.children ? listItems(this.props.children) : [];
|
const items = this.props.children ? listItems(this.props.children) : [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'ButtonGroup Dropdown dropdown ' + this.props.className + ' itemCount' + items.length}>
|
<div className={'ButtonGroup Dropdown dropdown ' + this.props.className + ' itemCount' + items.length + (this.showing ? ' open' : '')}>
|
||||||
{this.getButton()}
|
{this.getButton()}
|
||||||
{this.getMenu(items)}
|
{this.getMenu(items)}
|
||||||
</div>
|
</div>
|
||||||
@ -47,8 +51,17 @@ export default class Dropdown extends Component {
|
|||||||
// bottom of the viewport. If it does, we will apply class to make it show
|
// bottom of the viewport. If it does, we will apply class to make it show
|
||||||
// above the toggle button instead of below it.
|
// above the toggle button instead of below it.
|
||||||
this.$().on('shown.bs.dropdown', () => {
|
this.$().on('shown.bs.dropdown', () => {
|
||||||
|
this.showing = true;
|
||||||
|
|
||||||
|
if (this.props.onshow) {
|
||||||
|
this.props.onshow();
|
||||||
|
}
|
||||||
|
|
||||||
|
m.redraw();
|
||||||
|
|
||||||
const $menu = this.$('.Dropdown-menu');
|
const $menu = this.$('.Dropdown-menu');
|
||||||
const isRight = $menu.hasClass('Dropdown-menu--right');
|
const isRight = $menu.hasClass('Dropdown-menu--right');
|
||||||
|
|
||||||
$menu.removeClass('Dropdown-menu--top Dropdown-menu--right');
|
$menu.removeClass('Dropdown-menu--top Dropdown-menu--right');
|
||||||
|
|
||||||
$menu.toggleClass(
|
$menu.toggleClass(
|
||||||
@ -60,18 +73,16 @@ export default class Dropdown extends Component {
|
|||||||
'Dropdown-menu--right',
|
'Dropdown-menu--right',
|
||||||
isRight || $menu.offset().left + $menu.width() > $(window).scrollLeft() + $(window).width()
|
isRight || $menu.offset().left + $menu.width() > $(window).scrollLeft() + $(window).width()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.props.onshow) {
|
|
||||||
this.props.onshow();
|
|
||||||
m.redraw();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$().on('hidden.bs.dropdown', () => {
|
this.$().on('hidden.bs.dropdown', () => {
|
||||||
|
this.showing = false;
|
||||||
|
|
||||||
if (this.props.onhide) {
|
if (this.props.onhide) {
|
||||||
this.props.onhide();
|
this.props.onhide();
|
||||||
m.redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.redraw();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
td, th {
|
td, th {
|
||||||
padding: 10px 0;
|
padding: 5px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
td {
|
td {
|
||||||
@ -65,11 +65,6 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tr:last-child {
|
|
||||||
td, th {
|
|
||||||
padding-bottom: 15px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.Dropdown {
|
.Dropdown {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
@ -79,12 +74,15 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
float: none;
|
float: none;
|
||||||
}
|
}
|
||||||
|
.Dropdown-menu {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.Button {
|
.Button {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
.Badge {
|
.Badge {
|
||||||
margin: -3px 0;
|
margin: -3px 2px -3px 0;
|
||||||
vertical-align: 0;
|
vertical-align: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,15 +111,17 @@
|
|||||||
}
|
}
|
||||||
.PermissionGrid-section {
|
.PermissionGrid-section {
|
||||||
td, th {
|
td, th {
|
||||||
padding-top: 15px;
|
padding-top: 20px;
|
||||||
border-top: 1px solid @control-bg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.PermissionGrid-child {
|
.PermissionGrid-child {
|
||||||
td, th {
|
td, th {
|
||||||
padding: 5px 0;
|
position: relative;
|
||||||
}
|
}
|
||||||
th {
|
th {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
&:hover {
|
||||||
|
background: lighten(@control-bg, 3%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user