Add per-role badge colors

This commit is contained in:
2026-07-20 10:08:14 -04:00
parent ffe9fa1cce
commit 03c6adc77e
5 changed files with 119 additions and 4 deletions

View File

@@ -34,7 +34,8 @@
v-for="role in user.roles"
:key="role.roleid"
class="badge"
:class="role.rolename === 'admin' ? 'badge-primary' : 'badge-secondary'"
:class="roleBadgeClass(role)"
:style="roleBadgeStyle(role)"
>
{{ role.rolename }}
</span>
@@ -83,7 +84,7 @@
<tbody>
<tr v-for="role in roles" :key="role.roleid">
<td>
<span class="badge" :class="role.rolename === 'admin' ? 'badge-primary' : 'badge-secondary'">
<span class="badge" :class="roleBadgeClass(role)" :style="roleBadgeStyle(role)">
{{ role.rolename }}
</span>
</td>
@@ -214,6 +215,11 @@
</div>
</div>
<div class="form-group">
<label>Badge color</label>
<ColorSwatchPicker v-model="roleForm.color" />
</div>
<div class="form-group" v-if="!editingRole?.isadmin">
<label>Permissions</label>
<p class="text-muted" style="font-size: 0.85rem; margin: 0 0 0.5rem 0">
@@ -289,6 +295,9 @@ import { ref, reactive, onMounted } from 'vue'
import { usersApi } from '../../api'
import { useAuthStore } from '../../stores/auth'
import { apiError } from '../../utils/apiError'
import ColorSwatchPicker from '@/components/ColorSwatchPicker.vue'
const DEFAULT_ROLE_COLOR = '#0d6efd'
const authStore = useAuthStore()
const currentUserId = authStore.user?.userid
@@ -323,9 +332,32 @@ const userForm = reactive({
const roleForm = reactive({
rolename: '',
description: '',
color: DEFAULT_ROLE_COLOR,
permissions: []
})
// Role badge: use the role's own color when set (contrast-aware text), else
// fall back to the legacy admin=primary / other=gray classes.
function isLightColor(color) {
if (!color) return false
const hex = color.replace('#', '')
if (hex.length !== 6) return false
const r = parseInt(hex.slice(0, 2), 16)
const g = parseInt(hex.slice(2, 4), 16)
const b = parseInt(hex.slice(4, 6), 16)
return (r * 299 + g * 587 + b * 114) / 1000 > 155
}
function roleBadgeClass(role) {
if (role.color) return ''
return role.rolename === 'admin' ? 'badge-primary' : 'badge-secondary'
}
function roleBadgeStyle(role) {
if (!role.color) return null
return { background: role.color, color: isLightColor(role.color) ? '#000' : '#fff' }
}
async function loadData() {
loading.value = true
try {
@@ -459,6 +491,7 @@ function editRole(role) {
editingRole.value = role
roleForm.rolename = role.rolename
roleForm.description = role.description || ''
roleForm.color = role.color || DEFAULT_ROLE_COLOR
roleForm.permissions = role.permissions ? [...role.permissions] : []
}
@@ -467,6 +500,7 @@ function closeRoleModal() {
editingRole.value = null
roleForm.rolename = ''
roleForm.description = ''
roleForm.color = DEFAULT_ROLE_COLOR
roleForm.permissions = []
}
@@ -476,6 +510,7 @@ async function saveRole() {
try {
const data = {
description: roleForm.description,
color: roleForm.color,
permissions: roleForm.permissions
}