group_info.html 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. {% extends "master.html" %}
  2. {% from "userprofile_macros.html" import render_repo_listing %}
  3. {% from "_projectstring.html" import projectstring, projecticon %}
  4. {% block title %}Group {{ group.group_name }}{% endblock %}
  5. {% set tag = "groups" %}
  6. {% block header %}
  7. <link nonce="{{ g.nonce }}" rel="stylesheet" href="{{
  8. url_for('static', filename='vendor/selectize/selectize.bootstrap3.css') }}?version={{ g.version}}"/>
  9. {% endblock %}
  10. {% block content %}
  11. <div class="bg-light border border-top-0 pt-2">
  12. <div class="container">
  13. <div class="media my-4">
  14. <div class="align-self-start mr-3">
  15. <span class="fa fa-users fa-fw fa-4x text-muted"></span>
  16. </div>
  17. <div class="media-body align-self-start">
  18. <h3 class="mb-0 font-weight-bold">{{group.display_name }}</h3>
  19. {% if group.description %}<div>{{ group.description }}</div>{% endif %}
  20. <div><small>
  21. formed {{ group.created |humanize_tooltip | safe }},
  22. administered by <a href="{{ url_for('ui_ns.view_user', username=group.creator.user)}}">{{ group.creator.user }}</a></small>
  23. </div>
  24. </div>
  25. {% if g.authenticated and (member or g.admin)
  26. and config.get('ENABLE_GROUP_MNGT') %}
  27. <form method="POST" action="{{ url_for('ui_ns.group_delete',
  28. group=group.group_name) }}">
  29. <div class="btn-group ml-auto">
  30. <a href="{{ url_for('ui_ns.edit_group', group=group.group_name) }}"
  31. class="btn btn-sm btn-outline-primary">
  32. <span class="fa fa-pencil" title="Edit group"></span>&nbsp;Edit
  33. </a>
  34. <button title="Delete group"
  35. class="btn btn-sm btn-outline-danger delete-group-btn">
  36. <i class="fa fa-trash"></i> &nbsp;Delete
  37. </button>
  38. </div>
  39. {{ form.csrf_token }}
  40. </form>
  41. {% endif %}
  42. </div>
  43. </div>
  44. </div>
  45. <div class="container pt-4">
  46. <div class="row">
  47. <div class="col-md-8">
  48. <div class="d-flex align-items-center mb-3">
  49. <h4 class="font-weight-bold mb-0">Group {{projectstring(plural=True)}}</h4>
  50. <span class="btn btn-outline-secondary disabled opacity-100 border-0 ml-auto font-weight-bold">{{ group.projects | length }} {{projectstring(plural=True)}}</span>
  51. </div>
  52. {% if group.projects | length > 0 %}
  53. {{render_repo_listing(group.projects)}}
  54. {% else %}
  55. <div class="alert alert-secondary text-center p-4">
  56. no {{projectstring(plural=True)}}
  57. </div>
  58. {% endif %}
  59. </div>
  60. <div class="col-md-4">
  61. <div class='card'>
  62. <div class="card-header">
  63. <div class="d-flex align-items-center">
  64. <div><strong>{{group.users|count}} Members</strong></div>
  65. {% if g.authenticated and (member or admin)
  66. and config.get('ENABLE_GROUP_MNGT') %}
  67. <div id="add_user_button" class="btn btn-outline-primary btn-sm ml-auto">
  68. <span class="fa fa-user-plus"></span>
  69. </div>
  70. {% endif %}
  71. </div>
  72. </div>
  73. <div class="list-group list-group-flush">
  74. {% if g.authenticated and (member or g.admin)
  75. and config.get('ENABLE_GROUP_MNGT') %}
  76. <div class="list-group-item hidden" id="add_user_form_wrapper">
  77. <form action="{{ url_for('ui_ns.view_group', group=group.group_name)
  78. }}" method="post" id="add_user_form">
  79. <input placeholder="search for user" class="form-control" id="user" name="user" title="User name"/>
  80. {{ form.csrf_token }}
  81. </form>
  82. </div>
  83. {% endif %}
  84. {% for user in group.users %}
  85. <div class="list-group-item">
  86. <a href="{{ url_for('ui_ns.view_user', username=user.user)}}" title="{{ user.fullname }}" data-toggle="tooltip">
  87. {{ user.default_email | avatar(28) | safe }}
  88. {{ user.user }}
  89. </a>
  90. {% if g.authenticated and user != group.creator
  91. and (member or g.admin)
  92. and config.get('ENABLE_GROUP_MNGT') %}
  93. <form class="float-right inline-block" method="POST"
  94. action="{{ url_for('ui_ns.group_user_delete',
  95. group=group.group_name, user=user.user) }}">
  96. {{ form.csrf_token }}
  97. <button title="Remove user from group"
  98. data-username="{{ user.user }}"
  99. class="btn btn-sm btn-outline-danger border-0 remove-user-btn">
  100. <i class="fa fa-trash"></i>
  101. </button>
  102. </form>
  103. {% endif %}
  104. </div>
  105. {% endfor %}
  106. </div> <!--list-group-->
  107. </div> <!-- card -->
  108. </div> <!--col-md-4 -->
  109. </div> <!--row-->
  110. </div> <!--container-->
  111. {% endblock %}
  112. {% block jscripts %}
  113. {{ super() }}
  114. <script type="text/javascript" nonce="{{ g.nonce }}" src="{{
  115. url_for('static', filename='vendor/selectize/selectize.min.js') }}?version={{ g.version}}" type="text/javascript"> </script>
  116. <script type="text/javascript" nonce="{{ g.nonce }}">
  117. $(document).ready(function() {
  118. $('.delete-group-btn').click(function() {
  119. return confirm('Are you sure you want to delete the group `{{ group.group_name }}`?');
  120. })
  121. $('.remove-user-btn').click(function() {
  122. return confirm('Are you sure you want to remove user `' + $(this).attr('data-username') + '` from the group `{{ group.group_name }}`?');
  123. })
  124. $('#headerSearch').on('keypress keydown keyup', function(e) {
  125. if (e.which == 13) {
  126. e.preventDefault();
  127. return false;
  128. }
  129. });
  130. $('#term').selectize({
  131. valueField: 'group',
  132. labelField: 'group',
  133. searchField: 'group',
  134. onType: function(value){
  135. if (value == ""){
  136. this.close();
  137. }
  138. },
  139. onChange: function(value){
  140. if (value != ""){
  141. $('#headerSearch').submit();
  142. }
  143. },
  144. maxItems: 1,
  145. create: false,
  146. load: function(query, callback) {
  147. if (!query.length) return callback();
  148. $.getJSON(
  149. "{{ url_for('api_ns.api_groups') }}", {
  150. pattern: query
  151. },
  152. function( data ) {
  153. callback( data.groups.map(function(x) { return { group: x }; }) );
  154. }
  155. );
  156. }
  157. });
  158. var usersearch = $('#user').selectize({
  159. valueField: 'user',
  160. labelField: 'user',
  161. searchField: 'user',
  162. onChange: function(value){
  163. if (value != ""){
  164. $('#add_user_form').submit();
  165. }
  166. },
  167. maxItems: 1,
  168. create: false,
  169. preload: 'focus',
  170. load: function(query, callback) {
  171. $.getJSON(
  172. "{{ url_for('api_ns.api_users') }}",
  173. function( data ) {
  174. callback( data.users.map(function(x) { return { user: x }; }) );
  175. }
  176. );
  177. },
  178. render: {
  179. option: function(item, escape) {
  180. return '<div>' +
  181. '<div>' +
  182. '<span><strong>' + escape(item.user) + '</strong></span>' +
  183. '</div>' +
  184. '</div>';
  185. }
  186. },
  187. });
  188. $('#add_user_button').click(function(){
  189. $('#add_user_button').hide();
  190. $('#add_user_form_wrapper').show();
  191. usersearch[0].selectize.focus();
  192. });
  193. });
  194. </script>
  195. {% endblock %}