From 4d88b6a51e286b41583c04fe49b8c98bfdb4a79e Mon Sep 17 00:00:00 2001 From: AdrienClairembault Date: Fri, 17 Apr 2026 16:17:20 +0200 Subject: [PATCH 1/7] Rework permission UI --- ajax/subvisibility.php | 25 +- ajax/visibility.php | 43 +- css/includes/components/_kb.scss | 12 + css/includes/components/_utils.scss | 4 + js/glpi_dialog.js | 2 +- js/modules/Ajax.js | 25 +- js/modules/Knowbase/ArticleController.js | 5 +- .../Knowbase/PermissionsFormController.js | 191 +++++++++ .../SidePanel/PermissionsRenderer.php | 14 +- src/KnowbaseItem.php | 9 +- .../tools/kb/modal/permissions.html.twig | 233 +++++----- tests/e2e/pages/KnowbaseItemPage.ts | 11 + tests/e2e/specs/Knowbase/permissions.spec.ts | 349 +++++++++++++-- tests/e2e/utils/Api.ts | 2 +- tests/e2e/utils/KnowbaseApi.ts | 14 + tests/e2e/utils/Random.ts | 38 ++ tests/e2e/utils/WorkerEntities.ts | 6 + .../SidePanel/PermissionsRendererTest.php | 401 ++++++++++++++++++ 18 files changed, 1185 insertions(+), 199 deletions(-) create mode 100644 js/modules/Knowbase/PermissionsFormController.js create mode 100644 tests/e2e/utils/Random.ts create mode 100644 tests/functional/Glpi/Knowbase/SidePanel/PermissionsRendererTest.php diff --git a/ajax/subvisibility.php b/ajax/subvisibility.php index 9a9608451f6..ebb12167a8f 100644 --- a/ajax/subvisibility.php +++ b/ajax/subvisibility.php @@ -36,7 +36,7 @@ header("Content-Type: text/html; charset=UTF-8"); Html::header_nocache(); -if (!empty($_POST['type']) && isset($_POST['items_id']) && ($_POST['items_id'] > 0)) { +if (!empty($_POST['type'])) { $prefix = ''; $suffix = ''; if (!empty($_POST['prefix'])) { @@ -47,21 +47,26 @@ switch ($_POST['type']) { case 'Group': case 'Profile': - $params = ['value' => $_SESSION['glpiactive_entity'], + $rand = mt_rand(); + $params = [ + 'value' => $_SESSION['glpiactive_entity'], 'name' => $prefix . 'entities_id' . $suffix, + 'width' => '100%', + 'rand' => $rand, ]; if (Session::canViewAllEntities()) { $params['toadd'] = [-1 => __('No restriction')]; } - echo "
"; - echo htmlescape(Entity::getTypeName(1)); - echo ""; + echo '
'; + echo ""; Entity::dropdown($params); - echo "
"; - echo __s('Child entities'); - echo ""; - Dropdown::showYesNo($prefix . 'is_recursive' . $suffix); - echo "
"; + echo ""; + echo "
"; + echo ""; + Dropdown::showYesNo($prefix . 'is_recursive' . $suffix, 1, params: [ + 'rand' => $rand, + ]); + echo "
"; break; } } diff --git a/ajax/visibility.php b/ajax/visibility.php index 78b0b2864fc..9cc27bb8c3b 100644 --- a/ajax/visibility.php +++ b/ajax/visibility.php @@ -55,33 +55,26 @@ $_POST['prefix'] = ''; } - echo "
"; switch ($_POST['type']) { case 'User': $params = [ 'right' => isset($_POST['allusers']) ? 'all' : $_POST['right'], - 'name' => $prefix . 'users_id' . $suffix, + 'name' => $prefix . 'users_id' . $suffix, + 'width' => '100%', + 'aria_label' => User::getTypeName(1), ]; User::dropdown($params); $display = true; break; case 'Group': - $params = ['rand' => $rand, - 'name' => $prefix . 'groups_id' . $suffix, - ]; - $params['toupdate'] = ['value_fieldname' - => 'value', - 'to_update' => "subvisibility$rand", - 'url' => $CFG_GLPI["root_doc"] . "/ajax/subvisibility.php", - 'moreparams' => ['items_id' => '__VALUE__', - 'type' => $_POST['type'], - 'prefix' => $_POST['prefix'], - ], + $params = [ + 'rand' => $rand, + 'name' => $prefix . 'groups_id' . $suffix, + 'width' => '100%', + 'aria_label' => Group::getTypeName(1), ]; - Group::dropdown($params); - echo ""; $display = true; break; @@ -91,9 +84,9 @@ 'name' => $prefix . 'entities_id' . $suffix, 'entity' => $_POST['entity'] ?? -1, 'entity_sons' => $_POST['is_recursive'] ?? false, + 'width' => '100%', + 'aria_label' => Entity::getTypeName(1), ]); - echo '
' . __s('Child entities') . '
'; - Dropdown::showYesNo($prefix . 'is_recursive' . $suffix); $display = true; break; @@ -104,26 +97,17 @@ $righttocheck = 'knowbase'; $checkright = KnowbaseItem::READFAQ; } - $params = [ + $params = [ 'rand' => $rand, 'name' => $prefix . 'profiles_id' . $suffix, + 'width' => '100%', 'condition' => [ 'glpi_profilerights.name' => $righttocheck, 'glpi_profilerights.rights' => ['&', $checkright], ], + 'aria_label' => Profile::getTypeName(1), ]; - $params['toupdate'] = ['value_fieldname' - => 'value', - 'to_update' => "subvisibility$rand", - 'url' => $CFG_GLPI["root_doc"] . "/ajax/subvisibility.php", - 'moreparams' => ['items_id' => '__VALUE__', - 'type' => $_POST['type'], - 'prefix' => $_POST['prefix'], - ], - ]; - Profile::dropdown($params); - echo ""; $display = true; break; } @@ -132,5 +116,4 @@ echo ""; } - echo "
"; } diff --git a/css/includes/components/_kb.scss b/css/includes/components/_kb.scss index bde2fdc6c91..147b557165b 100644 --- a/css/includes/components/_kb.scss +++ b/css/includes/components/_kb.scss @@ -710,3 +710,15 @@ padding: 1rem 1.25rem; border-top: 1px solid var(--tblr-border-color); } + +.visibility-type-col .select2-selection { + // Merge borders with dropdown to its right + border-top-right-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +.visibility-item-col .select2-selection { + // Merge borders with dropdown to its left + border-top-left-radius: 0 !important; + border-bottom-left-radius: 0 !important; +} diff --git a/css/includes/components/_utils.scss b/css/includes/components/_utils.scss index cf3e43ad9f4..9afd5fc3039 100644 --- a/css/includes/components/_utils.scss +++ b/css/includes/components/_utils.scss @@ -77,6 +77,10 @@ font-size: 5em !important; } +.flex-grow-30 { + flex-grow: 30; +} + .opacity-100-hover:hover { opacity: 1 !important; } diff --git a/js/glpi_dialog.js b/js/glpi_dialog.js index 79d610a2e11..ff013384d81 100644 --- a/js/glpi_dialog.js +++ b/js/glpi_dialog.js @@ -110,7 +110,7 @@ var glpi_html_dialog = function({