layout.html 7.2 KB

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