userList.html 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. <html>
  2. <head>
  3. <title>User List</title>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
  6. <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
  7. <script type="text/javascript" src="../../script/jquery.min.js"></script>
  8. <script type="text/javascript" src="../../script/semantic/semantic.min.js"></script>
  9. <!-- <script type="text/javascript" src="../../script/ao_module.js"></script> -->
  10. </head>
  11. <body>
  12. <div class="ui container">
  13. <div class="ui basic segment">
  14. <div class="ui header">
  15. <i class="user icon"></i>
  16. <div class="content">
  17. Manage Users
  18. <div class="sub header">Manage registered users</div>
  19. </div>
  20. </div>
  21. <button class="ui primary small button" onclick="showNewUserUI();">
  22. <i class="add icon"></i>Create
  23. </button>
  24. <button id="editbtn" class="ui small disabled button" onclick="showEditUI();">
  25. <i class="edit icon"></i>Edit
  26. </button>
  27. <button id="editUserButton" class="ui small negative disabled right floated button" onclick="removeUser();">
  28. Remove
  29. </button>
  30. </div>
  31. <div class="ui styled fluid accordion">
  32. <div class="title">
  33. <i class="dropdown icon"></i>
  34. Advance Operations
  35. </div>
  36. <div class="content">
  37. <h3>Import from CSV</h3>
  38. <p>Example Structure of the csv format (one user per row)</p>
  39. <table class="ui mini celled table" style="max-width: 500px;">
  40. <tbody>
  41. <tr>
  42. <td>User Name</td>
  43. <td>Default Password</td>
  44. <td>Default Group</td>
  45. </tr>
  46. </tbody>
  47. </table>
  48. <p>(Please make sure the group exists before import)</p>
  49. <button id="importbtn" class="ui small green button" onclick="importFromCSV();">
  50. <i class="upload icon"></i>Import from CSV
  51. </button>
  52. <button id="importbtn" class="ui small button" onclick="window.open('../users/template.csv');">
  53. Download CSV Template
  54. </button>
  55. <div class="ui divider"></div>
  56. <h3>Multi-Selection Remove</h3>
  57. <p>Select multiple users by their user group</p>
  58. <div class="ui selection dropdown">
  59. <input id="usergroupselector" type="hidden" name="Group">
  60. <i class="dropdown icon"></i>
  61. <div class="default text">Group</div>
  62. <div id="grouplist" class="menu">
  63. </div>
  64. </div>
  65. <button class="ui red button" onclick="deleteUsersInGroup();">Remove All Users in Group</button>
  66. <br><br>
  67. <div class="ui checkbox">
  68. <input id="mustbeonegroup" type="checkbox" name="iff">
  69. <label>only if the user is in exactly one group</label>
  70. </div>
  71. </div>
  72. </div>
  73. <table class="ui very basic celled table">
  74. <thead>
  75. <tr>
  76. <th>Username</th>
  77. <th>Permission Group</th>
  78. <th>Select</th>
  79. </tr>
  80. </thead>
  81. <tbody id="userTable" >
  82. </tbody>
  83. </table>
  84. <br><br>
  85. </div>
  86. <!-- Import Confirm Dialog-->
  87. <div class="ui modal" id="confirmImport">
  88. <i class="close icon"></i>
  89. <div class="header">
  90. Import Users
  91. </div>
  92. <div class="content">
  93. <div class="description">
  94. <div class="ui header">Confirm importing the following users?</div>
  95. <table class="ui celled table">
  96. <thead>
  97. <tr><th>Username</th>
  98. <th>Default Password</th>
  99. <th>Group</th>
  100. </tr></thead>
  101. <tbody id="userImportPreview">
  102. </tbody>
  103. </table>
  104. </div>
  105. </div>
  106. <div class="actions">
  107. <div class="ui black deny button">
  108. Cancel
  109. </div>
  110. <div class="ui positive right labeled icon button" onclick="confirmImportUsers();">
  111. OK
  112. <i class="checkmark icon"></i>
  113. </div>
  114. </div>
  115. </div>
  116. <!-- Delete Confirm Dialog -->
  117. <div class="ui modal" id="deleteConfirmDialog">
  118. <i class="close icon"></i>
  119. <div class="header" style="color: #eb4034;">
  120. <i class="user times icon"></i> Remove Users
  121. </div>
  122. <div class="content">
  123. <div class="description">
  124. <div class="ui header">The following users will be removed from the system. This action is <span style="color: #eb4034;">NOT REVERSIBLE</span>.</div>
  125. <div id="removePendingUsers" class="ui bulleted list">
  126. </div>
  127. </div>
  128. </div>
  129. <div class="actions">
  130. <div class="ui black deny button">
  131. Cancel
  132. </div>
  133. <div class="ui red right labeled icon button" onclick="confirmRemoval(this);">
  134. Confirm Removal
  135. <i class="checkmark icon"></i>
  136. </div>
  137. </div>
  138. </div>
  139. <!-- Error Display Dialog-->
  140. <div class="ui basic modal errormodal">
  141. <div class="ui icon header">
  142. <i class="red remove icon"></i>
  143. Some accounts cannot be created
  144. </div>
  145. <div class="content">
  146. <p class="errormessage"></p>
  147. </div>
  148. <div class="actions">
  149. <div class="ui ok inverted button">
  150. <i class="checkmark icon"></i>
  151. OK
  152. </div>
  153. </div>
  154. </div>
  155. <script>
  156. //Init UI elements
  157. $('.ui.accordion').accordion();
  158. $('.ui.dropdown').dropdown();
  159. //Init group list
  160. $.get("../../system/permission/listgroup", function(data){
  161. $("#grouplist").html("");
  162. if (data.error !== undefined){
  163. console.log(data.error);
  164. }else{
  165. data.forEach(group => {
  166. $("#grouplist").append(`<div class="item" data-value="${group}">${group}</div>`);
  167. });
  168. }
  169. });
  170. //Init User List
  171. initUserList();
  172. function initUserList(){
  173. $("#userTable").html("");
  174. $("#editbtn").addClass('disabled');
  175. $.ajax({
  176. url: "../../system/users/list",
  177. success: function(data){
  178. for (var i =0; i < data.length; i++){
  179. var username = data[i][0];
  180. var group = data[i][1];
  181. var profilePic = data[i][2];
  182. if (profilePic == ""){
  183. profilePic = "../users/img/noprofileicon.png"
  184. }
  185. var accountStatus = data[i][3];
  186. $("#userTable").append(`<tr>
  187. <td>
  188. <h4 class="ui image header">
  189. <img src="${profilePic}" class="ui mini rounded image">
  190. <div class="content">
  191. ${username}
  192. </div>
  193. </h4>
  194. </td>
  195. <td>
  196. ${group.join("/")}
  197. </td>
  198. <td>
  199. <div class="ui checkbox">
  200. <input type="radio" name="selectUser" value="${username}" self="${data[i][3]}" onchange="enableEdit(this);">
  201. <label></label>
  202. </div>
  203. </td>
  204. </tr>`);
  205. }
  206. },
  207. error: function(data){
  208. $("#userTable").html("<p> Failed to load user database. </p>");
  209. }
  210. });
  211. }
  212. var importPendingData = "";
  213. function importFromCSV(){
  214. //Open the native file selector for uploading a csv file
  215. ao_module_selectFiles(function(files){
  216. var targetFile = files[0];
  217. console.log(targetFile, files);
  218. //Read the csv file into string
  219. ao_module_utils.readFileFromFileObject(targetFile, function(content){
  220. //Render the preview user list
  221. $("#userImportPreview").html("");
  222. var lines = content.split("\r\n").join("\n").split("\n");
  223. lines.forEach(line => {
  224. var data = line.split(",");
  225. if (line.length < 3){
  226. return;
  227. }
  228. $("#userImportPreview").append(`
  229. <tr>
  230. <td data-label="Name">${data[0]}</td>
  231. <td data-label="DP">${data[1]}</td>
  232. <td data-label="Group">${data[2]}</td>
  233. </tr>`);
  234. });
  235. $("#confirmImport").modal("show");
  236. //Post the content to server side
  237. importPendingData = content;
  238. });
  239. }, "file", ".csv", false);
  240. }
  241. var deletePendingGroup = "";
  242. function deleteUsersInGroup(){
  243. var targetGroup = $("#usergroupselector").val();
  244. if (targetGroup == ""){
  245. return;
  246. }
  247. deletePendingGroup = targetGroup;
  248. $.get("../../system/users/list", function(data){
  249. var username = [];
  250. data.forEach(user => {
  251. var userGroup = user[1];
  252. if ($("#mustbeonegroup")[0].checked == true){
  253. if (userGroup.length == 1 && userGroup[0] == (deletePendingGroup)){
  254. username.push(user[0]);
  255. }
  256. }else{
  257. if (userGroup.includes(deletePendingGroup)){
  258. username.push(user[0]);
  259. }
  260. }
  261. });
  262. $("#removePendingUsers").html("");
  263. username.forEach(thisuser => {
  264. $("#removePendingUsers").append(`<div class="item">${thisuser}</div>`);
  265. });
  266. });
  267. $("#deleteConfirmDialog").modal("show");
  268. }
  269. function confirmRemoval(btn){
  270. let group = deletePendingGroup;
  271. let removeUsersWithOneGroupOnly = $("#mustbeonegroup")[0].checked;
  272. $(btn).addClass("loading");
  273. $.ajax({
  274. url :"../../system/auth/groupdel",
  275. data: {group: group, exact: removeUsersWithOneGroupOnly},
  276. success: function(data){
  277. $("#deleteConfirmDialog").modal("hide");
  278. $(btn).removeClass("loading");
  279. initUserList();
  280. }
  281. })
  282. }
  283. function confirmImportUsers(){
  284. $.ajax({
  285. url: "../../system/auth/csvimport",
  286. data: {csv: importPendingData},
  287. success: function(data){
  288. //The returned data should ba list of errors (if any)
  289. if (data.length == 0){
  290. //Reload the list
  291. initUserList();
  292. }else{
  293. //Display error list
  294. console.log(data);
  295. $(".errormodal").modal("show");
  296. var errmsg = data.join("<br>");
  297. $(".errormessage").html(errmsg);
  298. initUserList();
  299. }
  300. }
  301. });
  302. }
  303. function showNewUserUI(){
  304. ao_module_newfw({
  305. url: "user.system",
  306. width: 530,
  307. height: 740,
  308. appicon: "SystemAO/users/img/user-white.svg",
  309. title: "Create New User",
  310. callback: "finishCreateHandler",
  311. parent: ao_module_windowID
  312. });
  313. }
  314. function showEditUI(){
  315. var username = $("input[name='selectUser']:checked").val();
  316. ao_module_newfw({
  317. url:"SystemAO/users/editUser.html#" + encodeURIComponent(username),
  318. width: 530,
  319. height: 740,
  320. appicon: "SystemAO/users/img/user-white.svg",
  321. title: "Edit User",
  322. callback: "finishCreateHandler",
  323. parent: ao_module_windowID
  324. });
  325. }
  326. function removeUser(){
  327. var username = $("input[name='selectUser']:checked").val();
  328. if (confirm("Remove " + username + " from the system PERMANENTLY?")){
  329. $.ajax({
  330. url: "../../system/users/removeUser",
  331. data: {username: username},
  332. method: "POST",
  333. success: function(data){
  334. if (data.error !== undefined){
  335. alert(data.error);
  336. }else{
  337. //Reload the list
  338. initUserList();
  339. }
  340. }
  341. });
  342. }
  343. }
  344. function finishCreateHandler(state){
  345. if (state){
  346. initUserList();
  347. }
  348. }
  349. function enableEdit(object){
  350. if ($(object).attr("self") != "true"){
  351. $("#editUserButton").removeClass("disabled");
  352. $("#editbtn").removeClass("disabled");
  353. }else{
  354. $("#editUserButton").addClass("disabled");
  355. $("#editbtn").removeClass("disabled");
  356. }
  357. }
  358. </script>
  359. </body>
  360. </html>