diff options
author | Udo Walter | 2017-11-30 17:40:00 +0100 |
---|---|---|
committer | Udo Walter | 2017-11-30 17:40:00 +0100 |
commit | eff2f558576ff58cb402c7b28b38620ddc467599 (patch) | |
tree | 2a5db71d227f3411731952163d1bd363e80c2b69 /modules-available/permissionmanager | |
parent | [permissionmanager] fixed bug: role without locations was shown as role with ... (diff) | |
download | slx-admin-eff2f558576ff58cb402c7b28b38620ddc467599.tar.gz slx-admin-eff2f558576ff58cb402c7b28b38620ddc467599.tar.xz slx-admin-eff2f558576ff58cb402c7b28b38620ddc467599.zip |
[permissionmanager] new permission and location chooser in roleeditor
Diffstat (limited to 'modules-available/permissionmanager')
9 files changed, 209 insertions, 228 deletions
diff --git a/modules-available/permissionmanager/page.inc.php b/modules-available/permissionmanager/page.inc.php index 20e8ad3a..9aba80b3 100644 --- a/modules-available/permissionmanager/page.inc.php +++ b/modules-available/permissionmanager/page.inc.php @@ -30,8 +30,8 @@ class Page_PermissionManager extends Page } elseif ($action === 'saveRole') { $roleID = Request::post("roleid", false); $rolename = Request::post("rolename"); - $locations = Request::post("allLocations", "off") == "on" ? array(NULL) : Request::post("locations"); - $permissions = Request::post("allPermissions", "off") == "on" ? array("*") : Request::post("permissions");; + $locations = self::processLocations(Request::post("locations")); + $permissions = self::processPermissions(Request::post("permissions")); PermissionDbUpdate::saveRole($rolename, $locations, $permissions, $roleID); } } @@ -46,13 +46,12 @@ class Page_PermissionManager extends Page // switch between tables, but always show menu to switch tables if ( $show === 'roles' || $show === 'users' || $show === 'locations' ) { // get menu button colors - $buttonColors = self::setButtonColors($show); + $buttonColors = array(); + $buttonColors['rolesButtonClass'] = $show === 'roles' ? 'active' : ''; + $buttonColors['usersButtonClass'] = $show === 'users' ? 'active' : ''; + $buttonColors['locationsButtonClass'] = $show === 'locations' ? 'active' : ''; - $data = array(); - - Render::openTag('div', array('class' => 'row')); Render::addtemplate('_page', $buttonColors); - Render::closeTag('div'); if ($show === "roles") { $data = array("roles" => GetPermissionData::getRoles()); @@ -67,68 +66,128 @@ class Page_PermissionManager extends Page } elseif ($show === "roleEditor") { $data = array(); - $roleID = Request::get("roleid", false); + $selectedPermissions = array(); $selectedLocations = array(); + $roleID = Request::get("roleid", false); if ($roleID) { $roleData = GetPermissionData::getRoleData($roleID); $data["roleid"] = $roleID; $data["rolename"] = $roleData["rolename"]; - if (count($roleData["locations"]) == 1 && $roleData["locations"][0] == 0) { - $data["allLocChecked"] = "checked"; - $data["selectizeClass"] = "faded unclickable"; - } else { - $data["allLocChecked"] = ""; - $data["selectizeClass"] = ""; - $selectedLocations = $roleData["locations"]; - } - if (count($roleData["permissions"]) == 1 && $roleData["permissions"][0] == "*") { - $data["allPermChecked"] = "checked"; - $data["permissionsClass"] = "faded unclickable"; - } else { - $data["allPermChecked"] = ""; - $data["permissionsClass"] = ""; - $data["selectedPermissions"] = implode(" ", $roleData["permissions"]); - } + $selectedPermissions = $roleData["permissions"]; + $selectedLocations = $roleData["locations"]; } - $permissions = PermissionUtil::getPermissions(); + $data["permissionHTML"] = self::generatePermissionHTML(PermissionUtil::getPermissions(), $selectedPermissions); + $data["locationHTML"] = self::generateLocationHTML(Location::getTree(), $selectedLocations); - $data["locations"] = Location::getLocations($selectedLocations); - $data["moduleNames"] = array(); - foreach (array_keys($permissions) as $moduleid) { - $data["moduleNames"][] = array("id" => $moduleid, "name" => Module::get($moduleid)->getDisplayName()); - } - $data["permissionHTML"] = self::generatePermissionHTML($permissions, "*"); Render::addTemplate('roleeditor', $data); } } - // Menu: Selected table is shown in blue (btn-primary) - private function setButtonColors($show) { - if ($show === 'roles') { - $buttonColors['rolesButtonClass'] = 'active'; - } elseif ($show === 'users') { - $buttonColors['usersButtonClass'] = 'active'; - } elseif ($show === 'locations') { - $buttonColors['locationsButtonClass'] = 'active'; + private static function generatePermissionHTML($subPermissions, $selectedPermissions = array(), $selectAll = false, $permString = "") + { + $res = ""; + $toplevel = $permString == ""; + if ($toplevel && in_array("*", $selectedPermissions)) $selectAll = true; + foreach ($subPermissions as $k => $v) { + $leaf = !is_array($v); + $nextPermString = $permString ? $permString.".".$k : $k; + $id = $leaf ? $nextPermString : $nextPermString.".*"; + $selected = $selectAll || in_array($id, $selectedPermissions); + $res .= Render::parse("treenode", + array("id" => $id, + "name" => $toplevel ? Module::get($k)->getDisplayName() : $k, + "toplevel" => $toplevel, + "checkboxname" => "permissions", + "selected" => $selected, + "HTML" => $leaf ? "" : self::generatePermissionHTML($v, $selectedPermissions, $selected, $nextPermString), + "description" => $leaf ? $v : "")); } - - return $buttonColors; + if ($toplevel) { + $res = Render::parse("treepanel", + array("id" => "*", + "name" => Dictionary::translateFile("template-tags", "lang_Permissions"), + "checkboxname" => "permissions", + "selected" => $selectAll, + "HTML" => $res)); + } + return $res; } - private static function generatePermissionHTML($subPermissions, $permString) + private static function generateLocationHTML($locations, $selectedLocations = array(), $selectAll = false, $toplevel = true) { - $genModuleBox = $permString == "*"; $res = ""; - foreach ($subPermissions as $k => $v) { - $res .= Render::parse($genModuleBox ? "modulepermissionbox" : (is_array($v) ? "permissiontreenode" : "permission"), - array("id" => $genModuleBox ? $k : $permString.".".$k, - "name" => $genModuleBox ? Module::get($k)->getDisplayName(): $k, - "HTML" => is_array($v) ? self::generatePermissionHTML($v, $genModuleBox ? $k : $permString.".".$k) : "", - "description" => $v)); + if ($toplevel && in_array(0, $selectedLocations)) $selectAll = true; + foreach ($locations as $location) { + $selected = $selectAll || in_array($location["locationid"], $selectedLocations); + $res .= Render::parse("treenode", + array("id" => $location["locationid"], + "name" => $location["locationname"], + "toplevel" => $toplevel, + "checkboxname" => "locations", + "selected" => $selected, + "HTML" => array_key_exists("children", $location) ? + self::generateLocationHTML($location["children"], $selectedLocations, $selected, false) : "")); + } + if ($toplevel) { + $res = Render::parse("treepanel", + array("id" => 0, + "name" => Dictionary::translateFile("template-tags", "lang_Locations"), + "checkboxname" => "locations", + "selected" => $selectAll, + "HTML" => $res)); } return $res; } + private static function processLocations($locations) + { + if (in_array(0, $locations)) return array(NULL); + $result = array(); + foreach ($locations as $location) { + $rootchain = array_reverse(Location::getLocationRootChain($location)); + foreach ($rootchain as $l) { + if (in_array($l, $result)) break; + if (in_array($l, $locations)) { + $result[] = $l; + break; + } + } + } + return $result; + } + + private static function processPermissions($permissions) + { + if (in_array("*", $permissions)) return array("*"); + $result = array(); + foreach ($permissions as $permission) { + $x =& $result; + foreach (explode(".", $permission) as $p) { + $x =& $x[$p]; + } + } + return self::extractPermissions($result); + } + + private static function extractPermissions($permissions) + { + $result = array(); + foreach ($permissions as $permission => $a) { + if (is_array($a)) { + if (array_key_exists("*", $a)) { + $result[] = $permission.".*"; + } else { + foreach (self::extractPermissions($a) as $subPermission) { + $result[] = $permission.".".$subPermission; + } + } + } else { + $result[] = $permission; + } + } + return $result; + } + } diff --git a/modules-available/permissionmanager/style.css b/modules-available/permissionmanager/style.css index abc3270a..bb03d153 100644 --- a/modules-available/permissionmanager/style.css +++ b/modules-available/permissionmanager/style.css @@ -10,7 +10,7 @@ #rolename { width: 200px; display: inline-block; - margin-left: 20px; + margin-left: 10px; } .table { @@ -41,52 +41,48 @@ margin-bottom: 20px; } -.list-group, .checkbox { - margin: 0; -} - -.faded { - opacity: 0.6; -} - -.unclickable { - pointer-events: none; -} -input[type='checkbox']:disabled { - cursor: inherit; +.tree-container .selected { + background-color: rgba(0, 182, 41, 0.23); } -.module-toggle-group { - width: 100%; - margin-top: 20px; -} - -.module-container { +.tree-container { -moz-column-gap: 20px; -webkit-column-gap: 20px; column-gap: 20px; } -.module-container div { +.tree-container > ul { display: inline-block; width: 100%; + padding: 0; } - @media (max-width: 767px) { - .module-container { + .tree-container { -moz-column-count: 1; -webkit-column-count: 1; column-count: 1; } } -@media (min-width: 768px) { - .module-container { +@media (min-width: 768px) and (max-width: 991px) { + .tree-container { -moz-column-count: 2; -webkit-column-count: 2; column-count: 2; } } + +@media (min-width: 992px) { + .tree-container { + -moz-column-count: 3; + -webkit-column-count: 3; + column-count: 3; + } +} + +ul { + list-style-type: none; +}
\ No newline at end of file diff --git a/modules-available/permissionmanager/templates/_page.html b/modules-available/permissionmanager/templates/_page.html index ff487c8f..405462f7 100644 --- a/modules-available/permissionmanager/templates/_page.html +++ b/modules-available/permissionmanager/templates/_page.html @@ -1,27 +1,29 @@ -<div class="col-md-12" style="margin-bottom: 0px;"> - <div class='page-header'> - <div class='pull-right'> - <form id="switchForm" method="GET" action="?do=permissionmanager"> - <input type="hidden" name="do" value="permissionmanager"> +<div class="row"> + <div class="col-md-12" style="margin-bottom: 0;"> + <div class='page-header'> + <div class='pull-right'> + <form id="switchForm" method="GET" action="?do=permissionmanager"> + <input type="hidden" name="do" value="permissionmanager"> - <div class="btn-group"> - <button class="btn btn-default {{rolesButtonClass}}" type="submit" name="show" value="roles"> - <span class="glyphicon glyphicon-education"></span> - {{lang_Roles}} - </button> + <div class="btn-group"> + <button class="btn btn-default {{rolesButtonClass}}" type="submit" name="show" value="roles"> + <span class="glyphicon glyphicon-education"></span> + {{lang_Roles}} + </button> - <button class="btn btn-default {{usersButtonClass}}" type="submit" name="show" value="users"> - <span class="glyphicon glyphicon-user"></span> - {{lang_Users}} - </button> + <button class="btn btn-default {{usersButtonClass}}" type="submit" name="show" value="users"> + <span class="glyphicon glyphicon-user"></span> + {{lang_Users}} + </button> - <button class="btn btn-default {{locationsButtonClass}}" type="submit" name="show" value="locations"> - <span class="glyphicon glyphicon-home"></span> - {{lang_Locations}} - </button> - </div> - </form> + <button class="btn btn-default {{locationsButtonClass}}" type="submit" name="show" value="locations"> + <span class="glyphicon glyphicon-home"></span> + {{lang_Locations}} + </button> + </div> + </form> + </div> + <h1>{{lang_moduleName}}</h1> </div> - <h1>{{lang_moduleName}}</h1> </div> </div>
\ No newline at end of file diff --git a/modules-available/permissionmanager/templates/modulepermissionbox.html b/modules-available/permissionmanager/templates/modulepermissionbox.html deleted file mode 100644 index 69bde718..00000000 --- a/modules-available/permissionmanager/templates/modulepermissionbox.html +++ /dev/null @@ -1,13 +0,0 @@ -<div id='{{id}}' class='panel panel-primary module-box' style='display: none;'> - <div class='panel-heading'> - <div class='checkbox'> - <input name='permissions[]' value='{{id}}.*' type='checkbox' class='form-control'> - <label>{{name}}</label> - </div> - </div> - <div class='panel-body'> - <ul class='list-group'> - {{{HTML}}} - </ul> - </div> -</div>
\ No newline at end of file diff --git a/modules-available/permissionmanager/templates/permission.html b/modules-available/permissionmanager/templates/permission.html deleted file mode 100644 index b28b9099..00000000 --- a/modules-available/permissionmanager/templates/permission.html +++ /dev/null @@ -1,6 +0,0 @@ -<li class='list-group-item' title="{{description}}" data-toggle="tooltip" data-placement="left"> - <div class='checkbox'> - <input name='permissions[]' value='{{id}}' type='checkbox' class='form-control'> - <label>{{name}}</label> - </div> -</li>
\ No newline at end of file diff --git a/modules-available/permissionmanager/templates/permissiontreenode.html b/modules-available/permissionmanager/templates/permissiontreenode.html deleted file mode 100644 index 47bff1f2..00000000 --- a/modules-available/permissionmanager/templates/permissiontreenode.html +++ /dev/null @@ -1,9 +0,0 @@ -<li class='list-group-item'> - <div class='checkbox'> - <input name='permissions[]' value='{{id}}.*' type='checkbox' class='form-control'> - <label>{{name}}</label> - </div> - <ul class='list-group'> - {{{HTML}}} - </ul> -</li> diff --git a/modules-available/permissionmanager/templates/roleeditor.html b/modules-available/permissionmanager/templates/roleeditor.html index 359f09a1..14839ee2 100644 --- a/modules-available/permissionmanager/templates/roleeditor.html +++ b/modules-available/permissionmanager/templates/roleeditor.html @@ -3,116 +3,57 @@ <input type="hidden" name="action" value="saveRole"> <input type="hidden" name="token" value="{{token}}"> <input type="hidden" name="roleid" value="{{roleid}}"> + <div class="row"> <div class="col-md-12" style="margin-bottom: 20px;"> - <b>{{lang_Name}}:</b> - <input name="rolename" value="{{rolename}}" type="text" id="rolename" class="form-control"> - <button type="submit" id="saveButton" class="btn btn-primary pull-right"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_Save}}</button> - <button type="button" id="cancelButton" class="btn btn-default pull-right">{{lang_Cancel}}</button> + <ul class="nav nav-tabs text-center" role="tablist"> + <li role="presentation" class="active"><a href="#permissions" role="tab" data-toggle="tab">{{lang_Permissions}}</a></li> + <li role="presentation"><a href="#locations" role="tab" data-toggle="tab">{{lang_Locations}}</a></li> + <li style="float: none; display: inline-block"> + <b>{{lang_Name}}:</b> + <input name="rolename" value="{{rolename}}" type="text" id="rolename" class="form-control"> + </li> + <li style="float: right;"> + <button type="button" id="cancelButton" class="btn btn-default">{{lang_Cancel}}</button> + <button type="submit" id="saveButton" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_Save}}</button> + </li> + </ul> </div> </div> <div class="row" style="margin-bottom: 20px;"> - <div class="col-md-3"> - <b style="line-height: 34px">{{lang_Locations}}:</b> - <div class="pull-right"><input name="allLocations" {{allLocChecked}} type="checkbox" id="allLocations"></div> - </div> - <div id="selectize-container" class="col-md-9 text-left {{selectizeClass}}"> - <select multiple name="locations[]" id="select-location"> - <option value></option> - {{#locations}} - <option value="{{locationid}}" {{#selected}}selected{{/selected}}>{{locationpad}} {{locationname}}</option> - {{/locations}} - </select> - </div> - </div> - <div class="row"> - <div class="col-md-3"> - <b style="line-height: 34px">{{lang_Permissions}}:</b> - <div class="pull-right"><input name="allPermissions" {{allPermChecked}} type="checkbox" id="allPermissions"></div> - <div class="btn-group-vertical module-toggle-group permissions-container {{permissionsClass}}" role="group"> - {{#moduleNames}} - <button id="button-{{id}}" type="button" class="btn btn-default module-toggle" data-moduleid="{{id}}">{{name}}</button> - {{/moduleNames}} + <div class="col-md-12"> + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="permissions"> + {{{permissionHTML}}} + </div> + <div role="tabpanel" class="tab-pane" id="locations"> + {{{locationHTML}}} + </div> </div> </div> - <div class="col-md-9 module-container permissions-container {{permissionsClass}}"> - {{{permissionHTML}}} - </div> </div> + </form> <script type="application/javascript"> - selectedPermissions = "{{selectedPermissions}}"; - document.addEventListener("DOMContentLoaded", function () { - $('#select-location').selectize({ - allowEmptyOption: false, - maxItems: null, - highlight: false, - hideSelected: true, - create: false, - plugins: [ "remove_button" ] - }); - - var allLocations = $("#allLocations"); - allLocations.bootstrapSwitch("size", "normal"); - allLocations.bootstrapSwitch("labelWidth", 1); - allLocations.bootstrapSwitch("onText", "{{lang_all}}"); - allLocations.bootstrapSwitch("offText", "{{lang_selected}}"); - - allLocations.on('switchChange.bootstrapSwitch', function(event, state) { - if (state) { - $("#selectize-container").addClass("faded unclickable"); - } else { - $("#selectize-container").removeClass("faded unclickable"); - } - }); - - var allPermissions = $("#allPermissions"); - allPermissions.bootstrapSwitch("size", "normal"); - allPermissions.bootstrapSwitch("labelWidth", 1); - allPermissions.bootstrapSwitch("onText", "{{lang_all}}"); - allPermissions.bootstrapSwitch("offText", "{{lang_selected}}"); - - - allPermissions.on('switchChange.bootstrapSwitch', function(event, state) { - if (state) { - $(".permissions-container").addClass("faded unclickable"); - } else { - $(".permissions-container").removeClass("faded unclickable"); - } - }); - - $(".module-toggle").click(function () { - var button = $(this); - var moduleBox = $("#" + button.data("moduleid")); - if (button.hasClass("btn-default")) { - button.removeClass("btn-default"); - button.addClass("btn-primary"); - moduleBox.show(); - } else { - button.removeClass("btn-primary"); - button.addClass("btn-default"); - moduleBox.hide(); - } - }); - - $(".module-container input[type=checkbox]").change(function () { + $(".tree-panel input[type=checkbox]").change(function () { + var checked = $(this).prop("checked"); var parent = $(this).parent().parent(); if (parent.hasClass("panel-heading")) parent = parent.parent(); - parent = parent.find("ul:first"); - parent.find("ul").removeClass("faded"); + var checkboxes = parent.find("input[type=checkbox]"); - if (parent.hasClass("faded")) { - checkboxes.prop("disabled", false); - checkboxes.prop("checked", false); - parent.removeClass("faded"); - } else { - checkboxes.prop("disabled", true); + if (checked) { checkboxes.prop("checked", true); - parent.addClass("faded"); + } else { + checkboxes.prop("checked", false); + while (!parent.hasClass("tree-panel")) { + parent = parent.parent().parent(); + if (parent.hasClass("tree-container")) parent = parent.parent().parent(); + parent.find("input[type=checkbox]:first").prop("checked", false); + } } }); @@ -128,19 +69,6 @@ } }); - var permissions = selectedPermissions.split(" "); - var arrayLength = permissions.length; - for (var i = 0; i < arrayLength; i++) { - var checkbox = $("input[type=checkbox][value='"+permissions[i]+"']"); - checkbox.trigger('change').attr('checked', 'checked'); - var moduleBox = checkbox.closest(".module-box"); - moduleBox.show(); - var button = $("#button-"+moduleBox.attr('id')); - button.removeClass("btn-default"); - button.addClass("btn-primary"); - } - - $('[data-toggle="tooltip"]').tooltip({ container: 'body', trigger : 'hover' diff --git a/modules-available/permissionmanager/templates/treenode.html b/modules-available/permissionmanager/templates/treenode.html new file mode 100644 index 00000000..336ca13e --- /dev/null +++ b/modules-available/permissionmanager/templates/treenode.html @@ -0,0 +1,11 @@ +{{#toplevel}}<ul>{{/toplevel}} + <li title="{{description}}" data-toggle="tooltip" data-placement="left"> + <div class='checkbox'> + <input name='{{checkboxname}}[]' value='{{id}}' type='checkbox' class='form-control' {{#selected}}checked{{/selected}}> + <label>{{#toplevel}}<b>{{/toplevel}}{{name}}{{#toplevel}}</b>{{/toplevel}}</label> + </div> + <ul> + {{{HTML}}} + </ul> + </li> +{{#toplevel}}</ul>{{/toplevel}} diff --git a/modules-available/permissionmanager/templates/treepanel.html b/modules-available/permissionmanager/templates/treepanel.html new file mode 100644 index 00000000..53e316c9 --- /dev/null +++ b/modules-available/permissionmanager/templates/treepanel.html @@ -0,0 +1,13 @@ +<div class='panel panel-primary tree-panel'> + <div class='panel-heading'> + <div class='checkbox'> + <input name='{{checkboxname}}[]' value='{{id}}' type='checkbox' class='form-control' {{#selected}}checked{{/selected}}> + <label>{{name}}</label> + </div> + </div> + <div class='panel-body'> + <div class="tree-container" style="padding-left: 20px; padding-right: 20px;"> + {{{HTML}}} + </div> + </div> +</div>
\ No newline at end of file |