list_groups.mako 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. ## Licensed to Cloudera, Inc. under one
  2. ## or more contributor license agreements. See the NOTICE file
  3. ## distributed with this work for additional information
  4. ## regarding copyright ownership. Cloudera, Inc. licenses this file
  5. ## to you under the Apache License, Version 2.0 (the
  6. ## "License"); you may not use this file except in compliance
  7. ## with the License. You may obtain a copy of the License at
  8. ##
  9. ## http://www.apache.org/licenses/LICENSE-2.0
  10. ##
  11. ## Unless required by applicable law or agreed to in writing, software
  12. ## distributed under the License is distributed on an "AS IS" BASIS,
  13. ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ## See the License for the specific language governing permissions and
  15. ## limitations under the License.
  16. <%!
  17. from django.utils.translation import ugettext as _
  18. from useradmin.models import group_permissions
  19. from desktop.views import commonheader, commonfooter, antixss
  20. %>
  21. <%namespace name="actionbar" file="actionbar.mako" />
  22. <%namespace name="layout" file="layout.mako" />
  23. %if not is_embeddable:
  24. ${ commonheader(_('Hue Groups'), "useradmin", user, request) | n,unicode }
  25. %endif
  26. ${layout.menubar(section='groups')}
  27. <div id="groupsComponents" class="useradmin container-fluid">
  28. <div class="card card-small">
  29. <h1 class="card-heading simple">${_('Hue Groups')}</h1>
  30. <%actionbar:render>
  31. <%def name="search()">
  32. <input type="text" class="input-xlarge search-query filter-input" placeholder="${_('Search for name, members, etc...')}">
  33. </%def>
  34. <%def name="actions()">
  35. %if user.is_superuser:
  36. <button class="btn delete-group-btn confirmationModal" title="${_('Delete')}" disabled="disabled"><i class="fa fa-trash-o"></i> ${_('Delete')}</button>
  37. %endif
  38. </%def>
  39. <%def name="creation()">
  40. %if user.is_superuser:
  41. <a id="addGroupBtn" href="${url('useradmin.views.edit_group')}" class="btn"><i
  42. class="fa fa-plus-circle"></i> ${_('Add group')}</a>
  43. % if is_ldap_setup:
  44. <a id="addLdapGroupBtn" href="${url('useradmin.views.add_ldap_groups')}" class="btn"><i
  45. class="fa fa-refresh"></i> ${_('Add/Sync LDAP group')}</a>
  46. % endif
  47. <a href="http://gethue.com/making-hadoop-accessible-to-your-employees-with-ldap/"
  48. title="${ _('Learn how to integrate Hue with your company LDAP') }" target="_blank">
  49. <i class="fa fa-question-circle"></i>
  50. </a>
  51. %endif
  52. </%def>
  53. </%actionbar:render>
  54. <table class="table table-condensed datatables">
  55. <thead>
  56. <tr>
  57. %if user.is_superuser:
  58. <th width="1%">
  59. <div class="select-all hueCheckbox fa"></div>
  60. </th>
  61. %endif
  62. <th>${_('Group Name')}</th>
  63. <th>${_('Members')}</th>
  64. <th>${_('Permissions')}</th>
  65. </tr>
  66. </thead>
  67. <tbody>
  68. % for group in groups:
  69. <tr class="tableRow"
  70. data-search="${group.name}${', '.join([group_user.username for group_user in group.user_set.all()])}">
  71. %if user.is_superuser:
  72. <td data-row-selector-exclude="true">
  73. <div class="hueCheckbox groupCheck fa" data-name="${group.name}" data-row-selector-exclude="true"></div>
  74. </td>
  75. %endif
  76. <td>
  77. %if user.is_superuser:
  78. <strong><a title="${ _('Edit %(groupname)s') % dict(groupname=group.name) }"
  79. href="${ url('useradmin.views.edit_group', name=group.name) }"
  80. data-row-selector="true">${group.name}</a></strong>
  81. %else:
  82. <strong>${group.name}</strong>
  83. %endif
  84. </td>
  85. <td>${', '.join([group_user.username for group_user in group.user_set.all()])}</td>
  86. <td>${', '.join([perm.app + "." + perm.action for perm in group_permissions(group)])}</td>
  87. </tr>
  88. % endfor
  89. </tbody>
  90. <tfoot class="hide">
  91. <tr>
  92. <td colspan="8">
  93. <div class="alert">
  94. ${_('There are no groups matching the search criteria.')}
  95. </div>
  96. </td>
  97. </tr>
  98. </tfoot>
  99. </table>
  100. </div>
  101. <div class="modal hide fade delete-group">
  102. <form action="${ url('useradmin.views.delete_group') }" method="POST">
  103. ${ csrf_token(request) | n,unicode }
  104. % if is_embeddable:
  105. <input type="hidden" value="true" name="is_embeddable" />
  106. % endif
  107. <div class="modal-header">
  108. <button type="button" class="close" data-dismiss="modal" aria-label="${ _('Close') }"><span aria-hidden="true">&times;</span></button>
  109. <h2 class="modal-title">${_("Are you sure you want to delete the selected group(s)?")}</h2>
  110. </div>
  111. <div class="modal-footer">
  112. <a href="javascript:void(0);" class="btn" data-dismiss="modal">${_('No')}</a>
  113. <input type="submit" class="btn btn-danger" value="${_('Yes')}"/>
  114. </div>
  115. <div class="hide">
  116. <select name="group_names" data-bind="options: chosenGroups, selectedOptions: chosenGroups" multiple="true"></select>
  117. </div>
  118. </form>
  119. </div>
  120. </div>
  121. <script src="${ static('desktop/ext/js/datatables-paging-0.1.js') }" type="text/javascript" charset="utf-8"></script>
  122. <script type="text/javascript">
  123. $(document).ready(function () {
  124. var $groupsComponents = $('#groupsComponents');
  125. $(document).off('click', '#groupsComponents .groupCheck');
  126. var viewModel = {
  127. availableGroups: ko.observableArray(${ groups_json | n,antixss }),
  128. chosenGroups: ko.observableArray([])
  129. };
  130. ko.applyBindings(viewModel, $groupsComponents[0]);
  131. var dt = $groupsComponents.find('.datatables').dataTable({
  132. "sPaginationType":"bootstrap",
  133. "iDisplayLength":100,
  134. "bLengthChange":false,
  135. "sDom": "<'row'r>t<'row-fluid'<'dt-pages'p><'dt-records'i>>",
  136. "bInfo": false,
  137. "bFilter": true,
  138. "bAutoWidth": false,
  139. "aoColumns": [
  140. %if user.is_superuser:
  141. { "bSortable": false },
  142. %endif
  143. { "sWidth": "20%" },
  144. { "sWidth": "20%" },
  145. null
  146. ],
  147. "oLanguage": {
  148. "sEmptyTable": "${_('No data available')}",
  149. "sZeroRecords": "${_('No matching records')}",
  150. }
  151. });
  152. % if is_embeddable:
  153. $groupsComponents.find('.delete-group form').ajaxForm({
  154. dataType: 'json',
  155. success: function(data) {
  156. if (data && data.url){
  157. huePubSub.publish('open.link', data.url);
  158. }
  159. $.jHueNotify.info("${ _('The groups were deleted.') }");
  160. $groupsComponents.find(".delete-group").modal("hide");
  161. }
  162. });
  163. % endif
  164. $groupsComponents.find(".filter-input").jHueDelayedInput(function () {
  165. if (dt) {
  166. dt.fnFilter($groupsComponents.find(".filter-input").val().toLowerCase());
  167. }
  168. });
  169. $groupsComponents.find('[data-rel="tooltip"]').tooltip({
  170. placement: 'right'
  171. });
  172. $groupsComponents.find(".dataTables_wrapper").css("min-height", "0");
  173. $groupsComponents.find(".dataTables_filter").hide();
  174. $groupsComponents.find(".select-all").click(function () {
  175. if ($(this).attr("checked")) {
  176. $(this).removeAttr("checked").removeClass("fa-check");
  177. $groupsComponents.find(".groupCheck").removeClass("fa-check").removeAttr("checked");
  178. }
  179. else {
  180. $(this).attr("checked", "checked").addClass("fa-check");
  181. $groupsComponents.find(".groupCheck").addClass("fa-check").attr("checked", "checked");
  182. }
  183. toggleActions();
  184. });
  185. $(document).on('click', '#groupsComponents .groupCheck', function () {
  186. if ($(this).attr("checked")) {
  187. $(this).removeClass("fa-check").removeAttr("checked");
  188. }
  189. else {
  190. $(this).addClass("fa-check").attr("checked", "checked");
  191. }
  192. toggleActions();
  193. });
  194. function toggleActions() {
  195. if ($groupsComponents.find(".groupCheck[checked='checked']").length > 0) {
  196. $groupsComponents.find(".delete-group-btn").removeAttr("disabled");
  197. }
  198. else {
  199. $groupsComponents.find(".delete-group-btn").attr("disabled", "disabled");
  200. }
  201. }
  202. $groupsComponents.find(".delete-group-btn").click(function () {
  203. viewModel.chosenGroups.removeAll();
  204. $groupsComponents.find(".hueCheckbox[checked='checked']").each(function (index) {
  205. viewModel.chosenGroups.push($(this).data("name").toString()); // needed for numeric group names
  206. });
  207. $groupsComponents.find(".delete-group").modal("show");
  208. });
  209. $groupsComponents.find("a[data-row-selector='true']").jHueRowSelector();
  210. });
  211. </script>
  212. ${layout.commons()}
  213. %if not is_embeddable:
  214. ${ commonfooter(request, messages) | n,unicode }
  215. %endif