feat(front) : maj @malio/layer-ui 1.7.1 et refonte des drawers

- adaptation a l'API MalioDrawer 1.7 (titre via slot #header, footer frere du body scrollable)
- footer fixe : boutons 150px, justify-between, bordures header/footer
- permissions en accordeon Malio par module (RoleDrawer + UserRbacDrawer)
- cases a cocher sur une seule colonne
- suppression de PermissionGroup, devenu inutilise

Ajustements restants (layers/titres) a suivre.
This commit is contained in:
2026-05-27 16:53:06 +02:00
parent 43d80df1e1
commit 7c2e570fa0
7 changed files with 198 additions and 160 deletions
@@ -1,11 +1,17 @@
<template>
<MalioDrawer
:model-value="modelValue"
:title="t('admin.users.drawer.title', { username: user?.username ?? '' })"
drawer-class="w-full max-w-lg"
drawer-class="w-full max-w-[450px]"
header-class="border-b border-black"
footer-class="justify-between border-t border-black p-6"
@update:model-value="emit('update:modelValue', $event)"
>
<div class="flex flex-col gap-6 p-4">
<template #header>
<h2 class="text-[24px] font-bold">
{{ t('admin.users.drawer.title', { username: user?.username ?? '' }) }}
</h2>
</template>
<div class="flex flex-col gap-4 py-4">
<!-- Etat d'erreur de chargement des referentiels : bloque la
sauvegarde pour empecher un ecrasement silencieux des droits. -->
<div
@@ -60,18 +66,39 @@
<div v-if="permissionsByModule.length === 0" class="text-sm text-neutral-400">
{{ t('admin.roles.permissions.noPermissions') }}
</div>
<div class="flex flex-col gap-4">
<PermissionGroup
<!-- Un panneau d'accordeon par module (mode multiple) ; le compteur
selectionnees/total reste visible dans l'en-tete replie. -->
<MalioAccordion v-else v-model="openDirectModules">
<MalioAccordionItem
v-for="group in permissionsByModule"
:key="group.module"
:module="group.module"
:module-label="group.module"
:permissions="group.permissions"
:selected-ids="selectedDirectPermissionIds"
@toggle="handleTogglePermission"
@toggle-all="handleToggleAll"
/>
</div>
:value="group.module"
:title="`${group.module} (${directSelectedCount(group)}/${group.permissions.length})`"
header-class="capitalize"
>
<div class="flex flex-col gap-3">
<!-- Tout selectionner pour ce module -->
<MalioCheckbox
:id="`direct-group-${group.module}`"
:label="t('admin.roles.permissions.selectAll')"
:model-value="directAllSelected(group)"
label-class="font-semibold text-sm text-neutral-700"
@update:model-value="(val: boolean) => handleToggleAll(group.module, val)"
/>
<div class="flex flex-col gap-2">
<MalioCheckbox
v-for="perm in group.permissions"
:id="`direct-perm-${perm.id}`"
:key="perm.id"
:label="perm.label"
:model-value="selectedDirectPermissionIds.has(perm.id)"
label-class="text-sm text-neutral-600"
@update:model-value="(val: boolean) => handleTogglePermission(perm.id, val)"
/>
</div>
</div>
</MalioAccordionItem>
</MalioAccordion>
</div>
<!-- Section Sites autorises (ticket 2 module Sites) -->
@@ -103,21 +130,25 @@
<EffectivePermissions :permissions="effectivePermissions" />
</div>
<!-- Boutons -->
<div class="flex justify-end gap-3 border-t border-neutral-200 pt-4">
<MalioButton
:label="t('common.cancel')"
variant="tertiary"
@click="emit('update:modelValue', false)"
/>
<MalioButton
:label="t('common.save')"
variant="primary"
:disabled="saving || loadFailed"
@click="handleSave"
/>
</div>
</div>
<!-- Footer fixe : depuis la 1.7.1 le slot #footer est un frere du body
scrollable (shrink-0), donc reellement fige sans sticky. -->
<template #footer>
<MalioButton
:label="t('common.cancel')"
variant="tertiary"
button-class="w-[150px]"
@click="emit('update:modelValue', false)"
/>
<MalioButton
:label="t('common.save')"
variant="primary"
button-class="w-[150px]"
:disabled="saving || loadFailed"
@click="handleSave"
/>
</template>
</MalioDrawer>
</template>
@@ -158,6 +189,19 @@ const selectedRoleIds = ref(new Set<number>())
const selectedDirectPermissionIds = ref(new Set<number>())
const selectedSiteIds = ref(new Set<number>())
// Modules ouverts dans l'accordeon des permissions directes (mode multiple)
const openDirectModules = ref<string[]>([])
// Nombre de permissions directes selectionnees pour un module donne
function directSelectedCount(group: PermissionModule): number {
return group.permissions.filter(p => selectedDirectPermissionIds.value.has(p.id)).length
}
// Vrai si toutes les permissions directes du module sont selectionnees
function directAllSelected(group: PermissionModule): boolean {
return group.permissions.length > 0 && directSelectedCount(group) === group.permissions.length
}
// Detecter l'auto-edition
const isSelfEdit = computed(() => props.user?.id === auth.user?.id)