mayan/apps/dashboards/ — Moteur de tableaux de bord avec widgets enfichables.
L'application Dashboards fournit un système de tableaux de bord composables. Elle définit des conteneurs nommés (Dashboard) dans lesquels n'importe quelle app peut injecter des widgets (compteurs numériques, listes d'objets). Les widgets sont rendus sous forme de panneaux Bootstrap responsives.
Il n'y a pas de modèles de base de données — tout est en mémoire, enregistré au démarrage de Django.
Dashboard (conteneur nommé, singleton)
├── Widget A (DashboardWidgetNumeric) order=0
├── Widget B (DashboardWidgetNumeric) order=1
├── Widget C (DashboardWidgetList) order=99
└── Widget D (DashboardWidgetNumeric) order=99
Chaque widget est une classe Python enregistrée dans le dashboard. Au rendu, la classe est instanciée et render(request) est appelée.
Mayan définit deux dashboards nommés :
| Dashboard | Nom interne | Défini dans | Affichage |
|---|---|---|---|
| Tableau de bord administrateur | administrator |
mayan/apps/dashboards/dashboards.py |
12 widgets système |
| Tableau de bord utilisateur | user |
mayan/apps/user_management/dashboards.py |
3 widgets personnels |
La page d'accueil affiche par défaut le dashboard user. Le paramètre COMMON_HOME_VIEW_DASHBOARD_NAME (défaut : 'user') contrôle quel dashboard est affiché sur la page d'accueil.
# config.yml — Afficher le dashboard admin par défaut
COMMON_HOME_VIEW_DASHBOARD_NAME: administrator
DashboardWidgetNumeric — CompteurWidget affichant un nombre (ou une chaîne formatée) dans un panneau avec icône, label et lien.
Template : dashboards/numeric_widget.html
class DashboardWidgetDocumentsTotal(DashboardWidgetNumeric):
icon = icon_documents
label = _(message='Total documents')
link = reverse_lazy(viewname='documents:document_list')
def get_count(self):
return Document.objects.count()
Attributs de classe :
icon — icône FontAwesomelabel — libellé traduitlink — URL vers laquelle pointe le lien du widgetlink_icon — icône du lien (défaut : external-link-alt)Méthode à surcharger : get_count() → retourne un int ou une str (ex. "1.5 Go (30.2%)").
DashboardWidgetList — ListeWidget affichant une liste d'objets sous forme de tableau.
Template : dashboards/widget_list.html
class DashboardWidgetUserRecentlyAccessedDocuments(DashboardWidgetList):
columns = ('label',)
icon = icon_documents
label = _(message='Recently accessed')
link = reverse_lazy(viewname='documents:document_recently_accessed_list')
object_list_length = 10
def get_object_list(self):
return Document.valid.filter(...)
Attributs de classe :
columns — tuple de noms de colonnes (SourceColumn)object_list_length — nombre max d'éléments affichés (défaut : 10)Méthode à surcharger : get_object_list() → retourne un QuerySet.
| Ordre | Widget | App | Description |
|---|---|---|---|
| -1 | DashboardWidgetTotalCheckouts |
checkouts | Nombre d'emprunts actifs |
| 0 | DashboardWidgetDocumentsTotal |
documents | Nombre total de documents valides |
| 1 | DashboardWidgetDocumentFilePagesTotal |
documents | Nombre total de pages |
| 2 | DashboardWidgetDocumentsInTrash |
documents | Documents dans la corbeille |
| 3 | DashboardWidgetDocumentsTypesTotal |
documents | Nombre de types de documents |
| 4 | DashboardWidgetDocumentsNewThisMonth |
documents | Nouveaux documents ce mois |
| 5 | DashboardWidgetDocumentsPagesNewThisMonth |
documents | Nouvelles pages ce mois |
| 99 | DashboardWidgetUserTotal |
user_management | Nombre d'utilisateurs |
| 99 | DashboardWidgetGroupTotal |
user_management | Nombre de groupes |
| 99 | DashboardWidgetFileCacheSizeUsed |
file_caching | Taille utilisée du cache |
| 99 | DashboardWidgetFileCacheSizeAllocated |
file_caching | Taille allouée du cache |
| 99 | DashboardWidgetRoleTotal |
permissions | Nombre de rôles |
| Ordre | Widget | App | Description |
|---|---|---|---|
| 1 | DashboardWidgetUserRecentlyAccessedDocuments |
documents | Documents récemment consultés |
| 2 | DashboardWidgetUserRecentlyCreatedDocuments |
documents | Documents récemment créés |
| 3 | DashboardWidgetUserFavoriteDocuments |
documents | Documents favoris |
1. Définition — Sous-classe de DashboardWidgetNumeric/List dans dashboard_widgets.py
2. Enregistrement — dashboard.add_widget(widget=MaClasse, order=N) dans apps.py → ready()
3. Stockage — Dashboard.widgets[MaClasse] = {'widget': MaClasse, 'order': N}
4. Tri — Au rendu, get_widgets() trie par (order, label) ASC
5. Instanciation — widget() appelé sans arguments
6. Rendu — widget.render(request) → get_count() ou get_object_list() → template HTML
7. Assemblage — Dashboard.render() collecte les HTML et les injecte dans dashboard.html
Le template dashboard.html organise les widgets en grille Bootstrap :
col-xs-12 col-sm-6 col-md-4 col-lg-3 (1 à 4 colonnes selon l'écran)col-lg-4 (3 colonnes)Chaque panneau reçoit la classe .match-height — le JavaScript utilise jQuery matchHeight pour égaliser les hauteurs.
# mon_app/dashboard_widgets.py
from mayan.apps.dashboards.classes import DashboardWidgetList
from django.utils.translation import gettext_lazy as _
class DashboardWidgetRecentInvoices(DashboardWidgetList):
columns = ('label', 'date_added')
icon = icon_invoices
label = _(message='Recent invoices')
link = reverse_lazy(viewname='invoices:invoice_list')
object_list_length = 5
def get_object_list(self):
from mayan.apps.acls.classes import AccessControlList
queryset = Invoice.objects.order_by('-date_added')
return AccessControlList.objects.restrict_queryset(
permission=permission_invoice_view,
queryset=queryset,
user=self.request.user
)
# mon_app/apps.py → ready()
from mayan.apps.dashboards.dashboards import dashboard_administrator
from .dashboard_widgets import DashboardWidgetRecentInvoices
dashboard_administrator.add_widget(
widget=DashboardWidgetRecentInvoices, order=50
)
| URL | Vue | Description |
|---|---|---|
/dashboards/ |
DashboardListView |
Liste tous les dashboards |
/dashboards/<nom>/ |
DashboardDetailView |
Affiche un dashboard spécifique |
L'app Dashboards n'a pas de permissions propres. L'accès aux données de chaque widget est filtré par ACL via AccessControlList.objects.restrict_queryset() dans get_count() ou get_object_list(). Un utilisateur voit uniquement les données pour lesquelles il possède les permissions requises.
ready() des appshas_rest_api = Falsedashboard.remove_widget(WidgetClass) permet de désactiver un widget| Fichier | Rôle |
|---|---|
classes.py |
Dashboard, BaseDashboardWidget, DashboardWidgetNumeric, DashboardWidgetList |
dashboards.py |
Instance singleton dashboard_administrator |
views.py |
DashboardListView, DashboardDetailView |
templatetags/dashboards_tags.py |
Tag {% dashboards_render_dashboard %} |
templates/dashboards/dashboard.html |
Conteneur grille Bootstrap |
templates/dashboards/numeric_widget.html |
Panneau compteur |
templates/dashboards/widget_list.html |
Panneau liste |