Skip to content

Commit

Permalink
Merge pull request #170 from dew326/update-roles
Browse files Browse the repository at this point in the history
 EZP-28493: Interface improvements when assigning roles to user / groups
  • Loading branch information
Łukasz Serwatka authored Dec 14, 2017
2 parents d3b0e52 + 9ab9f5f commit 275f083
Show file tree
Hide file tree
Showing 14 changed files with 320 additions and 89 deletions.
88 changes: 43 additions & 45 deletions src/bundle/Controller/RoleAssignmentController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use eZ\Publish\API\Repository\RoleService;
use eZ\Publish\API\Repository\Values\User\Limitation\RoleLimitation;
use eZ\Publish\API\Repository\Values\User\Limitation\SectionLimitation;
use eZ\Publish\API\Repository\Values\User\Limitation\SubtreeLimitation;
use eZ\Publish\API\Repository\Values\User\Role;
Expand Down Expand Up @@ -85,55 +86,17 @@ public function listAction(Role $role): Response

public function createAction(Request $request, Role $role): Response
{
$form = $this->formFactory->createRoleAssignment(
new RoleAssignmentCreateData()
);
$form = $this->formFactory->createRoleAssignment(new RoleAssignmentCreateData());
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
if ($form->isSubmitted()) {
$result = $this->submitHandler->handle($form, function (RoleAssignmentCreateData $data) use ($role) {
$users = $data->getUsers();
$groups = $data->getGroups();
$sections = $data->getSections();
$locations = $data->getLocations();

$limitations = [];

if (empty($sections) && empty($locations)) {
$limitations[] = null;
} else {
if (!empty($sections)) {
$limitation = new SectionLimitation();

foreach ($sections as $section) {
$limitation->limitationValues[] = $section->id;
}

$limitations[] = $limitation;
}

if (!empty($locations)) {
$limitation = new SubtreeLimitation();

foreach ($locations as $location) {
$limitation->limitationValues[] = $location->pathString;
}

$limitations[] = $limitation;
foreach ($this->createLimitations($data) as $limitation) {
foreach ($data->getUsers() as $user) {
$this->roleService->assignRoleToUser($role, $user, $limitation);
}
}

foreach ($limitations as $limitation) {
if (!empty($users)) {
foreach ($users as $user) {
$this->roleService->assignRoleToUser($role, $user, $limitation);
}
}

if (!empty($groups)) {
foreach ($groups as $group) {
$this->roleService->assignRoleToUserGroup($role, $group, $limitation);
}
foreach ($data->getGroups() as $group) {
$this->roleService->assignRoleToUserGroup($role, $group, $limitation);
}
}

Expand Down Expand Up @@ -261,4 +224,39 @@ private function getRoleAssignmentsNumbers(array $roleAssignments): array

return array_combine($roleAssignmentsNumbers, array_fill_keys($roleAssignmentsNumbers, false));
}

/**
* @param RoleAssignmentCreateData $data
*
* @return RoleLimitation[]
*/
private function createLimitations(RoleAssignmentCreateData $data): array
{
$limitations = [];
switch ($data->getLimitationType()) {
case RoleAssignmentCreateData::LIMITATION_TYPE_LOCATION:
$limitation = new SubtreeLimitation();

foreach ($data->getLocations() as $location) {
$limitation->limitationValues[] = $location->pathString;
}

$limitations[] = $limitation;
break;
case RoleAssignmentCreateData::LIMITATION_TYPE_SECTION:
$limitation = new SectionLimitation();

foreach ($data->getSections() as $section) {
$limitation->limitationValues[] = $section->id;
}

$limitations[] = $limitation;
break;
case RoleAssignmentCreateData::LIMITATION_TYPE_NONE:
$limitations[] = null; // this acts as "no limitations"
break;
}

return $limitations;
}
}
43 changes: 28 additions & 15 deletions src/bundle/Resources/public/js/scripts/admin.role_assignment.add.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
(function () {
const btns = document.querySelectorAll('.btn--open-udw');
const udwContainer = document.getElementById('react-udw');
const token = document.querySelector('meta[name="CSRF-Token"]').content;
const siteaccess = document.querySelector('meta[name="SiteAccess"]').content;
(function (global, doc) {
const udwContainer = doc.getElementById('react-udw');
const limitationsRadio = [...doc.querySelectorAll('.ez-limitations__radio')];
const token = doc.querySelector('meta[name="CSRF-Token"]').content;
const siteaccess = doc.querySelector('meta[name="SiteAccess"]').content;
const closeUDW = () => udwContainer.innerHTML = '';
const onConfirm = (form, content) => {
const field = form.querySelector('#role_assignment_locations_value');
field.value = content.map(item => item.ContentInfo.Content._id).join();
const selectSubtreeConfirm = (data) => {
const selectedItems = data.reduce((total, item) => total + `<li>${item.ContentInfo.Content.Name}</li>`, '');

doc.querySelector('#role_assignment_create_locations').value = data.map(item => item.id).join();
doc.querySelector('.ez-limitations__selected-subtree').innerHTML = selectedItems;

closeUDW();
};
const onCancel = () => closeUDW();
const openUDW = (event) => {
const selectSubtree = (event) => {
event.preventDefault();

const form = event.target.closest('form[name=role_assignment]');
ReactDOM.render(React.createElement(eZ.modules.UniversalDiscovery, {
onConfirm: onConfirm.bind(this, form),
onCancel: onCancel,
onConfirm: selectSubtreeConfirm.bind(this),
onCancel: closeUDW,
multiple: true,
restInfo: {token, siteaccess}
}), udwContainer);
};
const toggleDisabledState = () => {
limitationsRadio.forEach(radio => {
const disableNode = doc.querySelector(radio.dataset.disableSelector);
const methodName = radio.checked ? 'removeAttribute' : 'setAttribute';

if (disableNode) {
disableNode[methodName]('disabled', 'disabled');
}
});
};

btns.forEach(btn => btn.addEventListener('click', openUDW, false));
})();
doc.querySelector('.ez-btn--select-subtree').addEventListener('click', selectSubtree, false);
limitationsRadio.forEach(radio => radio.addEventListener('change', toggleDisabledState, false));
})(window, document);
6 changes: 6 additions & 0 deletions src/bundle/Resources/public/scss/_buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,9 @@
.btn:disabled {
opacity: .3;
}

.ez-btn--select-subtree {
display: inline-flex;
align-items: center;
justify-content: center;
}
20 changes: 20 additions & 0 deletions src/bundle/Resources/public/scss/_icons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
.ez-icon {
width: 2rem;
height: 2rem;

&--small {
width: 1rem;
height: 1rem;
}

&--medium {
width: 1.5rem;
height: 1.5rem;
}

&--light {
fill: $ez-white;
}
}

.btn-icon {
Expand Down Expand Up @@ -169,3 +183,9 @@
}
}
}

.ez-btn--select-subtree {
.ez-icon {
margin-right: .5rem;
}
}
8 changes: 4 additions & 4 deletions src/bundle/Resources/translations/menu.en.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,10 @@
<target state="new">Discard changes</target>
<note>key: role_assignment_create__sidebar_right__cancel</note>
</trans-unit>
<trans-unit id="574bac165f9c298de0c0d06801b68ec7e331658b" resname="role_assignment_create__sidebar_right__create">
<source>Create</source>
<target state="new">Create</target>
<note>key: role_assignment_create__sidebar_right__create</note>
<trans-unit id="63bb349c122da33ab95d2e395ca9a62f8050bf66" resname="role_assignment_create__sidebar_right__save">
<source>Save</source>
<target state="new">Save</target>
<note>key: role_assignment_create__sidebar_right__save</note>
</trans-unit>
<trans-unit id="ec3a03215b15b79b7db72bac312b5e59734ac99c" resname="role_create__sidebar_right__cancel">
<source>Discard changes</source>
Expand Down
25 changes: 25 additions & 0 deletions src/bundle/Resources/translations/role.en.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
</header>
<body>
<trans-unit id="50fbff4724e8543718a7a0fe08fc1f134bbeb7d6" resname="limitation_type.none">
<source>No limitations</source>
<target state="new">No limitations</target>
<note>key: limitation_type.none</note>
</trans-unit>
<trans-unit id="e4eb27643d4149122e8009b8ca930678eadcd713" resname="limitation_type.section">
<source>Sections</source>
<target state="new">Sections</target>
<note>key: limitation_type.section</note>
</trans-unit>
<trans-unit id="5e91632f7d9ab6e55cf2df01163acebcb1a124d0" resname="limitation_type.subtree">
<source>Subtree</source>
<target state="new">Subtree</target>
<note>key: limitation_type.subtree</note>
</trans-unit>
<trans-unit id="0dbfb3fd5136aa1d54a82ba5e5f399c2908d26f2" resname="locations.select_subtree">
<source>Select Subtree</source>
<target state="new">Select Subtree</target>
<note>key: locations.select_subtree</note>
</trans-unit>
<trans-unit id="d92993cb4cb3690f06c599b5f500a29fa23421c9" resname="policy.add.success">
<source>New policies in role '%role%' created.</source>
<target state="new">New policies in role '%role%' created.</target>
Expand Down Expand Up @@ -231,6 +251,11 @@
<target state="new">Assignments (%count%)</target>
<note>key: role_assignment.view.list.title.count</note>
</trans-unit>
<trans-unit id="5abe6179f254b9bdd5e8680eec4456118980932e" resname="validator.assign_users_or_groups">
<source>Assign User(s) and/or Group(s) to the Role</source>
<target state="new">Assign User(s) and/or Group(s) to the Role</target>
<note>key: validator.assign_users_or_groups</note>
</trans-unit>
</body>
</file>
</xliff>
16 changes: 16 additions & 0 deletions src/bundle/Resources/translations/validators.en.xliff
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file source-language="en" target-language="en" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
</header>
<body>
<trans-unit id="f52d0870dd7bdbff2c2728c2b6ec708aa5cb240b" resname="validator.define_subtree_or_section_limitation">
<source>Define a Subtree or Section limitation</source>
<target state="new">Define a Subtree or Section limitation</target>
<note>key: validator.define_subtree_or_section_limitation</note>
</trans-unit>
</body>
</file>
</xliff>
27 changes: 23 additions & 4 deletions src/bundle/Resources/views/admin/role_assignment/create.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,29 @@
<div class="ez-card__header ez-card__header--secondary">
{{ 'role_assignment.view.add.panel.limitations.title'|trans|desc('Limitations') }}
</div>
<div class="card-body">
{{ form_row(form.sections) }}
{{ form_widget(form.locations.select_content, {'attr': {'class': 'btn btn-secondary btn--open-udw'}}) }}
{% do form.locations.setRendered %}
<div class="card-body ez-limitations">
{{ form_widget(form.limitation_type.none, {'label': 'limitation_type.none'|trans|desc('No limitations'), 'attr': {'class': 'ez-limitations__radio'}, 'label_attr': {'class': 'ez-limitations__label'}}) }}
{% if not form.limitation_type.section.vars.checked %}
{% set sections_attr = {'attr': {'disabled': 'disabled'}} %}
{% else %}
{% set sections_attr = {} %}
{% endif %}
{{ form_widget(form.limitation_type.section, {'label': 'limitation_type.section'|trans|desc('Sections'), 'attr': {'class': 'ez-limitations__radio', 'data-disable-selector': '#' ~ form.sections.vars.id}, 'label_attr': {'class': 'ez-limitations__label'}}) }}
{{ form_widget(form.sections, sections_attr) }}
{{ form_widget(form.limitation_type.location, {'label': 'limitation_type.subtree'|trans|desc('Subtree'), 'attr': {'class': 'ez-limitations__radio', 'data-disable-selector': '#role_assignment_create_locations_select_content'}, 'label_attr': {'class': 'ez-limitations__label'}}) }}
{{ form_widget(form.locations) }}
<button id="role_assignment_create_locations_select_content" class="btn btn-secondary ez-btn--select-subtree"{% if not form.limitation_type.location.vars.checked %} disabled{% endif %}>
<svg class="ez-icon ez-icon--select-subtree ez-icon--medium ez-icon--light">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="{{ asset('bundles/ezplatformadminui/img/ez-icons.svg') }}#relations"></use>
</svg>
{{ 'locations.select_subtree'|trans|desc('Select Subtree') }}
</button>
<ul class="ez-limitations__selected-subtree mt-4">
{% for location in form.locations.vars.data %}
<li>{{ location.contentInfo.name }}</li>
{% endfor %}
</ul>
</div>
</div>
</section>
Expand Down
Loading

0 comments on commit 275f083

Please sign in to comment.