refactor(templates): use role_display_name and improve role/admin clarity
Clarify role display names, refine admin role labeling, and update confirmation messages for better UX.
This commit is contained in:
5 files changed
+106
-12
No files matched your search
@@ -0,0 +1,90 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Roles{% endblock %}
|
||||
{% block breadcrumb %}
|
||||
<nav class="mb-4" aria-label="Breadcrumb">
|
||||
<ol class="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400">
|
||||
<li><a href="{% url 'dashboard' %}" class="hover:text-gray-700 dark:hover:text-gray-300">Dashboard</a></li>
|
||||
<li class="text-gray-300 dark:text-gray-600">/</li>
|
||||
<li class="text-gray-900 dark:text-white font-medium" aria-current="page">Roles</li>
|
||||
</ol>
|
||||
</nav>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="mb-6 flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold">Roles</h1>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-sm mt-1">{{ roles.count }} role{{ roles.count|pluralize }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if request.user.is_admin %}
|
||||
<div class="dk-card divide-y divide-gray-200 dark:divide-gray-600 mb-6">
|
||||
<div class="px-6 py-4"><h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100">Create Custom Role</h3><p class="text-xs text-gray-500 mt-0.5">Define a new role for your organization</p></div>
|
||||
<div class="px-6 py-5">
|
||||
<form method="post" action="{% url 'role-add' %}" class="flex items-end gap-3">
|
||||
{% csrf_token %}
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-500 mb-1">Name</label>
|
||||
<input type="text" name="name" required placeholder="e.g. Senior Developer"
|
||||
class="w-60 text-sm border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 bg-white dark:bg-gray-950 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
<button type="submit" class="dk-btn dk-btn-primary"><i class="fas fa-plus"></i> Create</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="dk-card overflow-hidden divide-y divide-gray-200 dark:divide-gray-600">
|
||||
<div class="px-6 py-4"><h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100">All Roles</h3><p class="text-xs text-gray-500 mt-0.5">System roles cannot be deleted</p></div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-800">
|
||||
<th class="text-left px-4 py-3 font-semibold text-xs text-gray-500 dark:text-gray-400">Name</th>
|
||||
<th class="text-left px-4 py-3 font-semibold text-xs text-gray-500 dark:text-gray-400">Slug</th>
|
||||
<th class="text-left px-4 py-3 font-semibold text-xs text-gray-500 dark:text-gray-400">Type</th>
|
||||
<th class="text-left px-4 py-3 font-semibold text-xs text-gray-500 dark:text-gray-400">Users</th>
|
||||
{% if request.user.is_admin %}
|
||||
<th class="text-right px-4 py-3 font-semibold text-xs text-gray-500 dark:text-gray-400">Actions</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for r in roles %}
|
||||
<tr class="border-b border-gray-100 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800/50">
|
||||
<td class="px-4 py-3 font-medium text-gray-900 dark:text-white">
|
||||
{{ r.name }}
|
||||
{% if r.slug in admin_roles %}
|
||||
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400 ml-1.5">System</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-gray-500 dark:text-gray-400 font-mono text-xs">{{ r.slug }}</td>
|
||||
<td class="px-4 py-3">
|
||||
{% if r.slug in admin_roles %}
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400">Hardcoded — full access</span>
|
||||
{% else %}
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400">Custom — follows rules</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-gray-500 dark:text-gray-400">{{ r.users.count }}</td>
|
||||
{% if request.user.is_admin %}
|
||||
<td class="px-4 py-3 text-right">
|
||||
{% if not r.is_system %}
|
||||
<form method="post" action="{% url 'role-delete' r.id %}" class="inline">
|
||||
{% csrf_token %}
|
||||
<button type="button" @click="confirmAction({title:'Delete Role', message:'Delete role <strong>{{ r.name|escapejs }}</strong>? Users with this role will become unassigned.', confirmText:'Delete', danger:true, onConfirm:function(){ $el.closest('form').submit() }})" class="inline-flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium text-red-600 dark:text-red-400 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors shadow-sm">Delete</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<span class="text-xs text-gray-400 italic">Protected</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="5" class="text-center py-12 text-gray-400">No roles defined</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -21,8 +21,9 @@
|
||||
<a href="/dashboard/tickets/" class="dk-sidebar-link dk-sidebar-link-inactive"><i class="fas fa-ticket w-5 text-center"></i><span>Tickets</span></a>
|
||||
<a href="/dashboard/ticket-timeline/" class="dk-sidebar-link dk-sidebar-link-inactive"><i class="fas fa-calendar w-5 text-center"></i><span>Ticket Timeline</span></a>
|
||||
<a href="/dashboard/epics/" class="dk-sidebar-link dk-sidebar-link-inactive"><i class="fas fa-flag w-5 text-center"></i><span>Epics</span></a>
|
||||
{% if request.user.role == 'superadmin' %}
|
||||
{% if request.user.is_admin %}
|
||||
<p class="px-3 text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase tracking-wider mt-6 mb-2">Administration</p>
|
||||
<a href="/dashboard/roles/" class="dk-sidebar-link dk-sidebar-link-inactive" @click="mobileSidebar = false"><i class="fas fa-user-tag w-5 text-center"></i><span>Roles</span></a>
|
||||
<a href="/dashboard/users/" class="dk-sidebar-link {% if '/users/' in request.path %}dk-sidebar-link-active{% else %}dk-sidebar-link-inactive{% endif %}" title="Users" @click="mobileSidebar = false">
|
||||
<i class="fas fa-users w-5 text-center"></i><span class="flex-1">Users</span>
|
||||
<span class="dk-badge bg-blue-600 text-white text-[10px]">{{ total_users }}</span>
|
||||
|
||||
@@ -54,8 +54,11 @@
|
||||
<a href="/dashboard/settings/ui/" class="dk-sidebar-link {% if '/settings/ui/' in request.path %}dk-sidebar-link-active{% else %}dk-sidebar-link-inactive{% endif %}" title="UI Settings">
|
||||
<i class="fas fa-cog w-5 text-center"></i><span x-show="sidebarOpen">UI Settings</span>
|
||||
</a>
|
||||
{% if request.user.role == 'superadmin' %}
|
||||
{% if request.user.is_admin %}
|
||||
<p class="dk-sidebar-group px-3 text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase tracking-wider mt-6 mb-2"><span x-show="sidebarOpen">Administration</span></p>
|
||||
<a href="/dashboard/roles/" class="dk-sidebar-link {% if '/roles/' in request.path %}dk-sidebar-link-active{% else %}dk-sidebar-link-inactive{% endif %}" title="Roles">
|
||||
<i class="fas fa-user-tag w-5 text-center"></i><span x-show="sidebarOpen">Roles</span>
|
||||
</a>
|
||||
<a href="/dashboard/users/" class="dk-sidebar-link {% if '/users/' in request.path %}dk-sidebar-link-active{% else %}dk-sidebar-link-inactive{% endif %}" title="Users">
|
||||
<i class="fas fa-users w-5 text-center"></i><span x-show="sidebarOpen" class="flex-1">Users</span>
|
||||
<span class="dk-badge bg-blue-600 text-white text-[10px]" x-show="sidebarOpen">{{ total_users }}</span>
|
||||
|
||||
@@ -785,9 +785,9 @@ class="space-y-6"
|
||||
<select name="role" required
|
||||
class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
||||
<option value="">Select a role</option>
|
||||
{% for role_key, role_label in role_choices %}
|
||||
{% if role_key not in admin_roles %}
|
||||
<option value="{{ role_key }}">{{ role_label }}</option>
|
||||
{% for role in role_choices %}
|
||||
{% if role.slug not in admin_roles %}
|
||||
<option value="{{ role.slug }}">{{ role.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
@@ -826,7 +826,7 @@ class="space-y-6"
|
||||
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
{% for perm in permissions %}
|
||||
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/30">
|
||||
<td class="px-4 py-3 font-medium text-gray-900 dark:text-white">{{ perm.get_role_display }}</td>
|
||||
<td class="px-4 py-3 font-medium text-gray-900 dark:text-white">{{ perm.role_display_name }}</td>
|
||||
<td class="px-4 py-3">
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
{% for status in perm.move_to_statuses.all %}
|
||||
@@ -842,7 +842,7 @@ class="space-y-6"
|
||||
<td class="px-4 py-3 text-right">
|
||||
<form method="post" action="{% url 'board-permission-delete' selected_project.id perm.id %}" class="inline">
|
||||
{% csrf_token %}
|
||||
<button type="button" @click="confirmAction({title:'Delete Permission', message:'Delete permission for <strong>' + '{{ perm.get_role_display|escapejs }}' + '</strong>?', confirmText:'Delete', danger:true, onConfirm:function(){ $el.closest('form').submit() }})" class="inline-flex items-center gap-1 px-2.5 py-1.5 text-xs font-medium text-red-600 dark:text-red-400 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors shadow-sm">
|
||||
<button type="button" @click="confirmAction({title:'Delete Permission', message:'Delete permission for <strong>' + '{{ perm.role_display_name|escapejs }}' + '</strong>?', confirmText:'Delete', danger:true, onConfirm:function(){ $el.closest('form').submit() }})" class="inline-flex items-center gap-1 px-2.5 py-1.5 text-xs font-medium text-red-600 dark:text-red-400 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors shadow-sm">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -722,9 +722,9 @@
|
||||
<select name="role" required
|
||||
class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none">
|
||||
<option value="">Select a role</option>
|
||||
{% for role_key, role_label in role_choices %}
|
||||
{% if role_key not in admin_roles %}
|
||||
<option value="{{ role_key }}">{{ role_label }}</option>
|
||||
{% for role in role_choices %}
|
||||
{% if role.slug not in admin_roles %}
|
||||
<option value="{{ role.slug }}">{{ role.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
@@ -763,7 +763,7 @@
|
||||
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
{% for perm in permissions %}
|
||||
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/30">
|
||||
<td class="px-4 py-3 font-medium text-gray-900 dark:text-white">{{ perm.get_role_display }}</td>
|
||||
<td class="px-4 py-3 font-medium text-gray-900 dark:text-white">{{ perm.role_display_name }}</td>
|
||||
<td class="px-4 py-3">
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
{% for status in perm.move_to_statuses.all %}
|
||||
@@ -779,7 +779,7 @@
|
||||
<td class="px-4 py-3 text-right">
|
||||
<form method="post" action="{% url 'board-permission-delete' project.id perm.id %}" class="inline">
|
||||
{% csrf_token %}
|
||||
<button type="button" @click="confirmAction({title:'Delete Permission', message:'Delete permission for <strong>' + '{{ perm.get_role_display|escapejs }}' + '</strong>?', confirmText:'Delete', danger:true, onConfirm:function(){ $el.closest('form').submit() }})" class="inline-flex items-center gap-1 px-2.5 py-1.5 text-xs font-medium text-red-600 dark:text-red-400 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors shadow-sm">
|
||||
<button type="button" @click="confirmAction({title:'Delete Permission', message:'Delete permission for <strong>' + '{{ perm.role_display_name|escapejs }}' + '</strong>?', confirmText:'Delete', danger:true, onConfirm:function(){ $el.closest('form').submit() }})" class="inline-flex items-center gap-1 px-2.5 py-1.5 text-xs font-medium text-red-600 dark:text-red-400 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors shadow-sm">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
Reference in new issue
Block a user