5c4bc32827
- extrait PermissionAccordion (modules/core/components) : source unique pour l'accordeon de permissions par module, utilise par RoleDrawer et UserRbacDrawer (supprime la duplication selectedCountFor/directSelectedCount + ~25 lignes de markup) - expose le type PermissionModule dans shared/types/rbac - audit-log : simplifie toggleEntity (filter au lieu de Set, valeurs uniques par construction) - default.vue : commente les valeurs en dur (232/170/47) comme issues de la maquette Figma - audit-log : corrige iconSize -> icon-size (warning eslint vue/attribute-hyphenation)
72 lines
3.0 KiB
Vue
72 lines
3.0 KiB
Vue
<template>
|
|
<!-- Accordeon de permissions groupees par module : un panneau par module,
|
|
avec compteur (selectionnees/total) dans le titre, case "Tout selectionner"
|
|
et liste des permissions individuelles. Source unique de cette UX, utilisee
|
|
par RoleDrawer (permissions du role) et UserRbacDrawer (permissions directes). -->
|
|
<MalioAccordion v-model="openModules">
|
|
<MalioAccordionItem
|
|
v-for="group in groupsByModule"
|
|
:key="group.module"
|
|
:value="group.module"
|
|
:title="`${group.module} (${selectedCountFor(group)}/${group.permissions.length})`"
|
|
header-class="capitalize"
|
|
>
|
|
<div class="flex flex-col gap-3">
|
|
<!-- Tout selectionner pour ce module -->
|
|
<MalioCheckbox
|
|
:id="`${idPrefix}-group-${group.module}`"
|
|
:label="t('admin.roles.permissions.selectAll')"
|
|
:model-value="allSelectedFor(group)"
|
|
label-class="font-semibold text-sm text-neutral-700"
|
|
@update:model-value="(val: boolean) => emit('toggle-all', group.module, val)"
|
|
/>
|
|
<div class="flex flex-col gap-2">
|
|
<MalioCheckbox
|
|
v-for="perm in group.permissions"
|
|
:id="`${idPrefix}-perm-${perm.id}`"
|
|
:key="perm.id"
|
|
:label="perm.label"
|
|
:model-value="selectedIds.has(perm.id)"
|
|
label-class="text-sm text-neutral-600"
|
|
@update:model-value="(val: boolean) => emit('toggle', perm.id, val)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</MalioAccordionItem>
|
|
</MalioAccordion>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { PermissionModule } from '~/shared/types/rbac'
|
|
|
|
const { t } = useI18n()
|
|
|
|
const props = defineProps<{
|
|
/** Groupes de permissions a afficher, un par module. */
|
|
groupsByModule: PermissionModule[]
|
|
/** Ids des permissions actuellement selectionnees. */
|
|
selectedIds: Set<number>
|
|
/** Prefixe pour les ids HTML : evite les collisions si plusieurs accordeons coexistent (ex: "role" vs "direct"). */
|
|
idPrefix: string
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
toggle: [permissionId: number, selected: boolean]
|
|
'toggle-all': [module: string, selected: boolean]
|
|
}>()
|
|
|
|
// Modules ouverts dans l'accordeon (mode multiple). Etat local : chaque instance
|
|
// du composant garde sa propre liste, pas de partage entre drawers.
|
|
const openModules = ref<string[]>([])
|
|
|
|
// Nombre de permissions selectionnees pour un module donne.
|
|
function selectedCountFor(group: PermissionModule): number {
|
|
return group.permissions.filter(p => props.selectedIds.has(p.id)).length
|
|
}
|
|
|
|
// Vrai si toutes les permissions du module sont selectionnees.
|
|
function allSelectedFor(group: PermissionModule): boolean {
|
|
return group.permissions.length > 0 && selectedCountFor(group) === group.permissions.length
|
|
}
|
|
</script>
|