users.html 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. {% extends '../layout/admin.html' %}
  2. {% block html_title %}ユーザー管理 · {% endblock %}
  3. {% block content_head %}
  4. <div class="header-wrap">
  5. <header id="page-header">
  6. <h1 class="title" id="">ユーザー管理</h1>
  7. </header>
  8. </div>
  9. {% endblock %}
  10. {% block content_main %}
  11. <div class="content-main">
  12. {% set smessage = req.flash('successMessage') %}
  13. {% if smessage.length %}
  14. <div class="alert alert-success">
  15. {{ smessage }}
  16. </div>
  17. {% endif %}
  18. {% set emessage = req.flash('errorMessage') %}
  19. {% if emessage.length %}
  20. <div class="alert alert-danger">
  21. {{ emessage }}
  22. </div>
  23. {% endif %}
  24. <div class="row">
  25. <div class="col-md-3">
  26. {% include './widget/menu.html' with {current: 'user'} %}
  27. </div>
  28. <div class="col-md-9">
  29. <p>
  30. <button data-toggle="collapse" class="btn btn-default" href="#inviteUserForm">新規ユーザーの招待</button>
  31. </p>
  32. <form role="form" action="/admin/user/invite" method="post">
  33. <div id="inviteUserForm" class="collapse">
  34. <div class="form-group">
  35. <label for="inviteForm[emailList]">メールアドレス (複数行入力で複数人招待可能)</label>
  36. <textarea class="form-control" name="inviteForm[emailList]" placeholder="例: user@crowi.wiki"></textarea>
  37. </div>
  38. <div class="checkbox">
  39. <label>
  40. <input type="checkbox" name="inviteForm[sendEmail]" checked> 招待をメールで送信
  41. </label>
  42. </div>
  43. <button type="submit" class="btn btn-primary">招待する</button>
  44. </div>
  45. <input type="hidden" name="_csrf" value="{{ _csrf() }}">
  46. </form>
  47. {% set createdUser = req.flash('createdUser') %}
  48. {% if createdUser.length %}
  49. <div class="modal fade in" id="createdUserModal">
  50. <div class="modal-dialog">
  51. <div class="modal-content">
  52. <div class="modal-header">
  53. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
  54. <h4 class="modal-title">ユーザーを招待しました</h4>
  55. </div>
  56. <div class="modal-body">
  57. <p>
  58. 作成したユーザーは仮パスワードが設定されています。<br>
  59. 仮パスワードはこの画面を閉じると二度と表示できませんのでご注意ください。<span class="text-danger">招待メールを送っていない場合、この画面で必ず仮パスワードをコピーし、招待者へ連絡してください。</span>
  60. </p>
  61. <pre>{% for cUser in createdUser %}{% if cUser.user %}{{ cUser.email }} {{ cUser.password }}<br>{% else %}{{ cUser.email }} 作成失敗<br>{% endif %}{% endfor %}</pre>
  62. </div>
  63. </div><!-- /.modal-content -->
  64. </div><!-- /.modal-dialog -->
  65. </div><!-- /.modal -->
  66. {% endif %}
  67. <h2>ユーザー一覧</h2>
  68. <table class="table table-hover table-striped table-bordered">
  69. <thead>
  70. <tr>
  71. <th>#</th>
  72. <th>ユーザーID</th>
  73. <th>名前</th>
  74. <th>メールアドレス</th>
  75. <th>作成日</th>
  76. <th>最終ログイン</th>
  77. <th>操作</th>
  78. </tr>
  79. </thead>
  80. <tbody>
  81. {% for sUser in users %}
  82. <tr>
  83. <td>
  84. <img src="{{ sUser|picture }}" class="picture picture-rounded" />
  85. <span class="label {{ css.userStatus(sUser) }}">
  86. {{ consts.userStatus[sUser.status] }}
  87. </span><br>
  88. {% if sUser.admin %}
  89. <span class="label label-primary">
  90. Admin
  91. </span>
  92. {% endif %}
  93. </td>
  94. <td>
  95. <strong>{{ sUser.username }}</strong>
  96. </td>
  97. <td>{{ sUser.name }}</td>
  98. <td>{{ sUser.email }}</td>
  99. <td>{{ sUser.createdAt|date('Y-m-d') }}</td>
  100. <td>{{ sUser.lastLoginAt }}</td>
  101. <td>
  102. <div class="btn-group admin-user-menu">
  103. <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
  104. 編集
  105. <span class="caret"></span>
  106. </button>
  107. <ul class="dropdown-menu" role="menu">
  108. <li class="dropdown-header">編集メニュー</li>
  109. <li>
  110. <a href="">編集</a>
  111. </li>
  112. <li class="divider"></li>
  113. <li class="dropdown-header">ステータス</li>
  114. <li class="dropdown-button">
  115. {% if sUser.status == 1 %}
  116. <form action="/admin/user/{{ sUser._id.toString() }}/activate" method="post">
  117. <input type="hidden" name="_csrf" value="{{ _csrf() }}">
  118. <button type="submit" class="btn btn-block btn-info">承認する</button>
  119. </form>
  120. {% endif %}
  121. {% if sUser.status == 2 %}
  122. <form action="/admin/user/{{ sUser._id.toString() }}/suspend" method="post">
  123. <input type="hidden" name="_csrf" value="{{ _csrf() }}">
  124. <button type="submit" class="btn btn-block btn-warning">アカウント停止</button>
  125. </form>
  126. {% endif %}
  127. {% if sUser.status == 3 %}
  128. <form action="/admin/user/{{ sUser._id.toString() }}/activate" method="post">
  129. <input type="hidden" name="_csrf" value="{{ _csrf() }}">
  130. <button type="submit" class="btn btn-block btn-default">元に戻す</button>
  131. </form>
  132. </li>
  133. <li class="dropdown-button">
  134. {# label は同じだけど、こっちは論理削除 #}
  135. <form action="/admin/user/{{ sUser._id.toString() }}/remove" method="post">
  136. <input type="hidden" name="_csrf" value="{{ _csrf() }}">
  137. <button type="submit" class="btn btn-block btn-danger">削除する</button>
  138. </form>
  139. {% endif %}
  140. {% if sUser.status == 5 %}
  141. {# label は同じだけど、こっちは物理削除 #}
  142. <form action="/admin/user/{{ sUser._id.toString() }}/removeCompletely" method="post">
  143. <input type="hidden" name="_csrf" value="{{ _csrf() }}">
  144. <button type="submit" class="btn btn-block btn-danger">削除する</button>
  145. </form>
  146. {% endif %}
  147. </li>
  148. {% if sUser.status == 2 %} {# activated な人だけこのメニューを表示 #}
  149. <li class="divider"></li>
  150. <li class="dropdown-header">管理者メニュー</li>
  151. <li class="dropdown-button">
  152. {% if sUser.admin %}
  153. {% if sUser.username != user.username %}
  154. <form action="/admin/user/{{ sUser._id.toString() }}/removeFromAdmin" method="post">
  155. <input type="hidden" name="_csrf" value="{{ _csrf() }}">
  156. <button type="submit" class="btn btn-block btn-danger">管理者からはずす</button>
  157. </form>
  158. {% else %}
  159. <p class="alert alert-danger">自分自身を管理者から外すことはできません</p>
  160. {% endif %}
  161. {% else %}
  162. <form action="/admin/user/{{ sUser._id.toString() }}/makeAdmin" method="post">
  163. <input type="hidden" name="_csrf" value="{{ _csrf() }}">
  164. <button type="submit" class="btn btn-block btn-primary">管理者にする</button>
  165. </form>
  166. {% endif %}
  167. </li>
  168. {% endif %}
  169. </ul>
  170. </div>
  171. </td>
  172. </tr>
  173. {% endfor %}
  174. </tbody>
  175. </table>
  176. <ul class="pagination">
  177. <li {% if pager.currentPage == 1 %}class="disabled"{% endif %}>
  178. <a href="/admin/users?page={{ pager.previous|default(1) }}">&laquo;</a>
  179. </li>
  180. {% if pager.previousDots %}
  181. <li><a href="#">...</a></li>
  182. {% endif %}
  183. {% for page in pager.pages %}
  184. <li {% if pager.currentPage == page %}class="active"{% endif %}>
  185. <a href="/admin/users?page={{ page }}">{{ page }}</a>
  186. </li>
  187. {% endfor %}
  188. {% if pager.nextDots %}
  189. <li><a href="#">...</a></li>
  190. {% endif %}
  191. <li {% if pager.currentPage == pager.pageCount %}class="disabled"{% endif %}>
  192. <a href="/admin/users?page={{ pager.next|default(pager.pageCount) }}">&raquo;</a>
  193. </li>
  194. </ul>
  195. </div>
  196. </div>
  197. </div>
  198. {% endblock content_main %}
  199. {% block content_footer %}
  200. {% endblock content_footer %}