layout.html 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. {% extends "layout.html" %}
  2. {% block content %}
  3. <div class="flex justify-between items-center mb-10">
  4. <div>
  5. <h2 class="text-4xl font-black text-white tracking-tighter italic">User Management</h2>
  6. <p class="text-gray-500 font-bold uppercase text-[10px] tracking-widest mt-2">Manage access and RBAC roles</p>
  7. </div>
  8. <button onclick="openAddUser()" class="bg-blue-600 hover:bg-blue-500 px-8 py-3 rounded-xl font-black shadow-2xl transition transform hover:scale-105 text-white uppercase text-xs tracking-widest">+ Create User</button>
  9. </div>
  10. <div class="bg-[#12161f] border border-gray-800 rounded-3xl overflow-hidden shadow-2xl">
  11. <table class="w-full text-left">
  12. <thead class="bg-black/20 text-[10px] font-black text-gray-500 uppercase tracking-widest border-b border-gray-800">
  13. <tr>
  14. <th class="p-6">Username</th>
  15. <th class="p-6">Role</th>
  16. <th class="p-6">Templates</th>
  17. <th class="p-6 text-right">Actions</th>
  18. </tr>
  19. </thead>
  20. <tbody class="divide-y divide-gray-800">
  21. {% for u, data in users.items() %}
  22. <tr class="hover:bg-white/[0.02] transition">
  23. <td class="p-6 font-bold text-white">{{ u }}</td>
  24. <td class="p-6">
  25. <span class="px-3 py-1 rounded-full text-[9px] font-black uppercase border {% if data.role=='admin' %}border-red-500/30 text-red-400 bg-red-500/10{% else %}border-blue-500/30 text-blue-400 bg-blue-500/10{% endif %}">
  26. {{ data.role }}
  27. </span>
  28. </td>
  29. <td class="p-6 text-xs text-gray-500">{{ data.assigned_templates|join(', ') or 'None' }}</td>
  30. <td class="p-6 text-right">
  31. <button type="button"
  32. data-user="{{ u }}"
  33. data-role="{{ data.role }}"
  34. data-templates="{{ data.assigned_templates|join(',') if data.assigned_templates else '' }}"
  35. onclick="editUser(this)"
  36. class="text-blue-500 hover:text-blue-400 text-[10px] font-black uppercase mr-4">
  37. Edit
  38. </button>
  39. {% if u != 'admin' %}
  40. <a href="/users/delete/{{ u|urlencode }}" onclick="return confirm('Are you sure you want to delete this user?')" class="text-red-500 hover:text-red-400 text-[10px] font-black uppercase">Delete</a>
  41. {% endif %}
  42. </td>
  43. </tr>
  44. {% endfor %}
  45. </tbody>
  46. </table>
  47. </div>
  48. <div id="userModal" class="hidden fixed inset-0 bg-black/90 backdrop-blur-md flex items-center justify-center z-50 p-4">
  49. <div class="bg-[#12161f] border border-gray-800 w-full max-w-md rounded-3xl p-8 shadow-2xl">
  50. <h3 id="modalTitle" class="text-xl font-black text-white mb-6 uppercase">Add User</h3>
  51. <form action="/users/save" method="POST" class="space-y-4">
  52. <input type="hidden" name="action" id="userAction" value="add">
  53. <input type="hidden" name="old_username" id="oldUsername">
  54. <input type="text" name="username" id="userName" placeholder="Username" required class="w-full bg-[#0b0e14] border border-gray-800 rounded-xl p-3 text-sm font-bold text-white outline-none">
  55. <input type="password" name="password" id="userPass" placeholder="Password (Leave blank to keep current)" class="w-full bg-[#0b0e14] border border-gray-800 rounded-xl p-3 text-sm font-bold text-white outline-none">
  56. <select name="role" id="userRole" class="w-full bg-[#0b0e14] border border-gray-800 rounded-xl p-3 text-sm font-bold text-white outline-none">
  57. <option value="user">User (Restricted)</option>
  58. <option value="admin">Administrator</option>
  59. </select>
  60. <div class="bg-black/20 p-4 rounded-xl border border-gray-800">
  61. <label class="text-[10px] font-black text-gray-500 uppercase block mb-3">Assigned Templates</label>
  62. <div class="grid grid-cols-2 gap-2 max-h-48 overflow-y-auto pr-2">
  63. {% for t in all_templates %}
  64. <label class="flex items-center gap-2 text-xs text-gray-400 cursor-pointer hover:text-white">
  65. <input type="checkbox" name="assigned_templates[]" value="{{ t }}" class="template-check rounded border-gray-700 bg-gray-900 text-blue-600">
  66. {{ t }}
  67. </label>
  68. {% endfor %}
  69. </div>
  70. </div>
  71. <div class="flex gap-4 pt-4">
  72. <button type="button" onclick="closeUserModal()" class="flex-1 bg-gray-800 text-gray-400 font-bold py-3 rounded-xl uppercase text-xs hover:text-white transition">Cancel</button>
  73. <button type="submit" class="flex-1 bg-blue-600 text-white font-black py-3 rounded-xl uppercase text-xs hover:bg-blue-500 transition">Save</button>
  74. </div>
  75. </form>
  76. </div>
  77. </div>
  78. <script>
  79. function openAddUser() {
  80. document.getElementById('userModal').classList.remove('hidden');
  81. document.getElementById('userAction').value = 'add';
  82. document.getElementById('modalTitle').innerText = 'Add User';
  83. document.getElementById('userName').value = '';
  84. document.getElementById('userPass').value = '';
  85. document.getElementById('userPass').placeholder = 'Password (Required)';
  86. document.getElementById('userPass').required = true;
  87. var checkboxes = document.querySelectorAll('.template-check');
  88. for (var i = 0; i < checkboxes.length; i++) {
  89. checkboxes[i].checked = false;
  90. }
  91. }
  92. function editUser(btn) {
  93. // Διαβάζουμε τα δεδομένα με ασφάλεια από το κουμπί
  94. var u = btn.getAttribute('data-user');
  95. var role = btn.getAttribute('data-role');
  96. var rawTemplates = btn.getAttribute('data-templates');
  97. // Σπάμε το "AWMN,LOCAL" σε λίστα
  98. var templates = rawTemplates ? rawTemplates.split(',') : [];
  99. // Εμφάνιση Modal και γέμισμα πεδίων
  100. document.getElementById('userModal').classList.remove('hidden');
  101. document.getElementById('userAction').value = 'edit';
  102. document.getElementById('oldUsername').value = u;
  103. document.getElementById('userName').value = u;
  104. document.getElementById('userRole').value = role;
  105. document.getElementById('modalTitle').innerText = 'Edit User';
  106. document.getElementById('userPass').value = '';
  107. document.getElementById('userPass').placeholder = 'Password (Leave blank to keep current)';
  108. document.getElementById('userPass').required = false;
  109. // Τσεκάρισμα των σωστών Templates
  110. var checkboxes = document.querySelectorAll('.template-check');
  111. for (var i = 0; i < checkboxes.length; i++) {
  112. checkboxes[i].checked = templates.includes(checkboxes[i].value);
  113. }
  114. }
  115. function closeUserModal() {
  116. document.getElementById('userModal').classList.add('hidden');
  117. }
  118. </script>
  119. {% endblock %}