2026-08-21 17:48:59 +02:00
{% extends "base.html" %}
{% block title %}Permissions — {{ role.name }}{% endblock %}
{% block content %}
< div class = "container-fluid" >
< h1 > Permissions du rôle « {{ role.name }} »< / h1 >
2026-08-21 20:10:29 +02:00
{% if role.slug == 'super_admin' %}
< div class = "alert alert-danger" > < strong > Super administrateur — accès complet< / strong > < br > Ce rôle possède automatiquement toutes les permissions de l'application et ne peut pas être modifié.< / div >
{% else %}< p class = "text-muted" > Les sections sont repliées par défaut. Les intitulés sont fonctionnels ; le code technique est affiché en second niveau.< / p >
2026-08-21 17:48:59 +02:00
< form method = "post" >
< input type = "hidden" name = "csrf_token" value = "{{ csrf_token() }}" >
{% for module, permissions in permissions_list|groupby('module') %}
{% set section_id = 'permissions-' ~ (module|slugify) %}
< details class = "card mb-3 permission-section" >
< summary class = "card-header d-flex align-items-center gap-2" style = "cursor:pointer;list-style:none" >
< span class = "me-auto" > < i class = "bi bi-chevron-right section-chevron" > < / i > < strong > {{ permission_labels.get(module, module|replace('_', ' ')|title) }}< / strong > < small class = "text-muted" > ({{ permissions|length }})< / small > < / span >
< label class = "small mb-0" onclick = "event.stopPropagation()" >
2026-08-21 17:58:28 +02:00
< input type = "checkbox" class = "section-toggle me-1" data-section = "section-{{ section_id }}" > Tout sélectionner
2026-08-21 17:48:59 +02:00
< / label >
< / summary >
< div class = "card-body row g-2" >
{% for permission in permissions %}
< div class = "col-xl-3 col-md-4" >
< label class = "border rounded p-2 d-block h-100" >
< input type = "checkbox" class = "permission-check section-{{ section_id }}" name = "permission_ids" value = "{{ permission.id }}" { % if permission . id in selected % } checked { % endif % } >
2026-08-21 20:10:29 +02:00
< strong > {{ permission.name }}< / strong > < br >
< small class = "text-muted" > {{ permission.description }}< / small > < br >
< small class = "text-secondary" > Code : {{ permission.code }}< / small >
2026-08-21 17:48:59 +02:00
< / label >
< / div >
{% endfor %}
< / div >
< / details >
{% else %}
< p class = "text-muted" > Aucune permission. Exécutez la migration RBAC.< / p >
{% endfor %}
< button class = "btn btn-primary" > Enregistrer les permissions< / button >
< a class = "btn btn-outline-secondary ms-2" href = "{{ url_for('admin.roles') }}" > Annuler< / a >
< / form >
2026-08-21 20:10:29 +02:00
{% endif %}
2026-08-21 17:48:59 +02:00
< / div >
< style >
.permission-section[open] .section-chevron { transform: rotate(90deg); }
.section-chevron { display:inline-block; transition:transform .15s ease; }
.permission-section > summary::-webkit-details-marker { display:none; }
< / style >
< script >
document.querySelectorAll('.section-toggle').forEach(function(toggle) {
var checks = document.querySelectorAll('.' + toggle.dataset.section);
var sync = function() {
var values = Array.from(checks);
toggle.checked = values.length > 0 & & values.every(function(check) { return check.checked; });
toggle.indeterminate = values.some(function(check) { return check.checked; }) & & !toggle.checked;
};
toggle.addEventListener('change', function(event) {
event.stopPropagation();
checks.forEach(function(check) { check.checked = toggle.checked; });
toggle.indeterminate = false;
});
checks.forEach(function(check) { check.addEventListener('change', sync); });
sync();
});
< / script >
{% endblock %}