Configure Maven repository for unionflow-server-api dependency
This commit is contained in:
@@ -0,0 +1,775 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Configuration Système - UnionFlow</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<!-- En-tête -->
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<h3 class="mb-2">
|
||||
<i class="pi pi-cog text-purple-500 mr-2"></i>
|
||||
Configuration Système
|
||||
</h3>
|
||||
<p class="text-600 m-0">Paramètres globaux • Sécurité • Intégrations • Performance • #{configBean.derniereModification}</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<p:commandButton value="Sauvegarder configuration"
|
||||
icon="pi pi-save"
|
||||
styleClass="ui-button-success"
|
||||
action="#{configBean.sauvegarderTout}" />
|
||||
<p:commandButton value="Réinitialiser"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="ui-button-outlined ui-button-warning"
|
||||
onclick="return confirm('Réinitialiser toute la configuration ?');"
|
||||
action="#{configBean.reinitialiser}" />
|
||||
<p:commandButton value="Exporter config"
|
||||
icon="pi pi-download"
|
||||
styleClass="ui-button-outlined ui-button-secondary"
|
||||
action="#{configBean.exporterConfiguration}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statut système -->
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card bg-green-100 border-left-3 border-green-500">
|
||||
<div class="flex justify-content-between">
|
||||
<div>
|
||||
<div class="text-green-900 font-bold text-2xl">#{configBean.statutSysteme}</div>
|
||||
<div class="text-green-700">Statut Système</div>
|
||||
</div>
|
||||
<div class="bg-green-500 text-white border-round text-center"
|
||||
style="width: 3rem; height: 3rem; line-height: 3rem;">
|
||||
<i class="pi pi-check-circle text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card bg-blue-100 border-left-3 border-blue-500">
|
||||
<div class="flex justify-content-between">
|
||||
<div>
|
||||
<div class="text-blue-900 font-bold text-2xl">#{configBean.versionApplication}</div>
|
||||
<div class="text-blue-700">Version Application</div>
|
||||
</div>
|
||||
<div class="bg-blue-500 text-white border-round text-center"
|
||||
style="width: 3rem; height: 3rem; line-height: 3rem;">
|
||||
<i class="pi pi-code text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card bg-orange-100 border-left-3 border-orange-500">
|
||||
<div class="flex justify-content-between">
|
||||
<div>
|
||||
<div class="text-orange-900 font-bold text-2xl">#{configBean.utilisateursConnectes}</div>
|
||||
<div class="text-orange-700">Utilisateurs En Ligne</div>
|
||||
</div>
|
||||
<div class="bg-orange-500 text-white border-round text-center"
|
||||
style="width: 3rem; height: 3rem; line-height: 3rem;">
|
||||
<i class="pi pi-users text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card bg-purple-100 border-left-3 border-purple-500">
|
||||
<div class="flex justify-content-between">
|
||||
<div>
|
||||
<div class="text-purple-900 font-bold text-2xl">#{configBean.espaceDisque}</div>
|
||||
<div class="text-purple-700">Espace Utilisé</div>
|
||||
</div>
|
||||
<div class="bg-purple-500 text-white border-round text-center"
|
||||
style="width: 3rem; height: 3rem; line-height: 3rem;">
|
||||
<i class="pi pi-database text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Configuration par onglets -->
|
||||
<div class="card">
|
||||
<p:tabView>
|
||||
<!-- Paramètres Généraux -->
|
||||
<p:tab title="🏢 Général">
|
||||
<h:form id="formGeneral">
|
||||
<div class="ui-fluid">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Informations Application</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="nomApplication" value="Nom de l'application" />
|
||||
<p:inputText id="nomApplication" value="#{configBean.config.nomApplication}" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="description" value="Description" />
|
||||
<p:inputTextarea id="description" value="#{configBean.config.description}" rows="3" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="organisation" value="Organisation" />
|
||||
<p:inputText id="organisation" value="#{configBean.config.organisation}" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="siteWeb" value="Site web" />
|
||||
<p:inputText id="siteWeb" value="#{configBean.config.siteWeb}" placeholder="https://..." />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Paramètres Régionaux</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="langue" value="Langue par défaut" />
|
||||
<p:selectOneMenu id="langue" value="#{configBean.config.langue}">
|
||||
<f:selectItem itemLabel="Français" itemValue="fr" />
|
||||
<f:selectItem itemLabel="English" itemValue="en" />
|
||||
<f:selectItem itemLabel="العربية" itemValue="ar" />
|
||||
<f:selectItem itemLabel="Wolof" itemValue="wo" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="fuseau" value="Fuseau horaire" />
|
||||
<p:selectOneMenu id="fuseau" value="#{configBean.config.fuseauHoraire}">
|
||||
<f:selectItem itemLabel="GMT (UTC+0)" itemValue="GMT" />
|
||||
<f:selectItem itemLabel="WAT (UTC+1)" itemValue="WAT" />
|
||||
<f:selectItem itemLabel="CET (UTC+1)" itemValue="CET" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="devise" value="Devise" />
|
||||
<p:selectOneMenu id="devise" value="#{configBean.config.devise}">
|
||||
<f:selectItem itemLabel="FCFA (XOF)" itemValue="XOF" />
|
||||
<f:selectItem itemLabel="Euro (EUR)" itemValue="EUR" />
|
||||
<f:selectItem itemLabel="Dollar (USD)" itemValue="USD" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="formatDate" value="Format de date" />
|
||||
<p:selectOneMenu id="formatDate" value="#{configBean.config.formatDate}">
|
||||
<f:selectItem itemLabel="dd/MM/yyyy" itemValue="dd/MM/yyyy" />
|
||||
<f:selectItem itemLabel="MM/dd/yyyy" itemValue="MM/dd/yyyy" />
|
||||
<f:selectItem itemLabel="yyyy-MM-dd" itemValue="yyyy-MM-dd" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>Options d'Interface</h5>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="modeNuit" value="#{configBean.config.modeNuit}" />
|
||||
<p:outputLabel for="modeNuit" value=" Mode sombre par défaut" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="notificationsDesktop" value="#{configBean.config.notificationsDesktop}" />
|
||||
<p:outputLabel for="notificationsDesktop" value=" Notifications desktop" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="animationsUI" value="#{configBean.config.animationsUI}" />
|
||||
<p:outputLabel for="animationsUI" value=" Animations d'interface" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:tab>
|
||||
|
||||
<!-- Configuration Email -->
|
||||
<p:tab title="📧 Email">
|
||||
<h:form id="formEmail">
|
||||
<div class="ui-fluid">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Serveur SMTP</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="smtpHost" value="Serveur SMTP" />
|
||||
<p:inputText id="smtpHost" value="#{configBean.emailConfig.smtpHost}"
|
||||
placeholder="smtp.gmail.com" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="smtpPort" value="Port" />
|
||||
<p:inputNumber id="smtpPort" value="#{configBean.emailConfig.smtpPort}"
|
||||
symbol="" placeholder="587" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="smtpUsername" value="Nom d'utilisateur" />
|
||||
<p:inputText id="smtpUsername" value="#{configBean.emailConfig.smtpUsername}" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="smtpPassword" value="Mot de passe" />
|
||||
<p:password id="smtpPassword" value="#{configBean.emailConfig.smtpPassword}"
|
||||
feedback="false" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="smtpSSL" value="#{configBean.emailConfig.smtpSSL}" />
|
||||
<p:outputLabel for="smtpSSL" value=" Utiliser SSL/TLS" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Configuration Email</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="emailExpediteur" value="Email expéditeur" />
|
||||
<p:inputText id="emailExpediteur" value="#{configBean.emailConfig.emailExpediteur}"
|
||||
placeholder="noreply@unionflow.com" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="nomExpediteur" value="Nom expéditeur" />
|
||||
<p:inputText id="nomExpediteur" value="#{configBean.emailConfig.nomExpediteur}"
|
||||
placeholder="UnionFlow System" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="emailAdmin" value="Email administrateur" />
|
||||
<p:inputText id="emailAdmin" value="#{configBean.emailConfig.emailAdmin}" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="signatureEmail" value="Signature email" />
|
||||
<p:inputTextarea id="signatureEmail" value="#{configBean.emailConfig.signature}"
|
||||
rows="4" placeholder="Signature automatique..." />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5>Test de Configuration</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="emailTest" value="Email de test" />
|
||||
<p:inputText id="emailTest" value="#{configBean.emailTest}"
|
||||
placeholder="test@example.com" />
|
||||
</div>
|
||||
|
||||
<p:commandButton value="Envoyer email de test"
|
||||
icon="pi pi-send"
|
||||
styleClass="ui-button-outlined ui-button-info w-full"
|
||||
action="#{configBean.envoyerEmailTest}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:tab>
|
||||
|
||||
<!-- Sécurité -->
|
||||
<p:tab title="🔒 Sécurité">
|
||||
<h:form id="formSecurite">
|
||||
<div class="ui-fluid">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Politique de Mots de Passe</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="longueurMinMdp" value="Longueur minimale" />
|
||||
<p:inputNumber id="longueurMinMdp" value="#{configBean.securityConfig.longueurMinMdp}"
|
||||
symbol="" min="6" max="20" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="majusculesRequises" value="#{configBean.securityConfig.majusculesRequises}" />
|
||||
<p:outputLabel for="majusculesRequises" value=" Majuscules obligatoires" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="chiffresRequis" value="#{configBean.securityConfig.chiffresRequis}" />
|
||||
<p:outputLabel for="chiffresRequis" value=" Chiffres obligatoires" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="caracteresSpeciaux" value="#{configBean.securityConfig.caracteresSpeciaux}" />
|
||||
<p:outputLabel for="caracteresSpeciaux" value=" Caractères spéciaux obligatoires" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="expirationMdp" value="Expiration (jours)" />
|
||||
<p:inputNumber id="expirationMdp" value="#{configBean.securityConfig.expirationMdp}"
|
||||
symbol="" min="0" max="365" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Sessions et Connexions</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="dureeSession" value="Durée session (minutes)" />
|
||||
<p:inputNumber id="dureeSession" value="#{configBean.securityConfig.dureeSession}"
|
||||
symbol="" min="15" max="1440" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="tentativesMax" value="Tentatives connexion max" />
|
||||
<p:inputNumber id="tentativesMax" value="#{configBean.securityConfig.tentativesMax}"
|
||||
symbol="" min="3" max="10" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="blocageDuree" value="Durée blocage (minutes)" />
|
||||
<p:inputNumber id="blocageDuree" value="#{configBean.securityConfig.blocageDuree}"
|
||||
symbol="" min="5" max="1440" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="connexionsMultiples" value="#{configBean.securityConfig.connexionsMultiples}" />
|
||||
<p:outputLabel for="connexionsMultiples" value=" Autoriser connexions multiples" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="doubleAuthentification" value="#{configBean.securityConfig.doubleAuthentification}" />
|
||||
<p:outputLabel for="doubleAuthentification" value=" Double authentification (2FA)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>Surveillance et Audit</h5>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="logConnexions" value="#{configBean.securityConfig.logConnexions}" />
|
||||
<p:outputLabel for="logConnexions" value=" Journaliser les connexions" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="logActions" value="#{configBean.securityConfig.logActions}" />
|
||||
<p:outputLabel for="logActions" value=" Journaliser les actions" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="alertesSuspectes" value="#{configBean.securityConfig.alertesSuspectes}" />
|
||||
<p:outputLabel for="alertesSuspectes" value=" Alertes activités suspectes" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:tab>
|
||||
|
||||
<!-- Intégrations -->
|
||||
<p:tab title="🔗 Intégrations">
|
||||
<h:form id="formIntegrations">
|
||||
<div class="ui-fluid">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Wave Money API</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="waveActive" value="#{configBean.waveConfig.actif}" />
|
||||
<p:outputLabel for="waveActive" value=" Activer Wave Money" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="waveApiKey" value="Clé API" />
|
||||
<p:password id="waveApiKey" value="#{configBean.waveConfig.apiKey}"
|
||||
feedback="false" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="waveSecretKey" value="Clé secrète" />
|
||||
<p:password id="waveSecretKey" value="#{configBean.waveConfig.secretKey}"
|
||||
feedback="false" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="waveEnvironnement" value="Environnement" />
|
||||
<p:selectOneMenu id="waveEnvironnement" value="#{configBean.waveConfig.environnement}">
|
||||
<f:selectItem itemLabel="Test (Sandbox)" itemValue="TEST" />
|
||||
<f:selectItem itemLabel="Production" itemValue="PROD" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<p:commandButton value="Tester la connexion"
|
||||
icon="pi pi-link"
|
||||
styleClass="ui-button-outlined ui-button-info w-full"
|
||||
action="#{configBean.testerWave}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>SMS / WhatsApp</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="fournisseurSMS" value="Fournisseur SMS" />
|
||||
<p:selectOneMenu id="fournisseurSMS" value="#{configBean.smsConfig.fournisseur}">
|
||||
<f:selectItem itemLabel="Twilio" itemValue="TWILIO" />
|
||||
<f:selectItem itemLabel="Orange SMS" itemValue="ORANGE" />
|
||||
<f:selectItem itemLabel="Sonatel" itemValue="SONATEL" />
|
||||
<f:selectItem itemLabel="Custom API" itemValue="CUSTOM" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="smsApiKey" value="Clé API SMS" />
|
||||
<p:password id="smsApiKey" value="#{configBean.smsConfig.apiKey}"
|
||||
feedback="false" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="expediteurSMS" value="ID expéditeur" />
|
||||
<p:inputText id="expediteurSMS" value="#{configBean.smsConfig.expediteur}"
|
||||
placeholder="UnionFlow" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="whatsappActive" value="#{configBean.smsConfig.whatsappActif}" />
|
||||
<p:outputLabel for="whatsappActive" value=" Activer WhatsApp Business" />
|
||||
</div>
|
||||
|
||||
<p:commandButton value="Tester SMS"
|
||||
icon="pi pi-comment"
|
||||
styleClass="ui-button-outlined ui-button-success w-full"
|
||||
action="#{configBean.testerSMS}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>APIs Externes</h5>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-4">
|
||||
<h6>Géolocalisation</h6>
|
||||
<div class="field">
|
||||
<p:outputLabel for="googleMapsAPI" value="Google Maps API" />
|
||||
<p:password id="googleMapsAPI" value="#{configBean.apisConfig.googleMapsKey}"
|
||||
feedback="false" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-4">
|
||||
<h6>Stockage Cloud</h6>
|
||||
<div class="field">
|
||||
<p:outputLabel for="cloudProvider" value="Fournisseur" />
|
||||
<p:selectOneMenu id="cloudProvider" value="#{configBean.apisConfig.cloudProvider}">
|
||||
<f:selectItem itemLabel="Local" itemValue="LOCAL" />
|
||||
<f:selectItem itemLabel="AWS S3" itemValue="AWS" />
|
||||
<f:selectItem itemLabel="Google Cloud" itemValue="GCP" />
|
||||
<f:selectItem itemLabel="Azure" itemValue="AZURE" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-4">
|
||||
<h6>Analytics</h6>
|
||||
<div class="field">
|
||||
<p:outputLabel for="googleAnalytics" value="Google Analytics ID" />
|
||||
<p:inputText id="googleAnalytics" value="#{configBean.apisConfig.googleAnalyticsId}"
|
||||
placeholder="GA-XXXXXXXXX" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:tab>
|
||||
|
||||
<!-- Performance -->
|
||||
<p:tab title="⚡ Performance">
|
||||
<h:form id="formPerformance">
|
||||
<div class="ui-fluid">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Cache et Mémoire</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="cacheActive" value="#{configBean.perfConfig.cacheActif}" />
|
||||
<p:outputLabel for="cacheActive" value=" Activer le cache" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="dureeCacheDefault" value="Durée cache par défaut (minutes)" />
|
||||
<p:inputNumber id="dureeCacheDefault" value="#{configBean.perfConfig.dureeCacheDefault}"
|
||||
symbol="" min="1" max="1440" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="tailleCacheMax" value="Taille cache max (MB)" />
|
||||
<p:inputNumber id="tailleCacheMax" value="#{configBean.perfConfig.tailleCacheMax}"
|
||||
symbol="" min="10" max="1024" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="compressionActive" value="Compression" />
|
||||
<p:selectBooleanCheckbox id="compressionActive" value="#{configBean.perfConfig.compressionActive}" />
|
||||
<p:outputLabel for="compressionActive" value=" Activer compression GZIP" />
|
||||
</div>
|
||||
|
||||
<p:commandButton value="Vider le cache"
|
||||
icon="pi pi-trash"
|
||||
styleClass="ui-button-outlined ui-button-warning w-full"
|
||||
action="#{configBean.viderCache}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Base de Données</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="poolConnexionsMin" value="Pool connexions min" />
|
||||
<p:inputNumber id="poolConnexionsMin" value="#{configBean.perfConfig.poolConnexionsMin}"
|
||||
symbol="" min="1" max="50" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="poolConnexionsMax" value="Pool connexions max" />
|
||||
<p:inputNumber id="poolConnexionsMax" value="#{configBean.perfConfig.poolConnexionsMax}"
|
||||
symbol="" min="5" max="200" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="timeoutRequete" value="Timeout requête (secondes)" />
|
||||
<p:inputNumber id="timeoutRequete" value="#{configBean.perfConfig.timeoutRequete}"
|
||||
symbol="" min="5" max="300" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="logSlowQueries" value="#{configBean.perfConfig.logSlowQueries}" />
|
||||
<p:outputLabel for="logSlowQueries" value=" Journaliser requêtes lentes" />
|
||||
</div>
|
||||
|
||||
<p:commandButton value="Optimiser base"
|
||||
icon="pi pi-cog"
|
||||
styleClass="ui-button-outlined ui-button-info w-full"
|
||||
action="#{configBean.optimiserBase}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>Monitoring en Temps Réel</h5>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 surface-50 border-round">
|
||||
<div class="text-2xl font-bold text-blue-500 mb-2">#{configBean.cpuUsage}%</div>
|
||||
<div class="text-600">Utilisation CPU</div>
|
||||
<p:progressBar value="#{configBean.cpuUsage}" styleClass="mt-2 h-1rem" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 surface-50 border-round">
|
||||
<div class="text-2xl font-bold text-green-500 mb-2">#{configBean.memoryUsage}%</div>
|
||||
<div class="text-600">Mémoire Utilisée</div>
|
||||
<p:progressBar value="#{configBean.memoryUsage}" styleClass="mt-2 h-1rem" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 surface-50 border-round">
|
||||
<div class="text-2xl font-bold text-orange-500 mb-2">#{configBean.activeConnections}</div>
|
||||
<div class="text-600">Connexions Actives</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 surface-50 border-round">
|
||||
<div class="text-2xl font-bold text-purple-500 mb-2">#{configBean.responseTime}ms</div>
|
||||
<div class="text-600">Temps Réponse Moy.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:tab>
|
||||
|
||||
<!-- Maintenance -->
|
||||
<p:tab title="🔧 Maintenance">
|
||||
<h:form id="formMaintenance">
|
||||
<div class="ui-fluid">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Sauvegarde Automatique</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="sauvegardeAuto" value="#{configBean.maintenanceConfig.sauvegardeAuto}" />
|
||||
<p:outputLabel for="sauvegardeAuto" value=" Sauvegarde automatique" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="frequenceSauvegarde" value="Fréquence" />
|
||||
<p:selectOneMenu id="frequenceSauvegarde" value="#{configBean.maintenanceConfig.frequenceSauvegarde}">
|
||||
<f:selectItem itemLabel="Quotidienne" itemValue="DAILY" />
|
||||
<f:selectItem itemLabel="Hebdomadaire" itemValue="WEEKLY" />
|
||||
<f:selectItem itemLabel="Mensuelle" itemValue="MONTHLY" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="heureSauvegarde" value="Heure de sauvegarde" />
|
||||
<p:calendar id="heureSauvegarde" value="#{configBean.maintenanceConfig.heureSauvegarde}"
|
||||
pattern="HH:mm" timeOnly="true" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="retentionSauvegardes" value="Rétention (jours)" />
|
||||
<p:inputNumber id="retentionSauvegardes" value="#{configBean.maintenanceConfig.retentionSauvegardes}"
|
||||
symbol="" min="7" max="365" />
|
||||
</div>
|
||||
|
||||
<p:commandButton value="Sauvegarder maintenant"
|
||||
icon="pi pi-save"
|
||||
styleClass="ui-button-success w-full"
|
||||
action="#{configBean.sauvegarderMaintenant}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="card">
|
||||
<h5>Nettoyage et Maintenance</h5>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="nettoyageAuto" value="#{configBean.maintenanceConfig.nettoyageAuto}" />
|
||||
<p:outputLabel for="nettoyageAuto" value=" Nettoyage automatique des logs" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="retentionLogs" value="Rétention logs (jours)" />
|
||||
<p:inputNumber id="retentionLogs" value="#{configBean.maintenanceConfig.retentionLogs}"
|
||||
symbol="" min="7" max="90" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:selectBooleanCheckbox id="optimisationAuto" value="#{configBean.maintenanceConfig.optimisationAuto}" />
|
||||
<p:outputLabel for="optimisationAuto" value=" Optimisation automatique des tables" />
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 mt-3">
|
||||
<p:commandButton value="Nettoyer logs"
|
||||
icon="pi pi-trash"
|
||||
styleClass="ui-button-outlined ui-button-warning"
|
||||
action="#{configBean.nettoyerLogs}" />
|
||||
<p:commandButton value="Optimiser DB"
|
||||
icon="pi pi-cog"
|
||||
styleClass="ui-button-outlined ui-button-info"
|
||||
action="#{configBean.optimiserDB}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5>Mode Maintenance</h5>
|
||||
|
||||
<div class="surface-50 p-3 border-round mb-3">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-info-circle text-blue-500 mr-2"></i>
|
||||
<div class="text-600">
|
||||
Le mode maintenance bloque l'accès utilisateur pendant les opérations critiques.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<p:outputLabel for="messageMaintenance" value="Message de maintenance" />
|
||||
<p:inputTextarea id="messageMaintenance" value="#{configBean.maintenanceConfig.messageMaintenance}"
|
||||
rows="3" placeholder="Le système est temporairement indisponible..." />
|
||||
</div>
|
||||
|
||||
<p:commandButton value="#{configBean.maintenanceConfig.modeMaintenanceActif ? 'Désactiver' : 'Activer'} maintenance"
|
||||
icon="pi #{configBean.maintenanceConfig.modeMaintenanceActif ? 'pi-play' : 'pi-pause'}"
|
||||
styleClass="ui-button-#{configBean.maintenanceConfig.modeMaintenanceActif ? 'success' : 'danger'} w-full"
|
||||
action="#{configBean.toggleModeMaintenance}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:tab>
|
||||
</p:tabView>
|
||||
</div>
|
||||
|
||||
<!-- Actions globales -->
|
||||
<div class="card">
|
||||
<div class="flex justify-content-center gap-3">
|
||||
<p:commandButton value="💾 Sauvegarder toute la configuration"
|
||||
icon="pi pi-save"
|
||||
styleClass="ui-button-success"
|
||||
action="#{configBean.sauvegarderTout}" />
|
||||
<p:commandButton value="🔄 Redémarrer application"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="ui-button-outlined ui-button-warning"
|
||||
onclick="return confirm('Redémarrer l\\'application ? Tous les utilisateurs seront déconnectés.');"
|
||||
action="#{configBean.redemarrerApplication}" />
|
||||
<p:commandButton value="📋 Voir logs système"
|
||||
icon="pi pi-list"
|
||||
styleClass="ui-button-outlined ui-button-info"
|
||||
action="#{configBean.voirLogs}" />
|
||||
<p:commandButton value="📊 Rapport de santé"
|
||||
icon="pi pi-chart-line"
|
||||
styleClass="ui-button-outlined ui-button-secondary"
|
||||
action="#{configBean.genererRapportSante}" />
|
||||
</div>
|
||||
</div>
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
@@ -0,0 +1,727 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Configuration Système - UnionFlow</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<div class="ui-fluid">
|
||||
<!-- En-tête principal avec disposition Freya stricte -->
|
||||
<div class="card">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 lg:col-8">
|
||||
<h2 class="text-primary font-bold mb-2">
|
||||
<i class="pi pi-cog text-purple-500 mr-2"></i>
|
||||
Configuration Système
|
||||
</h2>
|
||||
<p class="text-600 mt-0">
|
||||
Paramètres globaux et administration de la plateforme UnionFlow •
|
||||
<span class="font-semibold">Version #{configurationBean.versionSysteme}</span> •
|
||||
<span class="font-semibold text-green-600">Environnement #{configurationBean.environnement}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field col-12 lg:col-4 text-right">
|
||||
<h:form id="formActionsEntete">
|
||||
<p:commandButton icon="pi pi-save"
|
||||
title="Sauvegarder configuration"
|
||||
styleClass="ui-button-success ui-button-sm mr-3"
|
||||
action="#{configurationBean.sauvegarderConfiguration}" />
|
||||
<p:commandButton icon="pi pi-download"
|
||||
title="Exporter"
|
||||
styleClass="ui-button-info ui-button-outlined ui-button-sm mr-3"
|
||||
action="#{configurationBean.exporterConfiguration}" />
|
||||
<p:commandButton icon="pi pi-refresh"
|
||||
title="Redémarrer services"
|
||||
styleClass="ui-button-warning ui-button-outlined ui-button-sm"
|
||||
onclick="return confirm('Redémarrer les services système ?');"
|
||||
action="#{configurationBean.redemarrerServices}" />
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPIs Système avec grille Freya stricte -->
|
||||
<div class="formgrid grid">
|
||||
<!-- KPI 1: Statut Système -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Statut Système" />
|
||||
<ui:param name="value" value="Opérationnel" />
|
||||
<ui:param name="icon" value="pi-check-circle" />
|
||||
<ui:param name="iconColor" value="green-600" />
|
||||
<ui:param name="statusIcon" value="pi-circle-fill" />
|
||||
<ui:param name="statusLabel" value="Uptime" />
|
||||
<ui:param name="statusValue" value="#{configurationBean.tempsActivite}" />
|
||||
<ui:param name="showProgress" value="false" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 2: Utilisateurs Connectés -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Utilisateurs Actifs" />
|
||||
<ui:param name="value" value="#{configurationBean.utilisateursConnectes}" />
|
||||
<ui:param name="icon" value="pi-users" />
|
||||
<ui:param name="iconColor" value="blue-600" />
|
||||
<ui:param name="statusIcon" value="pi-clock" />
|
||||
<ui:param name="statusLabel" value="Sessions" />
|
||||
<ui:param name="statusValue" value="#{configurationBean.sessionsActives} actives" />
|
||||
<ui:param name="showProgress" value="false" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 3: Performance Système -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Performance" />
|
||||
<ui:param name="value" value="CPU #{configurationBean.cpuUtilisation}%" />
|
||||
<ui:param name="icon" value="pi-chart-line" />
|
||||
<ui:param name="iconColor" value="orange-600" />
|
||||
<ui:param name="progressValue" value="#{configurationBean.cpuUtilisation}" />
|
||||
<ui:param name="noDataLabel" value="Mémoire: #{configurationBean.memoireUtilisee}%" />
|
||||
<ui:param name="showGrowth" value="false" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 4: Dernière Sauvegarde -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Dernière Sauvegarde" />
|
||||
<ui:param name="value" value="#{configurationBean.derniereSauvegarde}" />
|
||||
<ui:param name="icon" value="pi-save" />
|
||||
<ui:param name="iconColor" value="purple-600" />
|
||||
<ui:param name="statusIcon" value="pi-database" />
|
||||
<ui:param name="statusLabel" value="Auto" />
|
||||
<ui:param name="statusValue" value="#{configurationBean.frequenceSauvegarde}" />
|
||||
<ui:param name="showProgress" value="false" />
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Générale avec structure Freya -->
|
||||
<div class="card">
|
||||
<h5 class="mb-3">
|
||||
<i class="pi pi-cog text-purple-500 mr-2"></i>
|
||||
Configuration Générale
|
||||
</h5>
|
||||
<h:form id="formConfigGenerale">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="nomApplication" class="block text-900 font-medium mb-2">Nom de l'Application</label>
|
||||
<p:inputText id="nomApplication"
|
||||
value="#{configurationBean.nomApplication}"
|
||||
placeholder="UnionFlow"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="version" class="block text-900 font-medium mb-2">Version Système</label>
|
||||
<p:inputText id="version"
|
||||
value="#{configurationBean.versionSysteme}"
|
||||
readonly="true"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="environnement" class="block text-900 font-medium mb-2">Environnement</label>
|
||||
<p:selectOneMenu id="environnement"
|
||||
value="#{configurationBean.environnement}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Développement" itemValue="DEV" />
|
||||
<f:selectItem itemLabel="Test" itemValue="TEST" />
|
||||
<f:selectItem itemLabel="Production" itemValue="PROD" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="timezone" class="block text-900 font-medium mb-2">Fuseau Horaire</label>
|
||||
<p:selectOneMenu id="timezone"
|
||||
value="#{configurationBean.timezone}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="GMT (Greenwich)" itemValue="GMT" />
|
||||
<f:selectItem itemLabel="CET (Europe Central)" itemValue="CET" />
|
||||
<f:selectItem itemLabel="WAT (Afrique Ouest)" itemValue="WAT" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="langue" class="block text-900 font-medium mb-2">Langue par Défaut</label>
|
||||
<p:selectOneMenu id="langue"
|
||||
value="#{configurationBean.langueDefaut}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Français" itemValue="fr" />
|
||||
<f:selectItem itemLabel="English" itemValue="en" />
|
||||
<f:selectItem itemLabel="العربية" itemValue="ar" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="devise" class="block text-900 font-medium mb-2">Devise par Défaut</label>
|
||||
<p:selectOneMenu id="devise"
|
||||
value="#{configurationBean.deviseDefaut}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="FCFA (Franc CFA)" itemValue="XOF" />
|
||||
<f:selectItem itemLabel="EUR (Euro)" itemValue="EUR" />
|
||||
<f:selectItem itemLabel="USD (Dollar)" itemValue="USD" />
|
||||
<f:selectItem itemLabel="GHS (Cédi Ghana)" itemValue="GHS" />
|
||||
<f:selectItem itemLabel="NGN (Naira Nigeria)" itemValue="NGN" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="urlBase" class="block text-900 font-medium mb-2">URL Base Application</label>
|
||||
<p:inputText id="urlBase"
|
||||
value="#{configurationBean.urlBaseApplication}"
|
||||
placeholder="https://unionflow.app"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="organisationPrincipale" class="block text-900 font-medium mb-2">Organisation Principale</label>
|
||||
<p:inputText id="organisationPrincipale"
|
||||
value="#{configurationBean.organisationPrincipale}"
|
||||
placeholder="Lions Clubs Afrique de l'Ouest"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end mt-3">
|
||||
<p:commandButton value="Appliquer"
|
||||
icon="pi pi-check"
|
||||
styleClass="ui-button-success ui-button-sm"
|
||||
action="#{configurationBean.appliquerConfigGenerale}"
|
||||
update="@form" />
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Base de Données avec structure Freya -->
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 lg:col-6">
|
||||
<div class="card">
|
||||
<h5 class="mb-3">
|
||||
<i class="pi pi-database text-teal-500 mr-2"></i>
|
||||
Base de Données
|
||||
</h5>
|
||||
<h:form id="formConfigBDD">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="dbType" class="block text-900 font-medium mb-2">Type de Base</label>
|
||||
<p:selectOneMenu id="dbType"
|
||||
value="#{configurationBean.typeBDD}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="PostgreSQL" itemValue="postgresql" />
|
||||
<f:selectItem itemLabel="MySQL" itemValue="mysql" />
|
||||
<f:selectItem itemLabel="H2 Database" itemValue="h2" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="dbHost" class="block text-900 font-medium mb-2">Serveur</label>
|
||||
<p:inputText id="dbHost"
|
||||
value="#{configurationBean.serveurBDD}"
|
||||
placeholder="localhost"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="dbPort" class="block text-900 font-medium mb-2">Port</label>
|
||||
<p:inputNumber id="dbPort"
|
||||
value="#{configurationBean.portBDD}"
|
||||
minValue="1"
|
||||
maxValue="65535"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="dbName" class="block text-900 font-medium mb-2">Nom Base</label>
|
||||
<p:inputText id="dbName"
|
||||
value="#{configurationBean.nomBDD}"
|
||||
placeholder="unionflow"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="dbUser" class="block text-900 font-medium mb-2">Utilisateur BDD</label>
|
||||
<p:inputText id="dbUser"
|
||||
value="#{configurationBean.utilisateurBDD}"
|
||||
placeholder="unionflow_user"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="dbPassword" class="block text-900 font-medium mb-2">Mot de Passe BDD</label>
|
||||
<p:password id="dbPassword"
|
||||
value="#{configurationBean.motDePasseBDD}"
|
||||
placeholder="Mot de passe sécurisé"
|
||||
feedback="true"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<p:selectBooleanCheckbox id="dbSSL"
|
||||
value="#{configurationBean.sslActifBDD}" />
|
||||
<label for="dbSSL" class="ml-2">Connexion SSL/TLS Sécurisée</label>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-600 text-sm">Pool: </span>
|
||||
<p:inputNumber id="poolSize"
|
||||
value="#{configurationBean.taillePoolConnexions}"
|
||||
minValue="5"
|
||||
maxValue="100"
|
||||
placeholder="20"
|
||||
size="3" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end gap-2 mt-3">
|
||||
<p:commandButton value="Tester Connexion"
|
||||
icon="pi pi-check"
|
||||
styleClass="ui-button-outlined ui-button-success ui-button-sm"
|
||||
action="#{configurationBean.testerConnexionBDD}"
|
||||
update="@form" />
|
||||
<p:commandButton value="Appliquer"
|
||||
icon="pi pi-save"
|
||||
styleClass="ui-button-info ui-button-sm"
|
||||
action="#{configurationBean.appliquerConfigBDD}"
|
||||
update="@form" />
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 lg:col-6">
|
||||
<div class="card">
|
||||
<h5 class="mb-3">
|
||||
<i class="pi pi-envelope text-blue-500 mr-2"></i>
|
||||
Configuration Email
|
||||
</h5>
|
||||
<h:form id="formConfigEmail">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="smtpHost" class="block text-900 font-medium mb-2">Serveur SMTP</label>
|
||||
<p:inputText id="smtpHost"
|
||||
value="#{configurationBean.serveurSMTP}"
|
||||
placeholder="smtp.gmail.com"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="smtpPort" class="block text-900 font-medium mb-2">Port SMTP</label>
|
||||
<p:inputNumber id="smtpPort"
|
||||
value="#{configurationBean.portSMTP}"
|
||||
minValue="1"
|
||||
maxValue="65535"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12">
|
||||
<label for="emailFrom" class="block text-900 font-medium mb-2">Email Expéditeur</label>
|
||||
<p:inputText id="emailFrom"
|
||||
value="#{configurationBean.emailExpediteur}"
|
||||
placeholder="noreply@unionflow.app"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12">
|
||||
<label for="nomExpediteur" class="block text-900 font-medium mb-2">Nom Affiché Expéditeur</label>
|
||||
<p:inputText id="nomExpediteur"
|
||||
value="#{configurationBean.nomExpediteur}"
|
||||
placeholder="UnionFlow Notifications"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="smtpUser" class="block text-900 font-medium mb-2">Utilisateur SMTP</label>
|
||||
<p:inputText id="smtpUser"
|
||||
value="#{configurationBean.utilisateurSMTP}"
|
||||
placeholder="smtp_user@gmail.com"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="smtpPassword" class="block text-900 font-medium mb-2">Mot de Passe SMTP</label>
|
||||
<p:password id="smtpPassword"
|
||||
value="#{configurationBean.motDePasseSMTP}"
|
||||
placeholder="Token ou mot de passe"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div class="flex align-items-center gap-3">
|
||||
<div>
|
||||
<p:selectBooleanCheckbox id="smtpAuth"
|
||||
value="#{configurationBean.authentificationSMTP}" />
|
||||
<label for="smtpAuth" class="ml-2">Auth SMTP</label>
|
||||
</div>
|
||||
<div>
|
||||
<p:selectBooleanCheckbox id="smtpTLS"
|
||||
value="#{configurationBean.tlsActive}" />
|
||||
<label for="smtpTLS" class="ml-2">TLS/SSL</label>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-600 text-sm mr-2">Limite/h:</span>
|
||||
<p:inputNumber id="rateLimitEmail"
|
||||
value="#{configurationBean.limiteTauxEmail}"
|
||||
minValue="50"
|
||||
maxValue="2000"
|
||||
placeholder="500"
|
||||
size="5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end gap-2 mt-3">
|
||||
<p:commandButton value="Tester Email"
|
||||
icon="pi pi-send"
|
||||
styleClass="ui-button-outlined ui-button-info ui-button-sm"
|
||||
action="#{configurationBean.testerEmail}"
|
||||
update="@form" />
|
||||
<p:commandButton value="Appliquer"
|
||||
icon="pi pi-save"
|
||||
styleClass="ui-button-success ui-button-sm"
|
||||
action="#{configurationBean.appliquerConfigEmail}"
|
||||
update="@form" />
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Sécurité avec structure Freya -->
|
||||
<div class="card">
|
||||
<h5 class="mb-3">
|
||||
<i class="pi pi-shield text-red-500 mr-2"></i>
|
||||
Sécurité et Authentification
|
||||
</h5>
|
||||
<h:form id="formConfigSecurite">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="sessionTimeout" class="block text-900 font-medium mb-2">Timeout Session (min)</label>
|
||||
<p:inputNumber id="sessionTimeout"
|
||||
value="#{configurationBean.timeoutSession}"
|
||||
minValue="5"
|
||||
maxValue="1440"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="maxLoginAttempts" class="block text-900 font-medium mb-2">Tentatives Max</label>
|
||||
<p:inputNumber id="maxLoginAttempts"
|
||||
value="#{configurationBean.tentativesMaxConnexion}"
|
||||
minValue="3"
|
||||
maxValue="10"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="complexiteMotDePasse" class="block text-900 font-medium mb-2">Complexité Mot de Passe</label>
|
||||
<p:selectOneMenu id="complexiteMotDePasse"
|
||||
value="#{configurationBean.complexiteMotDePasse}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Basique (8 caractères)" itemValue="BASIC" />
|
||||
<f:selectItem itemLabel="Moyenne (8+ maj+min+chiffre)" itemValue="MEDIUM" />
|
||||
<f:selectItem itemLabel="Forte (12+ maj+min+chiffre+symbole)" itemValue="STRONG" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="dureeValiditeMDP" class="block text-900 font-medium mb-2">Validité MDP (jours)</label>
|
||||
<p:inputNumber id="dureeValiditeMDP"
|
||||
value="#{configurationBean.dureeValiditeMotDePasse}"
|
||||
minValue="30"
|
||||
maxValue="365"
|
||||
placeholder="90"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<label for="retentionLogs" class="block text-900 font-medium mb-2">Rétention Logs (jours)</label>
|
||||
<p:inputNumber id="retentionLogs"
|
||||
value="#{configurationBean.retentionLogs}"
|
||||
minValue="90"
|
||||
maxValue="1825"
|
||||
placeholder="365"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Options de sécurité -->
|
||||
<div class="surface-100 border-round-lg p-3 mt-3">
|
||||
<h6 class="mb-3">Options de Sécurité Avancées</h6>
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<div class="flex align-items-center">
|
||||
<p:selectBooleanCheckbox id="forcePasswordChange"
|
||||
value="#{configurationBean.forcerChangementMotDePasse}" />
|
||||
<label for="forcePasswordChange" class="ml-2 text-sm">Forcer changement MDP périodique</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<div class="flex align-items-center">
|
||||
<p:selectBooleanCheckbox id="enableTwoFactor"
|
||||
value="#{configurationBean.authentification2FA}" />
|
||||
<label for="enableTwoFactor" class="ml-2 text-sm">Authentification 2FA</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<div class="flex align-items-center">
|
||||
<p:selectBooleanCheckbox id="logSecurityEvents"
|
||||
value="#{configurationBean.journaliserEvenementsSecurite}" />
|
||||
<label for="logSecurityEvents" class="ml-2 text-sm">Journaliser événements sécurité</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<div class="flex align-items-center">
|
||||
<p:selectBooleanCheckbox id="chiffrementBDD"
|
||||
value="#{configurationBean.chiffrementBDD}" />
|
||||
<label for="chiffrementBDD" class="ml-2 text-sm">Chiffrement BDD</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end mt-3">
|
||||
<p:commandButton value="Appliquer Configuration Sécurité"
|
||||
icon="pi pi-shield"
|
||||
styleClass="ui-button-danger ui-button-sm"
|
||||
action="#{configurationBean.appliquerConfigSecurite}"
|
||||
update="@form" />
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
|
||||
<!-- Monitoring Système Avancé avec grille Freya -->
|
||||
<div class="formgrid grid">
|
||||
<!-- Performance en temps réel -->
|
||||
<div class="field col-12 lg:col-8">
|
||||
<div class="card">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="m-0">
|
||||
<i class="pi pi-chart-line text-cyan-500 mr-2"></i>
|
||||
Monitoring Performance
|
||||
</h5>
|
||||
<h:form id="formActualiserMonitoring">
|
||||
<p:commandButton icon="pi pi-refresh"
|
||||
title="Actualiser"
|
||||
styleClass="ui-button-outlined ui-button-secondary ui-button-sm"
|
||||
action="#{configurationBean.actualiserMonitoring}"
|
||||
update="@(.monitoring)" />
|
||||
</h:form>
|
||||
</div>
|
||||
|
||||
<div class="formgrid grid monitoring">
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<div class="surface-50 border-round-lg p-3 text-center">
|
||||
<div class="text-500 text-sm mb-2">CPU Utilisation</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2 #{configurationBean.cpuUtilisationStyle}">#{configurationBean.cpuUtilisation}%</div>
|
||||
<p:progressBar value="#{configurationBean.cpuUtilisation}"
|
||||
showValue="false"
|
||||
styleClass="surface-200"
|
||||
style="height: 0.5rem;" />
|
||||
<div class="text-500 text-xs mt-2">Seuil critique: 80%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<div class="surface-50 border-round-lg p-3 text-center">
|
||||
<div class="text-500 text-sm mb-2">Mémoire RAM</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2">#{configurationBean.memoireUtilisee}%</div>
|
||||
<p:progressBar value="#{configurationBean.memoireUtilisee}"
|
||||
showValue="false"
|
||||
styleClass="surface-200"
|
||||
style="height: 0.5rem;" />
|
||||
<div class="text-500 text-xs mt-2">#{configurationBean.memoireTotal} GB total</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<div class="surface-50 border-round-lg p-3 text-center">
|
||||
<div class="text-500 text-sm mb-2">Disque Disponible</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2 #{configurationBean.disqueDisponibleStyle}">#{configurationBean.disqueDisponible} GB</div>
|
||||
<div class="text-500 text-xs">Min requis: 10 GB</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<div class="surface-50 border-round-lg p-3 text-center">
|
||||
<div class="text-500 text-sm mb-2">Connexions BDD</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2 text-teal-500">#{configurationBean.connexionsBDDActives}</div>
|
||||
<div class="text-500 text-xs">Pool max: #{configurationBean.taillePoolConnexions}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<div class="surface-50 border-round-lg p-3 text-center">
|
||||
<div class="text-500 text-sm mb-2">Queue Emails</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2 #{configurationBean.queueEmailsStyle}">#{configurationBean.queueEmailsEnAttente}</div>
|
||||
<div class="text-500 text-xs">En attente traitement</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-4">
|
||||
<div class="surface-50 border-round-lg p-3 text-center">
|
||||
<div class="text-500 text-sm mb-2">Logs Erreurs (24h)</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2 #{configurationBean.logsErreursStyle}">#{configurationBean.logsErreurs24h}</div>
|
||||
<div class="text-500 text-xs">Dernières 24 heures</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alertes système automatiques -->
|
||||
<div class="surface-100 border-round-lg p-3 mt-3">
|
||||
<h6 class="mb-3">Alertes Système Automatiques</h6>
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-4">
|
||||
<div class="flex align-items-center p-2 #{configurationBean.cpuAlertStyle} border-round-lg">
|
||||
<i class="pi #{configurationBean.cpuAlertIcon} mr-2"></i>
|
||||
<span class="text-sm font-medium">CPU: #{configurationBean.cpuAlertText}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<div class="flex align-items-center p-2 #{configurationBean.memoireAlertStyle} border-round-lg">
|
||||
<i class="pi #{configurationBean.memoireAlertIcon} mr-2"></i>
|
||||
<span class="text-sm font-medium">Mémoire: #{configurationBean.memoireAlertText}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<div class="flex align-items-center p-2 #{configurationBean.disqueAlertStyle} border-round-lg">
|
||||
<i class="pi #{configurationBean.disqueAlertIcon} mr-2"></i>
|
||||
<span class="text-sm font-medium">Disque: #{configurationBean.disqueAlertText}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions et Services -->
|
||||
<div class="field col-12 lg:col-4">
|
||||
<div class="card">
|
||||
<h5 class="mb-3">
|
||||
<i class="pi pi-cog text-orange-500 mr-2"></i>
|
||||
Actions Système
|
||||
</h5>
|
||||
|
||||
<!-- Mode Maintenance -->
|
||||
<div class="surface-50 border-round-lg p-3 mb-3">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<div class="font-medium text-900">Mode Maintenance</div>
|
||||
<div class="text-500 text-xs">Bloque l'accès utilisateurs</div>
|
||||
</div>
|
||||
<h:form id="formModeMaintenance">
|
||||
<p:selectBooleanCheckbox id="modeMaintenance"
|
||||
value="#{configurationBean.modeMaintenance}">
|
||||
<p:ajax update="@form" />
|
||||
</p:selectBooleanCheckbox>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Sauvegarde -->
|
||||
<div class="surface-50 border-round-lg p-3 mb-3">
|
||||
<div class="font-medium text-900 mb-2">Sauvegarde Automatique</div>
|
||||
<h:form id="formSauvegarde">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12">
|
||||
<p:selectOneMenu value="#{configurationBean.frequenceSauvegarde}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Toutes les 4h" itemValue="4H" />
|
||||
<f:selectItem itemLabel="Quotidienne (2h00)" itemValue="DAILY" />
|
||||
<f:selectItem itemLabel="Hebdomadaire" itemValue="WEEKLY" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="field col-12">
|
||||
<div class="text-500 text-xs">Rétention: </div>
|
||||
<p:inputNumber value="#{configurationBean.retentionSauvegardes}"
|
||||
minValue="7" maxValue="365" size="3" suffix=" jours" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
|
||||
<!-- Actions rapides -->
|
||||
<h:form id="formActionsRapides">
|
||||
<div class="flex flex-column gap-2">
|
||||
<p:commandButton value="Forcer Sauvegarde"
|
||||
icon="pi pi-save"
|
||||
styleClass="ui-button-info ui-button-outlined ui-button-sm w-full"
|
||||
action="#{configurationBean.forcerSauvegarde}" />
|
||||
|
||||
<p:commandButton value="Nettoyer Cache"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="ui-button-secondary ui-button-outlined ui-button-sm w-full"
|
||||
action="#{configurationBean.nettoyerCache}" />
|
||||
|
||||
<p:commandButton value="Audit Système"
|
||||
icon="pi pi-shield"
|
||||
styleClass="ui-button-warning ui-button-outlined ui-button-sm w-full"
|
||||
action="#{configurationBean.auditSysteme}" />
|
||||
|
||||
<p:commandButton value="Redémarrer Services"
|
||||
icon="pi pi-power-off"
|
||||
styleClass="ui-button-danger ui-button-outlined ui-button-sm w-full"
|
||||
onclick="return confirm('Redémarrer les services ?');"
|
||||
action="#{configurationBean.redemarrerServices}" />
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Alertes avec structure Freya -->
|
||||
<div class="card">
|
||||
<h5 class="mb-3">
|
||||
<i class="pi pi-bell text-orange-500 mr-2"></i>
|
||||
Alertes et Notifications
|
||||
</h5>
|
||||
<h:form id="formConfigAlertes">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="emailAlertes" class="block text-900 font-medium mb-2">Email Alertes Système</label>
|
||||
<p:inputText id="emailAlertes"
|
||||
value="#{configurationBean.emailAlertes}"
|
||||
placeholder="admin@unionflow.app"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<div class="flex flex-column gap-2">
|
||||
<div class="flex align-items-center">
|
||||
<p:selectBooleanCheckbox id="alertesCPU"
|
||||
value="#{configurationBean.alertesCPU}" />
|
||||
<label for="alertesCPU" class="ml-2">Alertes CPU (>80%)</label>
|
||||
</div>
|
||||
<div class="flex align-items-center">
|
||||
<p:selectBooleanCheckbox id="alertesMemoire"
|
||||
value="#{configurationBean.alertesMemoire}" />
|
||||
<label for="alertesMemoire" class="ml-2">Alertes Mémoire (>85%)</label>
|
||||
</div>
|
||||
<div class="flex align-items-center">
|
||||
<p:selectBooleanCheckbox id="alertesDisque"
|
||||
value="#{configurationBean.alertesDisque}" />
|
||||
<label for="alertesDisque" class="ml-2">Alertes Disque (<10 GB)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end mt-3">
|
||||
<p:commandButton value="Sauvegarder Alertes"
|
||||
icon="pi pi-check"
|
||||
styleClass="ui-button-success ui-button-sm"
|
||||
action="#{configurationBean.sauvegarderAlertes}"
|
||||
update="@form" />
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
@@ -0,0 +1,375 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Dashboard Super-Administrateur Enhanced - UnionFlow</ui:define>
|
||||
|
||||
<ui:define name="head">
|
||||
<style>
|
||||
.metric-card {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.metric-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.revenue-breakdown {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.system-health {
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
border-radius: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.subscription-stats {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
border-radius: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.alert-critical { border-left: 4px solid #ef4444; }
|
||||
.alert-warning { border-left: 4px solid #f59e0b; }
|
||||
.alert-success { border-left: 4px solid #10b981; }
|
||||
.alert-info { border-left: 4px solid #3b82f6; }
|
||||
</style>
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<div class="grid">
|
||||
<!-- En-tête avec informations utilisateur -->
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<h3 class="mb-2">
|
||||
<i class="pi pi-crown text-yellow-500 mr-2"></i>
|
||||
Dashboard Super-Administrateur
|
||||
</h3>
|
||||
<p class="text-600 m-0">Vue globale de la plateforme UnionFlow - Stratégie Volume</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-900 font-medium">#{superAdminBean.nomComplet}</div>
|
||||
<small class="text-600">Dernière connexion: #{superAdminBean.derniereConnexion}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPIs Principaux - Ordre psychologique optimal -->
|
||||
<!-- 1. MEMBRES : Le plus important - Les personnes d'abord -->
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card metric-card bg-blue-100 border-left-3 border-blue-500">
|
||||
<div class="flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<div class="text-blue-900 font-bold text-3xl mb-1">#{superAdminBean.totalMembres}</div>
|
||||
<div class="text-blue-700 font-medium">Membres Actifs</div>
|
||||
<div class="flex align-items-center mt-2">
|
||||
<i class="pi pi-arrow-up text-green-500 mr-1"></i>
|
||||
<span class="text-green-500 font-bold text-sm">+12.5%</span>
|
||||
<span class="text-600 text-xs ml-2">ce mois</span>
|
||||
</div>
|
||||
<div class="text-600 text-xs mt-1">Moyenne: 146/organisation</div>
|
||||
</div>
|
||||
<div class="bg-blue-500 text-white border-round flex align-items-center justify-content-center"
|
||||
style="width: 3.5rem; height: 3.5rem;">
|
||||
<i class="pi pi-users text-2xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. ORGANISATIONS : Structure organisationnelle -->
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card metric-card bg-green-100 border-left-3 border-green-500">
|
||||
<div class="flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<div class="text-green-900 font-bold text-3xl mb-1">#{superAdminBean.totalEntites}</div>
|
||||
<div class="text-green-700 font-medium">Organisations</div>
|
||||
<div class="flex align-items-center mt-2">
|
||||
<i class="pi pi-arrow-up text-green-500 mr-1"></i>
|
||||
<span class="text-green-500 font-bold text-sm">+8</span>
|
||||
<span class="text-600 text-xs ml-2">nouvelles</span>
|
||||
</div>
|
||||
<div class="text-600 text-xs mt-1">#{superAdminBean.souscriptionsActives} souscriptions actives</div>
|
||||
</div>
|
||||
<div class="bg-green-500 text-white border-round flex align-items-center justify-content-center"
|
||||
style="width: 3.5rem; height: 3.5rem;">
|
||||
<i class="pi pi-sitemap text-2xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. REVENUS : Santé financière -->
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card metric-card bg-purple-100 border-left-3 border-purple-500">
|
||||
<div class="flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<div class="text-purple-900 font-bold text-2xl mb-1">#{superAdminBean.revenusGlobaux}</div>
|
||||
<div class="text-purple-700 font-medium">Revenus Mensuels</div>
|
||||
<div class="flex align-items-center mt-2">
|
||||
<i class="pi pi-arrow-up text-green-500 mr-1"></i>
|
||||
<span class="text-green-500 font-bold text-sm">+23%</span>
|
||||
<span class="text-600 text-xs ml-2">vs mois dernier</span>
|
||||
</div>
|
||||
<div class="text-600 text-xs mt-1">Taux conversion: #{superAdminBean.tauxConversionFormat}</div>
|
||||
</div>
|
||||
<div class="bg-purple-500 text-white border-round flex align-items-center justify-content-center"
|
||||
style="width: 3.5rem; height: 3.5rem;">
|
||||
<i class="pi pi-dollar text-2xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. SYSTÈME : Santé technique -->
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card metric-card bg-indigo-100 border-left-3 border-indigo-500">
|
||||
<div class="flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<div class="text-indigo-900 font-bold text-3xl mb-1">#{superAdminBean.disponibiliteSystemeFormat}</div>
|
||||
<div class="text-indigo-700 font-medium">Disponibilité</div>
|
||||
<div class="flex align-items-center mt-2">
|
||||
<div class="bg-green-500 border-round mr-1" style="width: 8px; height: 8px;"></div>
|
||||
<span class="text-green-600 font-bold text-sm">Opérationnel</span>
|
||||
</div>
|
||||
<div class="text-600 text-xs mt-1">#{superAdminBean.tempsReponsMoyen}ms temps réponse</div>
|
||||
</div>
|
||||
<div class="bg-indigo-500 text-white border-round flex align-items-center justify-content-center"
|
||||
style="width: 3.5rem; height: 3.5rem;">
|
||||
<i class="pi pi-server text-2xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel de Souscriptions -->
|
||||
<div class="col-12 lg:col-8">
|
||||
<div class="card subscription-stats p-4">
|
||||
<h5 class="text-white mb-4">
|
||||
<i class="pi pi-credit-card mr-2"></i>
|
||||
Analyse des Souscriptions par Forfait
|
||||
</h5>
|
||||
<div class="grid">
|
||||
<div class="col-6 md:col-3">
|
||||
<div class="text-center">
|
||||
<div class="text-white font-bold text-2xl mb-1">44</div>
|
||||
<div class="text-blue-100 text-sm mb-2">Starter</div>
|
||||
<div class="text-blue-200 text-xs">#{superAdminBean.revenusStarterFormat}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 md:col-3">
|
||||
<div class="text-center">
|
||||
<div class="text-white font-bold text-2xl mb-1">60</div>
|
||||
<div class="text-blue-100 text-sm mb-2">Standard</div>
|
||||
<div class="text-blue-200 text-xs">#{superAdminBean.revenusStandardFormat}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 md:col-3">
|
||||
<div class="text-center">
|
||||
<div class="text-white font-bold text-2xl mb-1">20</div>
|
||||
<div class="text-blue-100 text-sm mb-2">Premium</div>
|
||||
<div class="text-blue-200 text-xs">#{superAdminBean.revenusPremmiumFormat}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 md:col-3">
|
||||
<div class="text-center">
|
||||
<div class="text-white font-bold text-2xl mb-1">3</div>
|
||||
<div class="text-blue-100 text-sm mb-2">Cristal</div>
|
||||
<div class="text-blue-200 text-xs">#{superAdminBean.revenusCristalFormat}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alertes souscriptions -->
|
||||
<div class="mt-4 pt-3 border-top-1 border-blue-400">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-exclamation-triangle text-yellow-300 mr-2"></i>
|
||||
<span class="text-white">#{superAdminBean.souscriptionsExpirantSous30Jours} souscriptions expirent sous 30 jours</span>
|
||||
</div>
|
||||
<p:commandButton value="Gérer"
|
||||
styleClass="p-button-warning p-button-sm"
|
||||
action="/pages/super-admin/souscriptions"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Support Client -->
|
||||
<div class="col-12 lg:col-4">
|
||||
<div class="card system-health p-4">
|
||||
<h5 class="text-white mb-4">
|
||||
<i class="pi pi-headphones mr-2"></i>
|
||||
Support Client
|
||||
</h5>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-6">
|
||||
<div class="text-center">
|
||||
<div class="text-white font-bold text-3xl mb-1">#{superAdminBean.ticketsSupportOuverts}</div>
|
||||
<div class="text-pink-100 text-sm">Tickets ouverts</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="text-center">
|
||||
<div class="text-white font-bold text-3xl mb-1">#{superAdminBean.satisfactionClientFormat}</div>
|
||||
<div class="text-pink-100 text-sm">Satisfaction</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 pt-3 border-top-1 border-pink-400">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<span class="text-white text-sm">Temps de résolution moyen: 2.3h</span>
|
||||
<p:commandButton value="Dashboard Support"
|
||||
styleClass="p-button-outlined p-button-sm"
|
||||
style="color: white; border-color: white;"
|
||||
action="/pages/super-admin/support"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alertes Système Enrichies -->
|
||||
<div class="col-12 lg:col-6">
|
||||
<div class="card">
|
||||
<h5>Alertes Critiques <span class="bg-red-500 text-white border-round px-2 py-1 text-xs ml-2">#{superAdminBean.alertesCount}</span></h5>
|
||||
|
||||
<ui:repeat value="#{superAdminBean.alertesRecentes}" var="alerte" varStatus="status">
|
||||
<div class="flex align-items-center justify-content-between p-3 border-round mb-2 alert-#{alerte.couleur.contains('red') ? 'critical' : alerte.couleur.contains('orange') ? 'warning' : alerte.couleur.contains('green') ? 'success' : 'info'}"
|
||||
style="background: var(--surface-50);">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi #{alerte.icone} #{alerte.couleur} mr-3"></i>
|
||||
<div>
|
||||
<div class="text-900 font-medium">#{alerte.titre}</div>
|
||||
<small class="text-600">#{alerte.entite} - #{alerte.date}</small>
|
||||
</div>
|
||||
</div>
|
||||
<h:form id="formAlertes#{alerte.id}">
|
||||
<p:commandButton icon="pi pi-eye"
|
||||
styleClass="p-button-rounded p-button-text"
|
||||
action="#{superAdminBean.voirAlerte(alerte)}"
|
||||
title="Voir détails" />
|
||||
</h:form>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
|
||||
<div class="text-center mt-3">
|
||||
<h:form id="formVoirToutesAlertes">
|
||||
<p:commandButton value="Voir toutes les alertes"
|
||||
styleClass="p-button-outlined p-button-sm"
|
||||
action="#{superAdminBean.voirToutesAlertes}" />
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions Rapides Enrichies -->
|
||||
<div class="col-12 lg:col-6">
|
||||
<div class="card">
|
||||
<h5>Actions Rapides</h5>
|
||||
<h:form id="formActionsRapides">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<p:commandButton value="Nouvelle Entité"
|
||||
icon="pi pi-plus"
|
||||
styleClass="p-button-outlined p-button-success w-full mb-2"
|
||||
action="#{superAdminBean.creerEntite}" />
|
||||
</div>
|
||||
<div class="col-12 md:col-6">
|
||||
<p:commandButton value="Gestion Formulaires"
|
||||
icon="pi pi-credit-card"
|
||||
styleClass="p-button-outlined p-button-info w-full mb-2"
|
||||
action="/pages/super-admin/formulaires" />
|
||||
</div>
|
||||
<div class="col-12 md:col-6">
|
||||
<p:commandButton value="Rapport Financier"
|
||||
icon="pi pi-chart-bar"
|
||||
styleClass="p-button-outlined p-button-warning w-full mb-2"
|
||||
action="#{superAdminBean.genererRapport}" />
|
||||
</div>
|
||||
<div class="col-12 md:col-6">
|
||||
<p:commandButton value="Configuration"
|
||||
icon="pi pi-cog"
|
||||
styleClass="p-button-outlined p-button-secondary w-full mb-2"
|
||||
action="#{superAdminBean.configurer}" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Performance par Région (si pertinent) -->
|
||||
<div class="col-12 lg:col-8">
|
||||
<div class="card">
|
||||
<h5>Performance Régionale</h5>
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 surface-50 border-round">
|
||||
<div class="text-2xl font-bold text-blue-500 mb-1">45</div>
|
||||
<div class="text-600 mb-2">Dakar</div>
|
||||
<div class="text-green-600 text-sm">+12%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 surface-50 border-round">
|
||||
<div class="text-2xl font-bold text-green-500 mb-1">32</div>
|
||||
<div class="text-600 mb-2">Thiès</div>
|
||||
<div class="text-green-600 text-sm">+8%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 surface-50 border-round">
|
||||
<div class="text-2xl font-bold text-purple-500 mb-1">28</div>
|
||||
<div class="text-600 mb-2">Kaolack</div>
|
||||
<div class="text-green-600 text-sm">+15%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 surface-50 border-round">
|
||||
<div class="text-2xl font-bold text-orange-500 mb-1">22</div>
|
||||
<div class="text-600 mb-2">Autres</div>
|
||||
<div class="text-green-600 text-sm">+5%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Top Entités et Activité Récente (conservés du dashboard original) -->
|
||||
<div class="col-12 lg:col-4">
|
||||
<div class="card">
|
||||
<h5>Top Entités (Membres)</h5>
|
||||
<ui:repeat value="#{superAdminBean.topEntites}" var="entite" varStatus="status">
|
||||
<div class="flex align-items-center justify-content-between p-3 mb-2 border-round"
|
||||
style="background: var(--surface-50);">
|
||||
<div class="flex align-items-center">
|
||||
<div class="bg-primary text-white border-round text-center mr-3"
|
||||
style="width: 2rem; height: 2rem; line-height: 2rem;">
|
||||
#{status.index + 1}
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-900 font-medium">#{entite.nom}</div>
|
||||
<small class="text-600">#{entite.typeEntite}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-900 font-bold">#{entite.nombreMembres}</div>
|
||||
<small class="text-600">membres</small>
|
||||
</div>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
@@ -0,0 +1,470 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Dashboard Super-Administrateur - UnionFlow</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<div class="ui-fluid">
|
||||
<!-- En-tête principal avec disposition Freya stricte -->
|
||||
<div class="card">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 lg:col-8">
|
||||
<h2 class="text-primary font-bold mb-2">
|
||||
<i class="pi pi-crown text-yellow-500 mr-2"></i>
|
||||
Tableau de bord Super-Administrateur
|
||||
</h2>
|
||||
<p class="text-600 mt-0">
|
||||
Vue globale de la plateforme UnionFlow •
|
||||
<span class="font-semibold">#{superAdminBean.totalEntites} organisations</span> •
|
||||
<span class="font-semibold text-green-600">#{superAdminBean.totalMembres} membres actifs</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field col-12 lg:col-4 text-right">
|
||||
<div class="text-900 font-bold text-lg">#{superAdminBean.nomComplet}</div>
|
||||
<div class="text-500 text-sm">Dernière connexion: #{superAdminBean.derniereConnexion}</div>
|
||||
<h:form id="formActionsRapidesHeader" styleClass="mt-2">
|
||||
<p:commandButton icon="pi pi-plus"
|
||||
title="Nouvelle organisation"
|
||||
styleClass="ui-button-success ui-button-sm mr-3"
|
||||
action="#{superAdminBean.creerEntite}" />
|
||||
<p:commandButton icon="pi pi-chart-bar"
|
||||
title="Rapport global"
|
||||
styleClass="ui-button-info ui-button-outlined ui-button-sm mr-3"
|
||||
action="#{superAdminBean.genererRapport}" />
|
||||
<p:commandButton icon="pi pi-cog"
|
||||
title="Configuration"
|
||||
styleClass="ui-button-secondary ui-button-outlined ui-button-sm"
|
||||
action="#{superAdminBean.configurer}" />
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPIs Principaux avec grille Freya stricte et alignement parfait -->
|
||||
<div class="formgrid grid">
|
||||
<!-- KPI 1: Membres Actifs -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Membres Actifs" />
|
||||
<ui:param name="value" value="#{superAdminBean.totalMembres}" />
|
||||
<ui:param name="icon" value="pi-users" />
|
||||
<ui:param name="iconColor" value="blue-600" />
|
||||
<ui:param name="growthValue" value="#{superAdminBean.croissanceMembres}" />
|
||||
<ui:param name="growthLabel" value="ce mois" />
|
||||
<ui:param name="progressValue" value="#{superAdminBean.pourcentageMembres}" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 2: Organisations -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Organisations" />
|
||||
<ui:param name="value" value="#{superAdminBean.totalEntites}" />
|
||||
<ui:param name="icon" value="pi-sitemap" />
|
||||
<ui:param name="iconColor" value="green-600" />
|
||||
<ui:param name="growthValue" value="#{superAdminBean.nouvellesEntites}" />
|
||||
<ui:param name="growthLabel" value="nouvelles" />
|
||||
<ui:param name="growthType" value="number" />
|
||||
<ui:param name="noDataLabel" value="Aucune nouvelle entité ce mois" />
|
||||
<ui:param name="progressValue" value="#{superAdminBean.pourcentageOrganisations}" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 3: Revenus Globaux -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Revenus (FCFA)" />
|
||||
<ui:param name="value" value="#{superAdminBean.revenusGlobaux}" />
|
||||
<ui:param name="icon" value="pi-dollar" />
|
||||
<ui:param name="iconColor" value="purple-600" />
|
||||
<ui:param name="growthValue" value="#{superAdminBean.croissanceRevenus}" />
|
||||
<ui:param name="growthLabel" value="vs mois dernier" />
|
||||
<ui:param name="progressValue" value="#{superAdminBean.pourcentageRevenus}" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 4: Activité du Jour -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Activité du Jour" />
|
||||
<ui:param name="value" value="#{superAdminBean.activiteJournaliere}" />
|
||||
<ui:param name="icon" value="pi-chart-line" />
|
||||
<ui:param name="iconColor" value="orange-600" />
|
||||
<ui:param name="statusIcon" value="pi-check-circle" />
|
||||
<ui:param name="statusLabel" value="En ligne" />
|
||||
<ui:param name="statusValue" value="#{superAdminBean.utilisateursActifs} actifs" />
|
||||
<ui:param name="progressValue" value="#{superAdminBean.pourcentageActivite}" />
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<!-- Section Analytics et Actions avec disposition Freya stricte -->
|
||||
<div class="formgrid grid">
|
||||
<!-- Actions Rapides -->
|
||||
<div class="field col-12 lg:col-6">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="p-4">
|
||||
<h5 class="text-900 font-bold mb-4">
|
||||
<i class="pi pi-bolt text-orange-500 mr-2"></i>
|
||||
Actions Rapides
|
||||
</h5>
|
||||
<h:form id="formActionsRapides">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:commandButton value="Nouvelle Entité"
|
||||
icon="pi pi-plus"
|
||||
styleClass="ui-button-success ui-button-outlined ui-button-sm w-full"
|
||||
action="#{superAdminBean.creerEntite}" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:commandButton value="Gestion Entités"
|
||||
icon="pi pi-building"
|
||||
styleClass="ui-button-info ui-button-outlined ui-button-sm w-full"
|
||||
action="#{superAdminBean.gererEntites}" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:commandButton value="Rapport Global"
|
||||
icon="pi pi-chart-bar"
|
||||
styleClass="ui-button-warning ui-button-outlined ui-button-sm w-full"
|
||||
action="#{superAdminBean.genererRapport}" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:commandButton value="Configuration"
|
||||
icon="pi pi-cog"
|
||||
styleClass="ui-button-secondary ui-button-outlined ui-button-sm w-full"
|
||||
action="#{superAdminBean.configurer}" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:commandButton value="Audit Système"
|
||||
icon="pi pi-shield"
|
||||
styleClass="ui-button-danger ui-button-outlined ui-button-sm w-full"
|
||||
action="#{superAdminBean.auditSysteme}" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:commandButton value="Backup"
|
||||
icon="pi pi-save"
|
||||
styleClass="ui-button-primary ui-button-outlined ui-button-sm w-full"
|
||||
action="#{superAdminBean.backup}" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alertes Système -->
|
||||
<div class="field col-12 lg:col-6">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="p-4">
|
||||
<div class="flex align-items-center justify-content-between mb-4">
|
||||
<h5 class="text-900 font-bold m-0">
|
||||
<i class="pi pi-exclamation-triangle text-orange-500 mr-2"></i>
|
||||
Alertes Système
|
||||
</h5>
|
||||
<p:tag value="#{superAdminBean.alertesCount} alertes"
|
||||
severity="warning" styleClass="text-xs" />
|
||||
</div>
|
||||
|
||||
<div class="surface-100 border-round-lg p-3 mb-3">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-info-circle text-blue-500 mr-2"></i>
|
||||
<span class="text-600 text-sm">#{superAdminBean.alertesCount} alertes nécessitent votre attention</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ui:repeat value="#{superAdminBean.alertesRecentes}" var="alerte">
|
||||
<div class="surface-100 border-round-lg p-3 mb-3 hover:surface-200 transition-colors transition-duration-150">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi #{alerte.icone} #{alerte.couleur} mr-3 text-lg"></i>
|
||||
<div>
|
||||
<div class="text-900 font-medium">#{alerte.titre}</div>
|
||||
<div class="text-500 text-xs">#{alerte.entite} • #{alerte.date}</div>
|
||||
</div>
|
||||
</div>
|
||||
<h:form id="formAlerte#{alerte.id}">
|
||||
<p:commandButton icon="pi pi-eye"
|
||||
styleClass="ui-button-rounded ui-button-text ui-button-info ui-button-sm"
|
||||
action="#{superAdminBean.voirAlerte(alerte)}"
|
||||
title="Voir détails" />
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
|
||||
<div class="text-center mt-3">
|
||||
<h:form id="formVoirToutesAlertes">
|
||||
<p:commandButton value="Voir toutes les alertes"
|
||||
icon="pi pi-arrow-right"
|
||||
styleClass="ui-button-link ui-button-sm"
|
||||
action="#{superAdminBean.voirToutesAlertes}" />
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section Évolution et Top Entités avec Freya stricte -->
|
||||
<div class="formgrid grid">
|
||||
<!-- Évolution des Entités -->
|
||||
<div class="field col-12 lg:col-8">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="p-4">
|
||||
<div class="flex align-items-center justify-content-between mb-4">
|
||||
<h5 class="text-900 font-bold m-0">
|
||||
<i class="pi pi-chart-bar text-blue-500 mr-2"></i>
|
||||
Évolution des Entités
|
||||
</h5>
|
||||
<p:selectOneMenu value="#{superAdminBean.periodeEvolution}" styleClass="w-8rem">
|
||||
<f:selectItem itemLabel="6 mois" itemValue="6M" />
|
||||
<f:selectItem itemLabel="12 mois" itemValue="12M" />
|
||||
<f:selectItem itemLabel="24 mois" itemValue="24M" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="surface-100 border-round-lg p-4">
|
||||
<div class="flex align-items-end justify-content-around" style="height: 150px;">
|
||||
<ui:repeat value="#{superAdminBean.evolutionEntites}" var="mois">
|
||||
<div class="flex flex-column align-items-center" style="width: 100%;">
|
||||
<div class="text-500 text-xs mb-1">#{mois.valeur}</div>
|
||||
<div class="bg-primary border-round"
|
||||
style="width: 40px; height: #{mois.hauteur}px; min-height: 20px;"></div>
|
||||
<div class="text-500 text-xs mt-2">#{mois.periode}</div>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between mt-3 pt-3 border-top-1 surface-border">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-arrow-up text-green-500 mr-2"></i>
|
||||
<span class="text-green-600 font-semibold">+#{superAdminBean.croissanceEntites}%</span>
|
||||
<span class="text-500 text-sm ml-2">ce mois</span>
|
||||
</div>
|
||||
<div class="text-600 text-sm">
|
||||
Total: <span class="font-semibold">#{superAdminBean.totalEntites}</span> entités
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Top Entités -->
|
||||
<div class="field col-12 lg:col-4">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="p-4">
|
||||
<h5 class="text-900 font-bold mb-4">
|
||||
<i class="pi pi-trophy text-yellow-500 mr-2"></i>
|
||||
Top 5 Entités
|
||||
</h5>
|
||||
|
||||
<ui:repeat value="#{superAdminBean.topEntites}" var="entite" varStatus="status">
|
||||
<div class="surface-100 border-round-lg p-3 mb-3 hover:surface-200 transition-colors transition-duration-150">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div class="flex align-items-center">
|
||||
<div class="flex align-items-center justify-content-center surface-200 border-circle mr-3"
|
||||
style="width: 2rem; height: 2rem;">
|
||||
<span class="text-primary font-bold">#{status.index + 1}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-900 font-medium">#{entite.nom}</div>
|
||||
<div class="text-500 text-xs">#{entite.typeEntite}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-900 font-bold">#{entite.nombreMembres}</div>
|
||||
<div class="text-500 text-xs">membres</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section Répartition et Activité avec Freya stricte -->
|
||||
<div class="formgrid grid">
|
||||
<!-- Répartition par Type -->
|
||||
<div class="field col-12 lg:col-6">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="p-4">
|
||||
<h5 class="text-900 font-bold mb-4">
|
||||
<i class="pi pi-chart-pie text-purple-500 mr-2"></i>
|
||||
Répartition par Type
|
||||
</h5>
|
||||
|
||||
<ui:repeat value="#{superAdminBean.repartitionTypes}" var="type">
|
||||
<div class="surface-100 border-round-lg p-3 mb-3 hover:surface-200 transition-colors transition-duration-150">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div class="flex align-items-center">
|
||||
<div class="flex align-items-center justify-content-center #{type.couleurBg} border-round-lg mr-3"
|
||||
style="width: 2.5rem; height: 2.5rem;">
|
||||
<i class="pi #{type.icone} #{type.couleurTexte}"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-900 font-medium">#{type.nom}</div>
|
||||
<div class="text-500 text-xs">#{type.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-900 font-bold text-lg">#{type.nombre}</div>
|
||||
<p:tag value="#{type.pourcentage}%" severity="info" styleClass="text-xs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
|
||||
<!-- Barre de progression globale -->
|
||||
<div class="surface-100 border-round-lg p-3 mt-3">
|
||||
<div class="flex align-items-center justify-content-between mb-2">
|
||||
<span class="text-600 font-medium text-sm">Répartition globale</span>
|
||||
<span class="text-900 font-semibold">#{superAdminBean.totalEntites} entités</span>
|
||||
</div>
|
||||
<div class="flex border-round overflow-hidden" style="height: 8px;">
|
||||
<ui:repeat value="#{superAdminBean.repartitionTypes}" var="type">
|
||||
<div class="#{type.couleurBg}"
|
||||
style="width: #{type.pourcentage}%; height: 100%;"></div>
|
||||
</ui:repeat>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Activité Récente (Timeline) -->
|
||||
<div class="field col-12 lg:col-6">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="p-4">
|
||||
<h5 class="text-900 font-bold mb-4">
|
||||
<i class="pi pi-history text-teal-500 mr-2"></i>
|
||||
Activité Récente
|
||||
</h5>
|
||||
|
||||
<div style="max-height: 400px; overflow-y: auto;">
|
||||
<ui:repeat value="#{superAdminBean.activitesRecentes}" var="activite" varStatus="status">
|
||||
<div class="flex mb-3">
|
||||
<!-- Timeline -->
|
||||
<div class="flex flex-column align-items-center mr-3" style="min-width: 40px;">
|
||||
<div class="flex align-items-center justify-content-center surface-200 border-circle"
|
||||
style="width: 2rem; height: 2rem;">
|
||||
<i class="pi #{activite.icone} text-primary text-sm"></i>
|
||||
</div>
|
||||
<div class="surface-300" style="width: 2px; flex: 1; margin-top: 0.5rem;"
|
||||
rendered="#{!status.last}"></div>
|
||||
</div>
|
||||
|
||||
<!-- Contenu -->
|
||||
<div class="flex-1">
|
||||
<div class="surface-100 border-round-lg p-3">
|
||||
<div class="flex align-items-center justify-content-between mb-2">
|
||||
<span class="text-900 font-medium text-sm">#{activite.description}</span>
|
||||
<span class="text-500 text-xs">#{activite.date}</span>
|
||||
</div>
|
||||
<div class="text-600 text-xs mb-1">#{activite.entite}</div>
|
||||
<div class="text-700 text-xs" rendered="#{activite.details != null}">
|
||||
#{activite.details}
|
||||
</div>
|
||||
<div class="flex align-items-center mt-2" rendered="#{activite.utilisateur != null}">
|
||||
<div class="surface-300 border-circle mr-2" style="width: 1.5rem; height: 1.5rem;"></div>
|
||||
<span class="text-500 text-xs">Par #{activite.utilisateur}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-3 pt-3 border-top-1 surface-border">
|
||||
<h:form id="formVoirTouteActivite">
|
||||
<p:commandButton value="Voir toute l'activité"
|
||||
icon="pi pi-arrow-right"
|
||||
styleClass="ui-button-link ui-button-sm"
|
||||
action="#{superAdminBean.voirTouteActivite}" />
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Performance Financière Globale avec Freya stricte -->
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="p-4">
|
||||
<h5 class="text-900 font-bold mb-4">
|
||||
<i class="pi pi-dollar text-green-500 mr-2"></i>
|
||||
Performance Financière Globale
|
||||
</h5>
|
||||
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<div class="surface-100 border-round-lg p-4 text-center hover:surface-200 transition-colors transition-duration-150">
|
||||
<div class="text-500 text-sm mb-2">Revenus Ce Mois</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2">#{superAdminBean.revenus.mensuel}</div>
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<i class="pi pi-arrow-up text-green-500 text-xs mr-2"></i>
|
||||
<span class="text-green-600 text-sm">+#{superAdminBean.revenus.croissanceMensuelle}%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<div class="surface-100 border-round-lg p-4 text-center hover:surface-200 transition-colors transition-duration-150">
|
||||
<div class="text-500 text-sm mb-2">Revenus Annuels</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2">#{superAdminBean.revenus.annuel}</div>
|
||||
<div class="text-600 text-xs">
|
||||
Objectif: #{superAdminBean.revenus.objectifAnnuel}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<div class="surface-100 border-round-lg p-4 text-center hover:surface-200 transition-colors transition-duration-150">
|
||||
<div class="text-500 text-sm mb-2">Croissance Annuelle</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2">#{superAdminBean.revenus.croissance}%</div>
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<i class="pi pi-trending-up text-orange-500 text-xs mr-2"></i>
|
||||
<span class="text-orange-600 text-sm">Tendance positive</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<div class="surface-100 border-round-lg p-4 text-center hover:surface-200 transition-colors transition-duration-150">
|
||||
<div class="text-500 text-sm mb-2">Revenu Moyen/Entité</div>
|
||||
<div class="text-900 font-bold text-2xl mb-2">#{superAdminBean.revenus.moyenne}</div>
|
||||
<div class="text-600 text-xs">
|
||||
Sur #{superAdminBean.totalEntites} entités
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Graphique de revenus -->
|
||||
<div class="surface-100 border-round-lg p-4 mt-3">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<span class="text-600 font-medium">Évolution des revenus (6 derniers mois)</span>
|
||||
<h:form id="formExportFinancier">
|
||||
<p:commandButton icon="pi pi-download"
|
||||
title="Exporter"
|
||||
styleClass="ui-button-secondary ui-button-outlined ui-button-sm"
|
||||
action="#{superAdminBean.exporterRapportFinancier}" />
|
||||
</h:form>
|
||||
</div>
|
||||
<div class="flex align-items-end justify-content-around" style="height: 120px;">
|
||||
<ui:repeat value="#{superAdminBean.revenus.evolution}" var="mois">
|
||||
<div class="flex flex-column align-items-center" style="width: 100%;">
|
||||
<div class="text-500 text-xs mb-1">#{mois.valeur}</div>
|
||||
<div class="bg-green-500 border-round"
|
||||
style="width: 30px; height: #{mois.hauteur}px; min-height: 20px;"></div>
|
||||
<div class="text-500 text-xs mt-2">#{mois.nom}</div>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
</div>
|
||||
<div class="text-500 text-xs text-right mt-2">
|
||||
<i class="pi pi-calendar mr-1"></i>
|
||||
Dernière mise à jour: #{superAdminBean.revenus.derniereMAJ}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
@@ -0,0 +1,641 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Gestion des Entités Enhanced - UnionFlow</ui:define>
|
||||
|
||||
<ui:define name="head">
|
||||
<style>
|
||||
.subscription-card {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.subscription-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.quota-progress {
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.quota-danger { background-color: #ef4444; }
|
||||
.quota-warning { background-color: #f59e0b; }
|
||||
.quota-success { background-color: #10b981; }
|
||||
|
||||
.expiration-alert { border-left: 4px solid #ef4444; }
|
||||
.quota-alert { border-left: 4px solid #f59e0b; }
|
||||
|
||||
.forfait-starter { background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); }
|
||||
.forfait-standard { background: linear-gradient(135deg, #10b981 0%, #047857 100%); }
|
||||
.forfait-premium { background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); }
|
||||
.forfait-cristal { background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); }
|
||||
</style>
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<!-- En-tête avec actions -->>
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<h3 class="mb-2">
|
||||
<i class="pi pi-building text-blue-500 mr-2"></i>
|
||||
Gestion des Entités - Stratégie Volume
|
||||
</h3>
|
||||
<p class="text-600 m-0">Administration complète avec suivi des souscriptions et quotas</p>
|
||||
</div>
|
||||
<h:form id="formActionsEntete">
|
||||
<div class="flex gap-2">
|
||||
<p:commandButton value="Nouvelle entité"
|
||||
icon="pi pi-plus"
|
||||
styleClass="p-button-success"
|
||||
onclick="PF('dlgNouvelleEntite').show();" />
|
||||
<p:commandButton value="Gestion Quotas"
|
||||
icon="pi pi-users"
|
||||
styleClass="p-button-outlined p-button-warning"
|
||||
action="#{entitesGestionBean.gererQuotas}" />
|
||||
<p:commandButton value="Relances"
|
||||
icon="pi pi-send"
|
||||
styleClass="p-button-outlined p-button-info"
|
||||
action="#{entitesGestionBean.envoyerRelancesSouscriptions}" />
|
||||
<p:commandButton value="Exporter"
|
||||
icon="pi pi-download"
|
||||
styleClass="p-button-outlined p-button-secondary"
|
||||
action="#{entitesGestionBean.exporterEntites}" />
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistiques enrichies avec souscriptions -->>
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card subscription-card bg-blue-100 border-left-3 border-blue-500">
|
||||
<div class="flex justify-content-between">
|
||||
<div>
|
||||
<div class="text-blue-900 font-bold text-2xl">#{entitesGestionBean.statistiques.totalEntites}</div>
|
||||
<div class="text-blue-700 mb-2">Total Entités</div>
|
||||
<div class="text-blue-600 text-sm">
|
||||
<i class="pi pi-check-circle mr-1"></i>
|
||||
#{entitesGestionBean.statistiques.entitesActives} actives
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-blue-500 text-white border-round text-center"
|
||||
style="width: 3rem; height: 3rem; line-height: 3rem;">
|
||||
<i class="pi pi-building text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card subscription-card bg-green-100 border-left-3 border-green-500">
|
||||
<div class="flex justify-content-between">
|
||||
<div>
|
||||
<div class="text-green-900 font-bold text-2xl">#{entitesGestionBean.statistiques.totalMembres}</div>
|
||||
<div class="text-green-700 mb-2">Total Membres</div>
|
||||
<div class="text-green-600 text-sm">
|
||||
<i class="pi pi-trending-up mr-1"></i>
|
||||
Moyenne: 146/entité
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-green-500 text-white border-round text-center"
|
||||
style="width: 3rem; height: 3rem; line-height: 3rem;">
|
||||
<i class="pi pi-users text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card subscription-card bg-orange-100 border-left-3 border-orange-500">
|
||||
<div class="flex justify-content-between">
|
||||
<div>
|
||||
<div class="text-orange-900 font-bold text-2xl">#{entitesGestionBean.statistiques.souscriptionsExpirantes}</div>
|
||||
<div class="text-orange-700 mb-2">Expirations Proches</div>
|
||||
<div class="text-orange-600 text-sm">
|
||||
<i class="pi pi-clock mr-1"></i>
|
||||
Sous 30 jours
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-orange-500 text-white border-round text-center"
|
||||
style="width: 3rem; height: 3rem; line-height: 3rem;">
|
||||
<i class="pi pi-exclamation-triangle text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="card subscription-card bg-purple-100 border-left-3 border-purple-500">
|
||||
<div class="flex justify-content-between">
|
||||
<div>
|
||||
<div class="text-purple-900 font-bold text-2xl">#{entitesGestionBean.statistiques.entitesQuotaAtteint}</div>
|
||||
<div class="text-purple-700 mb-2">Quotas Atteints</div>
|
||||
<div class="text-purple-600 text-sm">
|
||||
<i class="pi pi-info-circle mr-1"></i>
|
||||
Nécessitent upgrade
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-purple-500 text-white border-round text-center"
|
||||
style="width: 3rem; height: 3rem; line-height: 3rem;">
|
||||
<i class="pi pi-chart-pie text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Analyse des forfaits -->>
|
||||
<div class="grid">
|
||||
<div class="col-12 lg:col-8">
|
||||
<div class="card">
|
||||
<h5>Répartition par Forfait - Nouvelle Grille Tarifaire</h5>
|
||||
<div class="grid">
|
||||
<div class="col-6 md:col-3">
|
||||
<div class="forfait-starter text-white p-3 border-round text-center">
|
||||
<div class="font-bold text-2xl mb-1">44</div>
|
||||
<div class="text-blue-100 text-sm mb-2">Starter</div>
|
||||
<div class="text-blue-200 text-xs mb-1">2K FCFA/mois</div>
|
||||
<div class="text-blue-200 text-xs">100 membres max</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 md:col-3">
|
||||
<div class="forfait-standard text-white p-3 border-round text-center">
|
||||
<div class="font-bold text-2xl mb-1">60</div>
|
||||
<div class="text-green-100 text-sm mb-2">Standard</div>
|
||||
<div class="text-green-200 text-xs mb-1">3K FCFA/mois</div>
|
||||
<div class="text-green-200 text-xs">200 membres max</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 md:col-3">
|
||||
<div class="forfait-premium text-white p-3 border-round text-center">
|
||||
<div class="font-bold text-2xl mb-1">20</div>
|
||||
<div class="text-orange-100 text-sm mb-2">Premium</div>
|
||||
<div class="text-orange-200 text-xs mb-1">4K FCFA/mois</div>
|
||||
<div class="text-orange-200 text-xs">500 membres max</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 md:col-3">
|
||||
<div class="forfait-cristal text-white p-3 border-round text-center">
|
||||
<div class="font-bold text-2xl mb-1">3</div>
|
||||
<div class="text-purple-100 text-sm mb-2">Cristal</div>
|
||||
<div class="text-purple-200 text-xs mb-1">5K FCFA/mois</div>
|
||||
<div class="text-purple-200 text-xs">2000 membres max</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 lg:col-4">
|
||||
<div class="card">
|
||||
<h5>Performance Commerciale</h5>
|
||||
<div class="grid">
|
||||
<div class="col-6">
|
||||
<div class="text-center p-3 surface-100 border-round">
|
||||
<div class="text-2xl font-bold text-green-500 mb-1">#{entitesGestionBean.statistiques.revenus}</div>
|
||||
<div class="text-600 text-sm">Revenus Mensuels</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="text-center p-3 surface-100 border-round">
|
||||
<div class="text-2xl font-bold text-blue-500 mb-1">#{entitesGestionBean.statistiques.tauxRenouvellementFormat}</div>
|
||||
<div class="text-600 text-sm">Taux Renouvellement</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 p-3 surface-50 border-round">
|
||||
<div class="text-900 font-medium mb-2">Forfait le plus populaire</div>
|
||||
<div class="flex align-items-center">
|
||||
<p:tag value="#{entitesGestionBean.statistiques.formulairePopulaire}" severity="success" />
|
||||
<span class="text-600 text-sm ml-2">60 souscriptions</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filtres enrichis -->>
|
||||
<div class="card">
|
||||
<h5>Filtres et Recherche Avancée</h5>
|
||||
<h:form id="formFiltres">
|
||||
<div class="ui-fluid">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="field">
|
||||
<p:outputLabel for="searchNom" value="Nom de l'entité" />
|
||||
<p:inputText id="searchNom" value="#{entitesGestionBean.filtres.nom}"
|
||||
placeholder="Rechercher par nom...">
|
||||
<p:ajax event="keyup" update="dtEntites @(.stats-summary)" />
|
||||
</p:inputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-2">
|
||||
<div class="field">
|
||||
<p:outputLabel for="filterType" value="Type" />
|
||||
<p:selectOneMenu id="filterType" value="#{entitesGestionBean.filtres.type}">
|
||||
<f:selectItem itemLabel="Tous" itemValue="" />
|
||||
<f:selectItem itemLabel="Association" itemValue="ASSOCIATION" />
|
||||
<f:selectItem itemLabel="Club" itemValue="CLUB" />
|
||||
<f:selectItem itemLabel="Groupe" itemValue="GROUPE" />
|
||||
<f:selectItem itemLabel="Branche" itemValue="BRANCHE" />
|
||||
<p:ajax update="dtEntites @(.stats-summary)" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-2">
|
||||
<div class="field">
|
||||
<p:outputLabel for="filterStatut" value="Statut" />
|
||||
<p:selectOneMenu id="filterStatut" value="#{entitesGestionBean.filtres.statut}">
|
||||
<f:selectItem itemLabel="Tous" itemValue="" />
|
||||
<f:selectItem itemLabel="Active" itemValue="ACTIVE" />
|
||||
<f:selectItem itemLabel="Inactive" itemValue="INACTIVE" />
|
||||
<f:selectItem itemLabel="Suspendue" itemValue="SUSPENDUE" />
|
||||
<p:ajax update="dtEntites @(.stats-summary)" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-2">
|
||||
<div class="field">
|
||||
<p:outputLabel for="filterRegion" value="Région" />
|
||||
<p:selectOneMenu id="filterRegion" value="#{entitesGestionBean.filtres.region}">
|
||||
<f:selectItem itemLabel="Toutes" itemValue="" />
|
||||
<f:selectItem itemLabel="Région 1" itemValue="REGION_1" />
|
||||
<f:selectItem itemLabel="Région 2" itemValue="REGION_2" />
|
||||
<f:selectItem itemLabel="Région 3" itemValue="REGION_3" />
|
||||
<p:ajax update="dtEntites @(.stats-summary)" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="field">
|
||||
<p:outputLabel value="Actions rapides" />
|
||||
<div class="flex gap-2 mt-1">
|
||||
<p:commandButton value="Rechercher"
|
||||
icon="pi pi-search"
|
||||
styleClass="p-button-primary p-button-sm"
|
||||
action="#{entitesGestionBean.rechercher}"
|
||||
update="dtEntites @(.stats-summary)" />
|
||||
<p:commandButton value="Reset"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="p-button-outlined p-button-secondary p-button-sm"
|
||||
action="#{entitesGestionBean.reinitialiserFiltres}"
|
||||
update="@form dtEntites @(.stats-summary)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filtres avancés - Section extensible -->
|
||||
<p:togglePanel id="filtresAvances" header="Filtres Avancés (Souscriptions & Financier)"
|
||||
styleClass="mt-3" collapsed="true">
|
||||
<div class="grid mt-2">
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="field">
|
||||
<p:outputLabel for="filterForfait" value="Forfait" />
|
||||
<p:selectOneMenu id="filterForfait" value="#{entitesGestionBean.filtres.forfait}">
|
||||
<f:selectItem itemLabel="Tous les forfaits" itemValue="" />
|
||||
<f:selectItem itemLabel="Starter (2K)" itemValue="Starter" />
|
||||
<f:selectItem itemLabel="Standard (3K)" itemValue="Standard" />
|
||||
<f:selectItem itemLabel="Premium (4K)" itemValue="Premium" />
|
||||
<f:selectItem itemLabel="Cristal (5K)" itemValue="Cristal" />
|
||||
<p:ajax update="dtEntites @(.stats-summary)" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="field">
|
||||
<p:outputLabel for="filterQuota" value="Alerte Quota" />
|
||||
<p:selectOneMenu id="filterQuota" value="#{entitesGestionBean.filtres.alerteQuota}">
|
||||
<f:selectItem itemLabel="Toutes" itemValue="" />
|
||||
<f:selectItem itemLabel="Quota proche/atteint" itemValue="OUI" />
|
||||
<f:selectItem itemLabel="Quota normal" itemValue="NON" />
|
||||
<p:ajax update="dtEntites @(.stats-summary)" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="field">
|
||||
<p:outputLabel for="filterExpiration" value="Expiration Proche" />
|
||||
<p:selectOneMenu id="filterExpiration" value="#{entitesGestionBean.filtres.alerteExpiration}">
|
||||
<f:selectItem itemLabel="Toutes" itemValue="" />
|
||||
<f:selectItem itemLabel="Expire sous 30j" itemValue="OUI" />
|
||||
<f:selectItem itemLabel="Valide >30j" itemValue="NON" />
|
||||
<p:ajax update="dtEntites @(.stats-summary)" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="field">
|
||||
<p:outputLabel for="filterStatutSouscription" value="Statut Souscription" />
|
||||
<p:selectOneMenu id="filterStatutSouscription" value="#{entitesGestionBean.filtres.statutSouscription}">
|
||||
<f:selectItem itemLabel="Tous" itemValue="" />
|
||||
<f:selectItem itemLabel="Active" itemValue="ACTIVE" />
|
||||
<f:selectItem itemLabel="Expirée" itemValue="EXPIRED" />
|
||||
<f:selectItem itemLabel="Suspendue" itemValue="SUSPENDED" />
|
||||
<p:ajax update="dtEntites @(.stats-summary)" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</p:togglePanel>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
|
||||
<!-- Table enrichie des entités -->>
|
||||
<div class="card">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="m-0">Entités avec Souscriptions (#{entitesGestionBean.entitesFiltrees.size()})</h5>
|
||||
<div class="flex align-items-center gap-2">
|
||||
<h:form id="formActionsGroupees">
|
||||
<p:commandButton value="Actions groupées"
|
||||
icon="pi pi-cog"
|
||||
styleClass="p-button-outlined p-button-warning"
|
||||
onclick="PF('dlgActionsGroupees').show();"
|
||||
disabled="#{empty entitesGestionBean.entitesSelectionnees}" />
|
||||
</h:form>
|
||||
<span class="text-600 text-sm stats-summary">
|
||||
#{entitesGestionBean.entitesFiltrees.size()} sur #{entitesGestionBean.toutesLesEntites.size()} entités
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p:dataTable id="dtEntites"
|
||||
value="#{entitesGestionBean.entitesFiltrees}"
|
||||
var="entite"
|
||||
selection="#{entitesGestionBean.entitesSelectionnees}"
|
||||
rowKey="#{entite.id}"
|
||||
paginator="true"
|
||||
rows="15"
|
||||
paginatorPosition="both"
|
||||
sortMode="single"
|
||||
styleClass="p-datatable-sm"
|
||||
emptyMessage="Aucune entité trouvée">
|
||||
|
||||
<p:column selectionMode="multiple" width="40" />
|
||||
|
||||
<p:column headerText="Entité" sortBy="#{entite.nom}" width="220">
|
||||
<div class="flex align-items-center">
|
||||
<div class="border-circle bg-primary text-white flex align-items-center justify-content-center mr-3"
|
||||
style="width: 32px; height: 32px;">
|
||||
<i class="pi #{entite.typeIcon}"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-900 font-medium">#{entite.nom}</div>
|
||||
<div class="text-600 text-sm">#{entite.codeEntite}</div>
|
||||
</div>
|
||||
</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Forfait" sortBy="#{entite.forfaitSouscrit}" width="120">
|
||||
<div class="text-center">
|
||||
<p:tag value="#{entite.forfaitSouscrit}"
|
||||
severity="#{entite.forfaitCouleur}"
|
||||
icon="pi #{entite.forfaitIcone}" />
|
||||
<div class="text-600 text-xs mt-1">#{entite.montantMensuel}</div>
|
||||
</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Quota Membres" sortBy="#{entite.membresUtilises}" width="140">
|
||||
<div class="text-center">
|
||||
<div class="text-900 font-bold mb-1">#{entite.membresUtilises}/#{entite.membresQuota}</div>
|
||||
<div class="quota-progress #{entite.quotaAtteint ? 'quota-danger' : entite.quotaProche ? 'quota-warning' : 'quota-success'}">
|
||||
<div style="width: #{entite.pourcentageUtilisationQuota}%; height: 100%; background: rgba(255,255,255,0.8);"></div>
|
||||
</div>
|
||||
<div class="text-600 text-xs mt-1">#{entite.pourcentageUtilisationQuota}%</div>
|
||||
</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Expiration" sortBy="#{entite.dateExpirationSouscription}" width="120">
|
||||
<div class="text-center">
|
||||
<div class="text-900 text-sm mb-1">
|
||||
#{entite.dateExpirationSouscription != null ? entite.dateExpirationSouscription.format(java.time.format.DateTimeFormatter.ofPattern('dd/MM/yyyy')) : 'N/A'}
|
||||
</div>
|
||||
<div class="text-#{entite.expirationProche ? 'red' : 'green'}-600 text-xs">
|
||||
<i class="pi pi-clock mr-1"></i>
|
||||
#{entite.joursAvantExpiration} jours
|
||||
</div>
|
||||
</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Région" sortBy="#{entite.region}" width="100">
|
||||
<span class="text-900">#{entite.region}</span>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Statut" sortBy="#{entite.statut}" width="100">
|
||||
<p:tag value="#{entite.statut}"
|
||||
severity="#{entite.statutSeverity}"
|
||||
icon="pi #{entite.statutIcon}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Actions" width="150">
|
||||
<h:form id="formActions#{entite.id}">
|
||||
<div class="flex gap-1">
|
||||
<p:commandButton icon="pi pi-eye"
|
||||
styleClass="p-button-rounded p-button-text p-button-info"
|
||||
action="#{entitesGestionBean.voirEntite(entite)}"
|
||||
title="Voir détails" />
|
||||
<p:commandButton icon="pi pi-refresh"
|
||||
styleClass="p-button-rounded p-button-text p-button-success"
|
||||
onclick="PF('dlgRenouvelerSouscription').show();"
|
||||
title="Renouveler"
|
||||
rendered="#{entite.expirationProche}">
|
||||
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
|
||||
</p:commandButton>
|
||||
<p:commandButton icon="pi pi-arrow-up"
|
||||
styleClass="p-button-rounded p-button-text p-button-warning"
|
||||
onclick="PF('dlgUpgraderForfait').show();"
|
||||
title="Upgrader"
|
||||
rendered="#{entite.quotaProche}">
|
||||
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
|
||||
</p:commandButton>
|
||||
<p:commandButton icon="pi pi-cog"
|
||||
styleClass="p-button-rounded p-button-text p-button-secondary"
|
||||
onclick="PF('dlgActionsEntite').show();"
|
||||
title="Actions">
|
||||
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
|
||||
</p:commandButton>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:column>
|
||||
</p:dataTable>
|
||||
</div>
|
||||
|
||||
<!-- Dialog Renouveler Souscription -->>
|
||||
<p:dialog header="Renouveler la Souscription" widgetVar="dlgRenouvelerSouscription" modal="true" width="500">
|
||||
<h:form id="formRenouvelerSouscription">
|
||||
<div class="ui-fluid">
|
||||
<div class="text-center mb-4">
|
||||
<i class="pi pi-refresh text-green-500 text-4xl mb-2"></i>
|
||||
<h4>Confirmer le renouvellement</h4>
|
||||
<p class="text-600">
|
||||
Entité: <strong>#{entitesGestionBean.entiteSelectionne.nom}</strong><br/>
|
||||
Forfait: <strong>#{entitesGestionBean.entiteSelectionne.forfaitSouscrit}</strong><br/>
|
||||
Montant: <strong>#{entitesGestionBean.entiteSelectionne.montantMensuel}</strong>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 justify-content-center">
|
||||
<p:commandButton value="Confirmer" icon="pi pi-check"
|
||||
styleClass="p-button-success"
|
||||
action="#{entitesGestionBean.renouvelerSouscription}"
|
||||
update="dtEntites @(.stats-summary)"
|
||||
oncomplete="PF('dlgRenouvelerSouscription').hide();" />
|
||||
<p:commandButton value="Annuler" icon="pi pi-times"
|
||||
styleClass="p-button-secondary"
|
||||
onclick="PF('dlgRenouvelerSouscription').hide();" type="button" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
<!-- Dialog Upgrader Forfait -->>
|
||||
<p:dialog header="Upgrader le Forfait" widgetVar="dlgUpgraderForfait" modal="true" width="500">
|
||||
<h:form id="formUpgraderForfait">
|
||||
<div class="ui-fluid">
|
||||
<div class="text-center mb-4">
|
||||
<i class="pi pi-arrow-up text-orange-500 text-4xl mb-2"></i>
|
||||
<h4>Upgrader le forfait</h4>
|
||||
<p class="text-600">
|
||||
Entité: <strong>#{entitesGestionBean.entiteSelectionne.nom}</strong><br/>
|
||||
Forfait actuel: <strong>#{entitesGestionBean.entiteSelectionne.forfaitSouscrit}</strong><br/>
|
||||
Quota utilisé: <strong>#{entitesGestionBean.entiteSelectionne.pourcentageUtilisationQuota}%</strong>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 justify-content-center">
|
||||
<p:commandButton value="Upgrader" icon="pi pi-arrow-up"
|
||||
styleClass="p-button-warning"
|
||||
action="#{entitesGestionBean.upgraderForfait}"
|
||||
update="dtEntites @(.stats-summary)"
|
||||
oncomplete="PF('dlgUpgraderForfait').hide();" />
|
||||
<p:commandButton value="Annuler" icon="pi pi-times"
|
||||
styleClass="p-button-secondary"
|
||||
onclick="PF('dlgUpgraderForfait').hide();" type="button" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
<!-- Dialog Actions Groupées -->>
|
||||
<p:dialog header="Actions Groupées" widgetVar="dlgActionsGroupees" modal="true" width="600">
|
||||
<h:form id="formActionsGroupees">
|
||||
<div class="ui-fluid">
|
||||
<div class="text-center mb-4">
|
||||
<i class="pi pi-cog text-orange-500 text-4xl mb-2"></i>
|
||||
<h4>Actions sur #{entitesGestionBean.entitesSelectionnees.size()} entités sélectionnées</h4>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<h6>Actions de Souscription</h6>
|
||||
<p:commandButton value="Renouveler toutes"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="p-button-success w-full mb-2"
|
||||
action="#{entitesGestionBean.renouvelerSouscriptionsGroupees}"
|
||||
update="dtEntites @(.stats-summary)"
|
||||
oncomplete="PF('dlgActionsGroupees').hide();"
|
||||
onclick="return confirm('Renouveler les souscriptions de toutes les entités sélectionnées ?');" />
|
||||
|
||||
<p:commandButton value="Envoyer relances"
|
||||
icon="pi pi-send"
|
||||
styleClass="p-button-info w-full mb-2"
|
||||
action="#{entitesGestionBean.envoyerRelancesSouscriptions}"
|
||||
oncomplete="PF('dlgActionsGroupees').hide();" />
|
||||
|
||||
<p:commandButton value="Proposer upgrade"
|
||||
icon="pi pi-arrow-up"
|
||||
styleClass="p-button-warning w-full mb-2"
|
||||
action="#{entitesGestionBean.proposerUpgradeGroupees}"
|
||||
oncomplete="PF('dlgActionsGroupees').hide();" />
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<h6>Actions Administratives</h6>
|
||||
<p:commandButton value="Suspendre toutes"
|
||||
icon="pi pi-ban"
|
||||
styleClass="p-button-danger w-full mb-2"
|
||||
action="#{entitesGestionBean.suspendreEntitesGroupees}"
|
||||
update="dtEntites @(.stats-summary)"
|
||||
oncomplete="PF('dlgActionsGroupees').hide();"
|
||||
onclick="return confirm('ATTENTION: Suspendre toutes les entités sélectionnées ?');" />
|
||||
|
||||
<p:commandButton value="Réactiver toutes"
|
||||
icon="pi pi-check"
|
||||
styleClass="p-button-success w-full mb-2"
|
||||
action="#{entitesGestionBean.reactiverEntitesGroupees}"
|
||||
update="dtEntites @(.stats-summary)"
|
||||
oncomplete="PF('dlgActionsGroupees').hide();" />
|
||||
|
||||
<p:commandButton value="Exporter sélection"
|
||||
icon="pi pi-download"
|
||||
styleClass="p-button-secondary w-full mb-2"
|
||||
action="#{entitesGestionBean.exporterEntites}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end mt-4 pt-3 border-top-1 surface-border">
|
||||
<p:commandButton value="Fermer" icon="pi pi-times"
|
||||
styleClass="p-button-secondary"
|
||||
onclick="PF('dlgActionsGroupees').hide();" type="button" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
<!-- Dialog Actions Entité (conservé de l'original) -->>
|
||||
<p:dialog header="Actions sur l'Entité" widgetVar="dlgActionsEntite" modal="true" width="400">
|
||||
<h:form id="formActionsEntite">
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<p:commandButton value="Gérer les membres"
|
||||
icon="pi pi-users"
|
||||
styleClass="p-button-outlined p-button-info w-full mb-2"
|
||||
action="#{entitesGestionBean.gererMembres}" />
|
||||
|
||||
<p:commandButton value="Configuration"
|
||||
icon="pi pi-cog"
|
||||
styleClass="p-button-outlined p-button-warning w-full mb-2"
|
||||
action="#{entitesGestionBean.configurerEntite}" />
|
||||
|
||||
<p:commandButton value="Rapports"
|
||||
icon="pi pi-chart-bar"
|
||||
styleClass="p-button-outlined p-button-secondary w-full mb-2"
|
||||
action="#{entitesGestionBean.voirRapports}" />
|
||||
|
||||
<p:commandButton value="Suspendre"
|
||||
icon="pi pi-ban"
|
||||
styleClass="p-button-outlined p-button-danger w-full mb-2"
|
||||
action="#{entitesGestionBean.suspendreEntite}"
|
||||
onclick="return confirm('Êtes-vous sûr de vouloir suspendre cette entité ?');"
|
||||
rendered="#{entitesGestionBean.entiteSelectionne.statut == 'ACTIVE'}" />
|
||||
|
||||
<p:commandButton value="Réactiver"
|
||||
icon="pi pi-check"
|
||||
styleClass="p-button-outlined p-button-success w-full mb-2"
|
||||
action="#{entitesGestionBean.reactiverEntite}"
|
||||
rendered="#{entitesGestionBean.entiteSelectionne.statut == 'SUSPENDUE'}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end mt-3">
|
||||
<p:commandButton value="Fermer" icon="pi pi-times"
|
||||
styleClass="p-button-secondary"
|
||||
onclick="PF('dlgActionsEntite').hide();" type="button" />
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
@@ -0,0 +1,433 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Gestion des Entités - UnionFlow</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<div class="ui-fluid">
|
||||
<!-- En-tête principal avec disposition Freya stricte -->
|
||||
<div class="card">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 lg:col-8">
|
||||
<h2 class="text-primary font-bold mb-2">
|
||||
<i class="pi pi-building text-blue-500 mr-2"></i>
|
||||
Gestion des Entités
|
||||
</h2>
|
||||
<p class="text-600 mt-0">
|
||||
Administration complète des clubs et entités Lions •
|
||||
<span class="font-semibold">#{entitesGestionBean.statistiques.totalEntites} entités</span> •
|
||||
<span class="font-semibold text-green-600">#{entitesGestionBean.statistiques.entitesActives} actives</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field col-12 lg:col-4 text-right">
|
||||
<h:form id="formActionsEntete">
|
||||
<p:commandButton icon="pi pi-plus"
|
||||
title="Nouvelle entité"
|
||||
styleClass="ui-button-success ui-button-sm mr-3"
|
||||
onclick="PF('dlgNouvelleEntite').show();" />
|
||||
<p:commandButton icon="pi pi-upload"
|
||||
title="Import Excel"
|
||||
styleClass="ui-button-info ui-button-outlined ui-button-sm mr-3"
|
||||
onclick="PF('dlgImportEntites').show();" />
|
||||
<p:commandButton icon="pi pi-download"
|
||||
title="Exporter"
|
||||
styleClass="ui-button-secondary ui-button-outlined ui-button-sm"
|
||||
action="#{entitesGestionBean.exporterEntites}" />
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPIs avec grille Freya stricte -->
|
||||
<div class="formgrid grid">
|
||||
<!-- KPI 1: Total Entités -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Total Entités" />
|
||||
<ui:param name="value" value="#{entitesGestionBean.statistiques.totalEntites}" />
|
||||
<ui:param name="icon" value="pi-building" />
|
||||
<ui:param name="iconColor" value="blue-600" />
|
||||
<ui:param name="growthValue" value="8" />
|
||||
<ui:param name="growthLabel" value="ce mois" />
|
||||
<ui:param name="growthType" value="number" />
|
||||
<ui:param name="showProgress" value="false" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 2: Entités Actives -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Entités Actives" />
|
||||
<ui:param name="value" value="#{entitesGestionBean.statistiques.entitesActives}" />
|
||||
<ui:param name="icon" value="pi-check" />
|
||||
<ui:param name="iconColor" value="green-600" />
|
||||
<ui:param name="progressValue" value="92" />
|
||||
<ui:param name="noDataLabel" value="92% d'activité" />
|
||||
<ui:param name="showGrowth" value="false" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 3: Total Membres -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Total Membres" />
|
||||
<ui:param name="value" value="#{entitesGestionBean.statistiques.totalMembres}" />
|
||||
<ui:param name="icon" value="pi-users" />
|
||||
<ui:param name="iconColor" value="orange-600" />
|
||||
<ui:param name="statusIcon" value="pi-info-circle" />
|
||||
<ui:param name="statusLabel" value="Moyenne" />
|
||||
<ui:param name="statusValue" value="#{entitesGestionBean.statistiques.moyenneMembresParEntite}/entité" />
|
||||
<ui:param name="showProgress" value="false" />
|
||||
</ui:include>
|
||||
|
||||
<!-- KPI 4: Revenus Totaux -->
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Revenus Totaux" />
|
||||
<ui:param name="value" value="#{entitesGestionBean.statistiques.revenus}" />
|
||||
<ui:param name="icon" value="pi-dollar" />
|
||||
<ui:param name="iconColor" value="purple-600" />
|
||||
<ui:param name="growthValue" value="15" />
|
||||
<ui:param name="growthLabel" value="vs année dernière" />
|
||||
<ui:param name="showProgress" value="false" />
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<!-- Section Filtres avec structure Freya -->
|
||||
<div class="card">
|
||||
<h5 class="mb-3">
|
||||
<i class="pi pi-filter text-blue-500 mr-2"></i>
|
||||
Filtres et Recherche
|
||||
</h5>
|
||||
<h:form id="formFiltres">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<label for="searchNom" class="block text-900 font-medium mb-2">Nom de l'entité</label>
|
||||
<span class="p-input-icon-left w-full">
|
||||
<i class="pi pi-search"></i>
|
||||
<p:inputText id="searchNom"
|
||||
value="#{entitesGestionBean.filtres.nom}"
|
||||
placeholder="Rechercher par nom..."
|
||||
styleClass="w-full">
|
||||
<p:ajax event="keyup" delay="300"
|
||||
update=":formTableEntites:dtEntites" />
|
||||
</p:inputText>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<label for="filterType" class="block text-900 font-medium mb-2">Type d'entité</label>
|
||||
<p:selectOneMenu id="filterType"
|
||||
value="#{entitesGestionBean.filtres.type}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Tous les types" itemValue="" />
|
||||
<f:selectItem itemLabel="Club Lions" itemValue="CLUB_LIONS" />
|
||||
<f:selectItem itemLabel="LEO Club" itemValue="LEO_CLUB" />
|
||||
<f:selectItem itemLabel="Branche" itemValue="BRANCHE" />
|
||||
<p:ajax update=":formTableEntites:dtEntites" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<label for="filterStatut" class="block text-900 font-medium mb-2">Statut</label>
|
||||
<p:selectOneMenu id="filterStatut"
|
||||
value="#{entitesGestionBean.filtres.statut}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
|
||||
<f:selectItem itemLabel="Active" itemValue="ACTIVE" />
|
||||
<f:selectItem itemLabel="Inactive" itemValue="INACTIVE" />
|
||||
<f:selectItem itemLabel="Suspendue" itemValue="SUSPENDUE" />
|
||||
<p:ajax update=":formTableEntites:dtEntites" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6 lg:col-3">
|
||||
<label for="filterRegion" class="block text-900 font-medium mb-2">Région</label>
|
||||
<p:selectOneMenu id="filterRegion"
|
||||
value="#{entitesGestionBean.filtres.region}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Toutes les régions" itemValue="" />
|
||||
<f:selectItem itemLabel="Dakar" itemValue="DAKAR" />
|
||||
<f:selectItem itemLabel="Thiès" itemValue="THIES" />
|
||||
<f:selectItem itemLabel="Kaolack" itemValue="KAOLACK" />
|
||||
<f:selectItem itemLabel="Saint-Louis" itemValue="SAINT_LOUIS" />
|
||||
<p:ajax update=":formTableEntites:dtEntites" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end mt-3">
|
||||
<p:commandButton value="Réinitialiser"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="ui-button-outlined ui-button-secondary ui-button-sm"
|
||||
action="#{entitesGestionBean.reinitialiserFiltres}"
|
||||
update="@form :formTableEntites:dtEntites" />
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
|
||||
<!-- Table des Entités avec structure Freya -->
|
||||
<div class="card">
|
||||
<h:form id="formTableEntites">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="m-0">
|
||||
<i class="pi pi-list text-primary mr-2"></i>
|
||||
Liste des Entités
|
||||
</h5>
|
||||
<div>
|
||||
<p:commandButton value="Actions groupées"
|
||||
icon="pi pi-bars"
|
||||
styleClass="ui-button-warning ui-button-sm mr-2"
|
||||
onclick="PF('dlgActionsGroupees').show();"
|
||||
disabled="#{empty entitesGestionBean.entitesSelectionnees}" />
|
||||
<p:commandButton value="Export Excel"
|
||||
icon="pi pi-file-excel"
|
||||
styleClass="ui-button-success ui-button-outlined ui-button-sm"
|
||||
action="#{entitesGestionBean.exporterExcel}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p:dataTable id="dtEntites"
|
||||
value="#{entitesGestionBean.entitesFiltrees}"
|
||||
var="entite"
|
||||
selection="#{entitesGestionBean.entitesSelectionnees}"
|
||||
rowKey="#{entite.id}"
|
||||
paginator="true"
|
||||
rows="20"
|
||||
paginatorPosition="bottom"
|
||||
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
|
||||
rowsPerPageTemplate="10,20,50,100"
|
||||
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords} entités"
|
||||
styleClass="p-datatable-sm p-datatable-gridlines p-datatable-striped"
|
||||
emptyMessage="Aucune entité trouvée">
|
||||
|
||||
<p:column selectionMode="multiple" style="width:3rem" exportable="false"/>
|
||||
|
||||
<p:column headerText="Entité" sortBy="#{entite.nom}" filterBy="#{entite.nom}">
|
||||
<div class="flex align-items-center">
|
||||
<div class="flex align-items-center justify-content-center bg-primary-100 border-circle mr-2"
|
||||
style="width: 2rem; height: 2rem;">
|
||||
<i class="pi #{entite.typeIcon} text-primary-600"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-900 font-medium">#{entite.nom}</div>
|
||||
<div class="text-500 text-xs">#{entite.codeEntite}</div>
|
||||
</div>
|
||||
</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Type" sortBy="#{entite.type}" filterBy="#{entite.type}" style="width:8rem">
|
||||
<p:tag value="#{entite.typeLibelle}"
|
||||
severity="#{entite.typeSeverity}"
|
||||
icon="pi #{entite.typeIcon}"
|
||||
styleClass="text-xs" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Région" sortBy="#{entite.region}" style="width:8rem">
|
||||
<span class="text-900 font-medium">#{entite.region}</span>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Membres" sortBy="#{entite.nombreMembres}" style="width:6rem; text-align:center">
|
||||
<div class="text-center">
|
||||
<div class="text-900 font-bold">#{entite.nombreMembres}</div>
|
||||
<div class="text-500 text-xs">membres</div>
|
||||
</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Administrateur">
|
||||
<div class="flex align-items-center" rendered="#{entite.administrateur != null}">
|
||||
<div class="bg-300 border-circle mr-2" style="width: 1.5rem; height: 1.5rem;"></div>
|
||||
<div>
|
||||
<div class="text-900 text-sm">#{entite.administrateur.nomComplet}</div>
|
||||
<div class="text-500 text-xs">#{entite.administrateur.email}</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-400 text-xs" rendered="#{entite.administrateur == null}">
|
||||
Aucun administrateur
|
||||
</span>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Dernière activité" sortBy="#{entite.derniereActivite}" style="width:10rem">
|
||||
<div class="text-900 text-sm">#{entite.derniereActiviteFormatee}</div>
|
||||
<div class="text-500 text-xs">#{entite.derniereActiviteRelative}</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Statut" sortBy="#{entite.statut}" filterBy="#{entite.statut}" style="width:7rem">
|
||||
<p:tag value="#{entite.statut}"
|
||||
severity="#{entite.statutSeverity}"
|
||||
icon="pi #{entite.statutIcon}"
|
||||
styleClass="text-xs w-full" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Actions" style="width:8rem" exportable="false">
|
||||
<h:form id="formActions#{entite.id}">
|
||||
<div class="flex gap-1">
|
||||
<p:commandButton icon="pi pi-eye"
|
||||
styleClass="ui-button-rounded ui-button-text ui-button-info ui-button-sm"
|
||||
action="#{entitesGestionBean.voirEntite(entite)}"
|
||||
title="Voir détails" />
|
||||
<p:commandButton icon="pi pi-pencil"
|
||||
styleClass="ui-button-rounded ui-button-text ui-button-warning ui-button-sm"
|
||||
onclick="PF('dlgModifierEntite').show();"
|
||||
title="Modifier">
|
||||
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
|
||||
</p:commandButton>
|
||||
<p:commandButton icon="pi pi-cog"
|
||||
styleClass="ui-button-rounded ui-button-text ui-button-secondary ui-button-sm"
|
||||
onclick="PF('dlgActionsEntite').show();"
|
||||
title="Actions">
|
||||
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
|
||||
</p:commandButton>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:column>
|
||||
</p:dataTable>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dialogs avec structure Freya -->
|
||||
|
||||
<!-- Dialog Nouvelle Entité -->
|
||||
<p:dialog header="Créer une Nouvelle Entité"
|
||||
widgetVar="dlgNouvelleEntite"
|
||||
modal="true"
|
||||
width="700"
|
||||
height="auto"
|
||||
resizable="false">
|
||||
<h:form id="formNouvelleEntite">
|
||||
<div class="ui-fluid formgrid grid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="newNom" class="block text-900 font-medium mb-2">Nom de l'entité *</label>
|
||||
<p:inputText id="newNom"
|
||||
value="#{entitesGestionBean.nouvelleEntite.nom}"
|
||||
required="true"
|
||||
placeholder="Ex: Lions Club Dakar Centre" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="newType" class="block text-900 font-medium mb-2">Type d'entité *</label>
|
||||
<p:selectOneMenu id="newType"
|
||||
value="#{entitesGestionBean.nouvelleEntite.type}"
|
||||
required="true">
|
||||
<f:selectItem itemLabel="Sélectionner un type" itemValue="" />
|
||||
<f:selectItem itemLabel="Club Lions" itemValue="CLUB_LIONS" />
|
||||
<f:selectItem itemLabel="LEO Club" itemValue="LEO_CLUB" />
|
||||
<f:selectItem itemLabel="Branche" itemValue="BRANCHE" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="newRegion" class="block text-900 font-medium mb-2">Région *</label>
|
||||
<p:selectOneMenu id="newRegion"
|
||||
value="#{entitesGestionBean.nouvelleEntite.region}"
|
||||
required="true">
|
||||
<f:selectItem itemLabel="Sélectionner une région" itemValue="" />
|
||||
<f:selectItem itemLabel="Dakar" itemValue="DAKAR" />
|
||||
<f:selectItem itemLabel="Thiès" itemValue="THIES" />
|
||||
<f:selectItem itemLabel="Kaolack" itemValue="KAOLACK" />
|
||||
<f:selectItem itemLabel="Saint-Louis" itemValue="SAINT_LOUIS" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="newTelephone" class="block text-900 font-medium mb-2">Téléphone</label>
|
||||
<p:inputText id="newTelephone"
|
||||
value="#{entitesGestionBean.nouvelleEntite.telephone}"
|
||||
placeholder="77 123 45 67" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12">
|
||||
<label for="newEmail" class="block text-900 font-medium mb-2">Email</label>
|
||||
<p:inputText id="newEmail"
|
||||
value="#{entitesGestionBean.nouvelleEntite.email}"
|
||||
placeholder="contact@lionsclub-dakar.sn" />
|
||||
</div>
|
||||
|
||||
<div class="field col-12">
|
||||
<label for="newAdresse" class="block text-900 font-medium mb-2">Adresse</label>
|
||||
<p:inputTextarea id="newAdresse"
|
||||
value="#{entitesGestionBean.nouvelleEntite.adresse}"
|
||||
rows="2"
|
||||
placeholder="Adresse complète de l'entité..." />
|
||||
</div>
|
||||
|
||||
<div class="field col-12">
|
||||
<label for="newDescription" class="block text-900 font-medium mb-2">Description</label>
|
||||
<p:inputTextarea id="newDescription"
|
||||
value="#{entitesGestionBean.nouvelleEntite.description}"
|
||||
rows="3"
|
||||
placeholder="Description de l'entité..." />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end gap-2 mt-3">
|
||||
<p:commandButton value="Annuler"
|
||||
icon="pi pi-times"
|
||||
styleClass="ui-button-secondary ui-button-outlined ui-button-sm"
|
||||
onclick="PF('dlgNouvelleEntite').hide();"
|
||||
type="button" />
|
||||
<p:commandButton value="Créer l'entité"
|
||||
icon="pi pi-check"
|
||||
styleClass="ui-button-success ui-button-sm"
|
||||
action="#{entitesGestionBean.creerEntite}"
|
||||
update="@form :formTableEntites:dtEntites"
|
||||
oncomplete="if(!args.validationFailed) PF('dlgNouvelleEntite').hide();" />
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
<!-- Dialog Actions Entité -->
|
||||
<p:dialog header="Actions sur l'Entité"
|
||||
widgetVar="dlgActionsEntite"
|
||||
modal="true"
|
||||
width="400"
|
||||
height="auto"
|
||||
resizable="false">
|
||||
<h:form id="formActionsEntite">
|
||||
<div class="surface-50 border-round-lg p-3 mb-3">
|
||||
<div class="text-500 text-sm mb-1">Entité sélectionnée</div>
|
||||
<div class="text-900 font-bold">#{entitesGestionBean.entiteSelectionne.nom}</div>
|
||||
<div class="text-500 text-sm">#{entitesGestionBean.entiteSelectionne.codeEntite}</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-column gap-2">
|
||||
<p:commandButton value="Gérer les membres"
|
||||
icon="pi pi-users"
|
||||
styleClass="ui-button-info ui-button-outlined ui-button-sm w-full"
|
||||
action="#{entitesGestionBean.gererMembres}" />
|
||||
|
||||
<p:commandButton value="Configuration"
|
||||
icon="pi pi-cog"
|
||||
styleClass="ui-button-warning ui-button-outlined ui-button-sm w-full"
|
||||
action="#{entitesGestionBean.configurerEntite}" />
|
||||
|
||||
<p:commandButton value="Rapports"
|
||||
icon="pi pi-chart-bar"
|
||||
styleClass="ui-button-secondary ui-button-outlined ui-button-sm w-full"
|
||||
action="#{entitesGestionBean.voirRapports}" />
|
||||
|
||||
<p:commandButton value="Suspendre"
|
||||
icon="pi pi-ban"
|
||||
styleClass="ui-button-danger ui-button-outlined ui-button-sm w-full"
|
||||
action="#{entitesGestionBean.suspendreEntite}"
|
||||
onclick="return confirm('Êtes-vous sûr de vouloir suspendre cette entité ?');"
|
||||
rendered="#{entitesGestionBean.entiteSelectionne.statut == 'ACTIVE'}" />
|
||||
|
||||
<p:commandButton value="Réactiver"
|
||||
icon="pi pi-check"
|
||||
styleClass="ui-button-success ui-button-outlined ui-button-sm w-full"
|
||||
action="#{entitesGestionBean.reactiverEntite}"
|
||||
rendered="#{entitesGestionBean.entiteSelectionne.statut == 'SUSPENDUE'}" />
|
||||
|
||||
<hr class="surface-border" />
|
||||
|
||||
<p:commandButton value="Supprimer"
|
||||
icon="pi pi-trash"
|
||||
styleClass="ui-button-danger ui-button-sm w-full"
|
||||
onclick="return confirm('ATTENTION: Cette action est irréversible. Confirmer la suppression ?');"
|
||||
action="#{entitesGestionBean.supprimerEntite}" />
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
@@ -0,0 +1,212 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Gestion des Organisations</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<h:form id="formOrgs">
|
||||
<p:messages id="messages" showDetail="true" closable="true" />
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="mb-1">Organisations</h5>
|
||||
<span class="text-600">
|
||||
CRUD complet des organisations. Respect DRY/WOU: composants réutilisés et simplicité.
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<p:commandButton value="Nouvelle organisation"
|
||||
icon="pi pi-plus"
|
||||
styleClass="ui-button-success"
|
||||
actionListener="#{organisationsBean.preparerNouvelleOrganisation}"
|
||||
update=":formOrgs:dlgCreate"
|
||||
oncomplete="PF('dlgCreate').show();" />
|
||||
<p:commandButton value="Rafraîchir"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="ui-button-secondary ml-2"
|
||||
actionListener="#{organisationsBean.recharger}"
|
||||
update=":formOrgs:dtOrgs :formOrgs:stats :formOrgs:messages" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p:outputPanel id="stats" styleClass="grid mb-3">
|
||||
<div class="col-12 md:col-4">
|
||||
<p:card>
|
||||
<f:facet name="title">Total</f:facet>
|
||||
<h:outputText value="#{organisationsBean.totalOrganisations}" />
|
||||
</p:card>
|
||||
</div>
|
||||
<div class="col-12 md:col-4">
|
||||
<p:card>
|
||||
<f:facet name="title">Actives</f:facet>
|
||||
<h:outputText value="#{organisationsBean.organisationsActives}" />
|
||||
</p:card>
|
||||
</div>
|
||||
<div class="col-12 md:col-4">
|
||||
<p:card>
|
||||
<f:facet name="title">Inactives</f:facet>
|
||||
<h:outputText value="#{organisationsBean.organisationsInactives}" />
|
||||
</p:card>
|
||||
</div>
|
||||
</p:outputPanel>
|
||||
|
||||
<div class="card">
|
||||
<div class="grid mb-3 p-3">
|
||||
<div class="col-12 md:col-4">
|
||||
<p:inputText placeholder="Recherche (nom, ville, description)"
|
||||
value="#{organisationsBean.rechercheGlobale}">
|
||||
<p:ajax event="keyup" update=":formOrgs:dtOrgs" listener="#{organisationsBean.appliquerFiltres}" />
|
||||
</p:inputText>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<p:selectOneMenu value="#{organisationsBean.filtreStatut}">
|
||||
<f:selectItems value="#{organisationsBean.statutsSelectItems}" />
|
||||
<p:ajax update=":formOrgs:dtOrgs" listener="#{organisationsBean.appliquerFiltres}" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<p:selectOneMenu value="#{organisationsBean.filtreType}">
|
||||
<f:selectItems value="#{organisationsBean.typesSelectItems}" />
|
||||
<p:ajax update=":formOrgs:dtOrgs" listener="#{organisationsBean.appliquerFiltres}" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="col-12 md:col-2 text-right">
|
||||
<p:commandButton value="Réinitialiser"
|
||||
icon="pi pi-filter-slash"
|
||||
styleClass="ui-button-secondary"
|
||||
actionListener="#{organisationsBean.reinitialiserFiltres}"
|
||||
update=":formOrgs:dtOrgs :formOrgs:filters" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p:dataTable id="dtOrgs"
|
||||
value="#{organisationsBean.organisationsFiltrees}"
|
||||
var="org"
|
||||
paginator="true"
|
||||
rows="20"
|
||||
rowsPerPageTemplate="10,20,50"
|
||||
paginatorPosition="bottom"
|
||||
emptyMessage="Aucune organisation trouvée">
|
||||
|
||||
<p:column headerText="Nom" sortBy="#{org.nom}">
|
||||
<h:outputText value="#{org.nom}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Type" sortBy="#{org.typeAssociation}" style="width: 200px;">
|
||||
<p:tag value="#{org.typeLibelle}" severity="info" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Statut" style="width: 140px; text-align: center;">
|
||||
<p:tag value="#{org.statutLibelle}" severity="#{org.statutSeverity}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Localisation" sortBy="#{org.ville}">
|
||||
<h:outputText value="#{org.ville}" />
|
||||
<h:outputText value=", " rendered="#{not empty org.ville and not empty org.region}" />
|
||||
<h:outputText value="#{org.region}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Actions" style="width: 220px; text-align: center;">
|
||||
<p:commandButton icon="pi pi-pencil"
|
||||
title="Modifier"
|
||||
styleClass="ui-button-rounded ui-button-warning mr-2"
|
||||
actionListener="#{organisationsBean.setOrganisationSelectionnee(org)}"
|
||||
update=":formOrgs:dlgEdit"
|
||||
oncomplete="PF('dlgEdit').show();" />
|
||||
|
||||
<p:commandButton icon="#{organisationsBean.estActive(org) ? 'pi pi-ban' : 'pi pi-check'}"
|
||||
title="#{organisationsBean.estActive(org) ? 'Désactiver' : 'Activer'}"
|
||||
styleClass="ui-button-rounded #{organisationsBean.estActive(org) ? 'ui-button-secondary' : 'ui-button-success'} mr-2"
|
||||
update=":formOrgs:dtOrgs :formOrgs:messages :formOrgs:stats"
|
||||
actionListener="#{organisationsBean.basculerStatutOrganisation(org)}">
|
||||
<p:confirm header="Confirmation"
|
||||
message="Confirmez l'action sur le statut de l'organisation ?"
|
||||
icon="pi pi-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
|
||||
<p:commandButton icon="pi pi-trash"
|
||||
title="Supprimer"
|
||||
styleClass="ui-button-rounded ui-button-danger"
|
||||
update=":formOrgs:dtOrgs :formOrgs:messages :formOrgs:stats"
|
||||
actionListener="#{organisationsBean.supprimerOrganisation(org)}">
|
||||
<p:confirm header="Confirmation"
|
||||
message="Supprimer cette organisation ?"
|
||||
icon="pi pi-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
</p:column>
|
||||
</p:dataTable>
|
||||
</div>
|
||||
|
||||
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade" responsive="true" width="350">
|
||||
<p:commandButton value="Non" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
|
||||
onclick="PF('confirmDialog').hide()" />
|
||||
<p:commandButton value="Oui" type="button" styleClass="ui-button-danger" icon="pi pi-check" />
|
||||
</p:confirmDialog>
|
||||
|
||||
<!-- Dialogue création -->
|
||||
<p:dialog id="dlgCreate"
|
||||
widgetVar="dlgCreate"
|
||||
header="Nouvelle organisation"
|
||||
modal="true"
|
||||
resizable="false"
|
||||
responsive="true"
|
||||
width="700">
|
||||
|
||||
<ui:include src="/ui/includes/organisation-form.xhtml">
|
||||
<ui:param name="model" value="#{organisationsBean.nouvelleOrganisation}" />
|
||||
<ui:param name="typesItems" value="#{organisationsBean.typesSelectItemsForForm}" />
|
||||
</ui:include>
|
||||
|
||||
<f:facet name="footer">
|
||||
<p:commandButton value="Annuler"
|
||||
icon="pi pi-times"
|
||||
onclick="PF('dlgCreate').hide();"
|
||||
styleClass="ui-button-secondary" />
|
||||
|
||||
<p:commandButton value="Créer"
|
||||
icon="pi pi-check"
|
||||
process="@form"
|
||||
update=":formOrgs:dtOrgs :formOrgs:messages :formOrgs:stats"
|
||||
actionListener="#{organisationsBean.creerOrganisation}"
|
||||
oncomplete="if(!args.validationFailed) PF('dlgCreate').hide();" />
|
||||
</f:facet>
|
||||
</p:dialog>
|
||||
|
||||
<!-- Dialogue édition -->
|
||||
<p:dialog id="dlgEdit"
|
||||
widgetVar="dlgEdit"
|
||||
header="Modifier l'organisation"
|
||||
modal="true"
|
||||
resizable="false"
|
||||
responsive="true"
|
||||
width="700">
|
||||
|
||||
<ui:include src="/ui/includes/organisation-form.xhtml">
|
||||
<ui:param name="model" value="#{organisationsBean.organisationSelectionnee}" />
|
||||
<ui:param name="typesItems" value="#{organisationsBean.typesSelectItemsForForm}" />
|
||||
</ui:include>
|
||||
|
||||
<f:facet name="footer">
|
||||
<p:commandButton value="Annuler"
|
||||
icon="pi pi-times"
|
||||
onclick="PF('dlgEdit').hide();"
|
||||
styleClass="ui-button-secondary" />
|
||||
|
||||
<p:commandButton value="Enregistrer"
|
||||
icon="pi pi-check"
|
||||
process="@form"
|
||||
update=":formOrgs:dtOrgs :formOrgs:messages"
|
||||
actionListener="#{organisationsBean.modifierOrganisation}"
|
||||
oncomplete="if(!args.validationFailed) PF('dlgEdit').hide();" />
|
||||
</f:facet>
|
||||
</p:dialog>
|
||||
</h:form>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
@@ -0,0 +1,381 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Rôles et Permissions - UnionFlow</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<div class="ui-fluid">
|
||||
|
||||
<!-- En-tête avec statistiques -->
|
||||
<div class="grid mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="flex align-items-center justify-content-between mb-4">
|
||||
<div>
|
||||
<h2 class="text-900 font-bold text-4xl mb-2">
|
||||
<i class="pi pi-shield text-blue-500 mr-3"></i>
|
||||
Rôles et Permissions
|
||||
</h2>
|
||||
<p class="text-600 text-lg mb-0">
|
||||
Gérez les rôles utilisateur et leurs permissions système
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<p:commandButton value="Nouveau Rôle"
|
||||
styleClass="p-button-success"
|
||||
icon="pi pi-plus"
|
||||
onclick="PF('nouveauRoleDialog').show()" />
|
||||
<p:commandButton value="Permissions Globales"
|
||||
styleClass="p-button-info p-button-outlined"
|
||||
icon="pi pi-cog" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPIs -->
|
||||
<div class="grid">
|
||||
<div class="col-12 lg:col-3">
|
||||
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
|
||||
<div class="text-2xl font-bold text-blue-500 mb-2">#{rolesBean.totalRoles}</div>
|
||||
<div class="text-900 font-semibold mb-1">Rôles Totaux</div>
|
||||
<div class="text-600 text-sm">Système et personnalisés</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 lg:col-3">
|
||||
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
|
||||
<div class="text-2xl font-bold text-green-500 mb-2">#{rolesBean.rolesActifs}</div>
|
||||
<div class="text-900 font-semibold mb-1">Rôles Actifs</div>
|
||||
<div class="text-600 text-sm">Utilisés actuellement</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 lg:col-3">
|
||||
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
|
||||
<div class="text-2xl font-bold text-orange-500 mb-2">#{rolesBean.utilisateursAvecRoles}</div>
|
||||
<div class="text-900 font-semibold mb-1">Utilisateurs</div>
|
||||
<div class="text-600 text-sm">Avec rôles assignés</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 lg:col-3">
|
||||
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
|
||||
<div class="text-2xl font-bold text-purple-500 mb-2">#{rolesBean.permissionsUniques}</div>
|
||||
<div class="text-900 font-semibold mb-1">Permissions</div>
|
||||
<div class="text-600 text-sm">Définies au total</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filtres et Actions -->
|
||||
<div class="grid mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<h:form id="filtresForm">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 lg:col-4">
|
||||
<label for="filtreNom" class="block text-900 font-semibold mb-2">
|
||||
<i class="pi pi-search mr-2"></i>Recherche
|
||||
</label>
|
||||
<p:inputText id="filtreNom"
|
||||
value="#{rolesBean.filtreNom}"
|
||||
placeholder="Nom du rôle..."
|
||||
styleClass="w-full">
|
||||
<p:ajax event="keyup" update=":tableauForm:tableauRoles" delay="500" />
|
||||
</p:inputText>
|
||||
</div>
|
||||
<div class="field col-12 lg:col-3">
|
||||
<label for="filtreType" class="block text-900 font-semibold mb-2">
|
||||
<i class="pi pi-filter mr-2"></i>Type de Rôle
|
||||
</label>
|
||||
<p:selectOneMenu id="filtreType"
|
||||
value="#{rolesBean.filtreType}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Tous les types" itemValue="" />
|
||||
<f:selectItem itemLabel="Rôle Système" itemValue="SYSTEME" />
|
||||
<f:selectItem itemLabel="Rôle Personnalisé" itemValue="PERSONNALISE" />
|
||||
<f:selectItem itemLabel="Rôle Temporaire" itemValue="TEMPORAIRE" />
|
||||
<p:ajax update=":tableauForm:tableauRoles" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="field col-12 lg:col-3">
|
||||
<label for="filtreStatut" class="block text-900 font-semibold mb-2">
|
||||
<i class="pi pi-circle mr-2"></i>Statut
|
||||
</label>
|
||||
<p:selectOneMenu id="filtreStatut"
|
||||
value="#{rolesBean.filtreStatut}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
|
||||
<f:selectItem itemLabel="Actif" itemValue="ACTIF" />
|
||||
<f:selectItem itemLabel="Inactif" itemValue="INACTIF" />
|
||||
<f:selectItem itemLabel="Suspendu" itemValue="SUSPENDU" />
|
||||
<p:ajax update=":tableauForm:tableauRoles" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="field col-12 lg:col-2">
|
||||
<label class="block text-900 font-semibold mb-2"> </label>
|
||||
<div class="flex gap-2">
|
||||
<p:commandButton value="Reset"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="p-button-outlined w-full"
|
||||
action="#{rolesBean.reinitialiserFiltres}"
|
||||
update="@form :tableauForm:tableauRoles" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tableau des Rôles -->
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<h:form id="tableauForm">
|
||||
<p:dataTable id="tableauRoles"
|
||||
value="#{rolesBean.rolesFiltres}"
|
||||
var="role"
|
||||
paginator="true"
|
||||
rows="10"
|
||||
paginatorPosition="both"
|
||||
rowsPerPageTemplate="5,10,15,25,50"
|
||||
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown} {CurrentPageReport}"
|
||||
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords} rôles"
|
||||
emptyMessage="Aucun rôle trouvé"
|
||||
styleClass="p-datatable-sm p-datatable-striped"
|
||||
sortMode="multiple"
|
||||
allowUnsorting="true">
|
||||
|
||||
<p:column headerText="Rôle" sortBy="#{role.nom}" style="width: 25%">
|
||||
<div class="flex align-items-center">
|
||||
<div class="w-3rem h-3rem border-circle flex align-items-center justify-content-center mr-3"
|
||||
style="background: #{role.couleurFond}; color: #{role.couleurTexte};">
|
||||
<i class="#{role.icone}"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-900 mb-1">#{role.nom}</div>
|
||||
<div class="text-600 text-sm">#{role.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Type" sortBy="#{role.type}" style="width: 15%">
|
||||
<p:tag value="#{role.typeLibelle}"
|
||||
severity="#{role.typeSeverity}"
|
||||
styleClass="font-semibold" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Permissions" style="width: 20%">
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<ui:repeat value="#{role.permissionsPrincipales}" var="perm" varStatus="status">
|
||||
<p:tag value="#{perm}"
|
||||
severity="info"
|
||||
styleClass="text-xs"
|
||||
rendered="#{status.index lt 3}" />
|
||||
</ui:repeat>
|
||||
<p:tag value="+#{role.permissionsCount - 3} autres"
|
||||
severity="secondary"
|
||||
styleClass="text-xs"
|
||||
rendered="#{role.permissionsCount gt 3}" />
|
||||
</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Utilisateurs" sortBy="#{role.nombreUtilisateurs}" style="width: 10%" styleClass="text-center">
|
||||
<div class="text-900 font-semibold">#{role.nombreUtilisateurs}</div>
|
||||
<div class="text-600 text-xs">assignés</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Statut" sortBy="#{role.statut}" style="width: 10%" styleClass="text-center">
|
||||
<p:tag value="#{role.statutLibelle}"
|
||||
severity="#{role.statutSeverity}"
|
||||
styleClass="font-semibold" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Dernière Modif." sortBy="#{role.dateModification}" style="width: 12%">
|
||||
<div class="text-900">#{role.dateModificationFormatee}</div>
|
||||
<div class="text-600 text-xs">#{role.modifiePar}</div>
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Actions" style="width: 8%" styleClass="text-center">
|
||||
<div class="flex justify-content-center gap-1">
|
||||
<p:commandButton icon="pi pi-eye"
|
||||
styleClass="p-button-sm p-button-rounded"
|
||||
style="background-color: #17a2b8 !important; border-color: #17a2b8 !important; color: white !important;"
|
||||
title="Voir les détails"
|
||||
action="#{rolesBean.voirRole(role)}"
|
||||
onclick="PF('detailsRoleDialog').show()" />
|
||||
<p:commandButton icon="pi pi-pencil"
|
||||
styleClass="p-button-sm p-button-rounded"
|
||||
style="background-color: #ffc107 !important; border-color: #ffc107 !important; color: #212529 !important;"
|
||||
title="Modifier"
|
||||
action="#{rolesBean.modifierRole(role)}"
|
||||
onclick="PF('modifierRoleDialog').show()"
|
||||
rendered="#{role.modifiable}" />
|
||||
<p:commandButton icon="pi pi-users"
|
||||
styleClass="p-button-sm p-button-rounded"
|
||||
style="background-color: #28a745 !important; border-color: #28a745 !important; color: white !important;"
|
||||
title="Gérer les utilisateurs"
|
||||
action="#{rolesBean.gererUtilisateurs(role)}"
|
||||
onclick="PF('utilisateursRoleDialog').show()" />
|
||||
<p:commandButton icon="pi pi-trash"
|
||||
styleClass="p-button-sm p-button-rounded"
|
||||
style="background-color: #dc3545 !important; border-color: #dc3545 !important; color: white !important;"
|
||||
title="Supprimer"
|
||||
rendered="#{role.supprimable}">
|
||||
<p:confirm message="Êtes-vous sûr de vouloir supprimer ce rôle ?"
|
||||
icon="pi pi-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
</div>
|
||||
</p:column>
|
||||
</p:dataTable>
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dialog Nouveau Rôle -->
|
||||
<p:dialog id="nouveauRoleDialog"
|
||||
widgetVar="nouveauRoleDialog"
|
||||
header="Créer un Nouveau Rôle"
|
||||
modal="true"
|
||||
width="600"
|
||||
height="500"
|
||||
styleClass="surface-0">
|
||||
<h:form id="nouveauRoleForm">
|
||||
<div class="ui-fluid">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12">
|
||||
<label for="nomRole" class="block text-900 font-semibold mb-2">Nom du Rôle *</label>
|
||||
<p:inputText id="nomRole"
|
||||
value="#{rolesBean.nouveauRole.nom}"
|
||||
required="true"
|
||||
placeholder="Ex: Gestionnaire Comptabilité"
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
<div class="field col-12">
|
||||
<label for="descriptionRole" class="block text-900 font-semibold mb-2">Description</label>
|
||||
<p:inputTextarea id="descriptionRole"
|
||||
value="#{rolesBean.nouveauRole.description}"
|
||||
rows="3"
|
||||
placeholder="Description des responsabilités de ce rôle..."
|
||||
styleClass="w-full" />
|
||||
</div>
|
||||
<div class="field col-6">
|
||||
<label for="typeRole" class="block text-900 font-semibold mb-2">Type de Rôle *</label>
|
||||
<p:selectOneMenu id="typeRole"
|
||||
value="#{rolesBean.nouveauRole.type}"
|
||||
required="true"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="Sélectionner..." itemValue="" />
|
||||
<f:selectItem itemLabel="Rôle Personnalisé" itemValue="PERSONNALISE" />
|
||||
<f:selectItem itemLabel="Rôle Temporaire" itemValue="TEMPORAIRE" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="field col-6">
|
||||
<label for="iconeRole" class="block text-900 font-semibold mb-2">Icône</label>
|
||||
<p:selectOneMenu id="iconeRole"
|
||||
value="#{rolesBean.nouveauRole.icone}"
|
||||
styleClass="w-full">
|
||||
<f:selectItem itemLabel="pi pi-users" itemValue="pi pi-users" />
|
||||
<f:selectItem itemLabel="pi pi-user-edit" itemValue="pi pi-user-edit" />
|
||||
<f:selectItem itemLabel="pi pi-cog" itemValue="pi pi-cog" />
|
||||
<f:selectItem itemLabel="pi pi-briefcase" itemValue="pi pi-briefcase" />
|
||||
<f:selectItem itemLabel="pi pi-shield" itemValue="pi pi-shield" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="field col-12">
|
||||
<label class="block text-900 font-semibold mb-2">Permissions</label>
|
||||
<p:selectManyCheckbox id="permissions"
|
||||
value="#{rolesBean.nouveauRole.permissions}"
|
||||
layout="grid"
|
||||
columns="2">
|
||||
<f:selectItems value="#{rolesBean.permissionsDisponibles}"
|
||||
var="perm"
|
||||
itemLabel="#{perm.libelle}"
|
||||
itemValue="#{perm.code}" />
|
||||
</p:selectManyCheckbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-content-end gap-2 mt-4">
|
||||
<p:commandButton value="Annuler"
|
||||
styleClass="p-button-outlined"
|
||||
onclick="PF('nouveauRoleDialog').hide()"
|
||||
type="button" />
|
||||
<p:commandButton value="Créer le Rôle"
|
||||
styleClass="p-button-success"
|
||||
icon="pi pi-save"
|
||||
action="#{rolesBean.creerRole}"
|
||||
update="@form :tableauForm:tableauRoles"
|
||||
oncomplete="if (args && !args.validationFailed) PF('nouveauRoleDialog').hide()" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
<!-- Dialog Détails Rôle -->
|
||||
<p:dialog id="detailsRoleDialog"
|
||||
widgetVar="detailsRoleDialog"
|
||||
header="#{rolesBean.roleSelectionne.nom} - Détails"
|
||||
modal="true"
|
||||
width="700"
|
||||
height="600"
|
||||
styleClass="surface-0">
|
||||
<div class="ui-fluid">
|
||||
<div class="grid" rendered="#{rolesBean.roleSelectionne != null}">
|
||||
<div class="col-12">
|
||||
<div class="surface-100 border-round-lg p-4 mb-4">
|
||||
<div class="flex align-items-center mb-3">
|
||||
<div class="w-4rem h-4rem border-circle flex align-items-center justify-content-center mr-4"
|
||||
style="background: #{rolesBean.roleSelectionne.couleurFond}; color: #{rolesBean.roleSelectionne.couleurTexte};">
|
||||
<i class="#{rolesBean.roleSelectionne.icone} text-2xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-900 font-bold text-xl mb-1">#{rolesBean.roleSelectionne.nom}</h3>
|
||||
<p class="text-600 mb-2">#{rolesBean.roleSelectionne.description}</p>
|
||||
<div class="flex gap-2">
|
||||
<p:tag value="#{rolesBean.roleSelectionne.typeLibelle}" severity="#{rolesBean.roleSelectionne.typeSeverity}" />
|
||||
<p:tag value="#{rolesBean.roleSelectionne.statutLibelle}" severity="#{rolesBean.roleSelectionne.statutSeverity}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-12 lg:col-6">
|
||||
<h4 class="text-900 font-semibold mb-3">Permissions Accordées</h4>
|
||||
<div class="surface-100 border-round p-3" style="max-height: 300px; overflow-y: auto;">
|
||||
<ui:repeat value="#{rolesBean.roleSelectionne.permissionsDetaillees}" var="perm">
|
||||
<div class="flex align-items-center mb-2">
|
||||
<i class="pi pi-check text-green-500 mr-2"></i>
|
||||
<span class="text-900">#{perm.libelle}</span>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 lg:col-6">
|
||||
<h4 class="text-900 font-semibold mb-3">Utilisateurs Assignés</h4>
|
||||
<div class="surface-100 border-round p-3" style="max-height: 300px; overflow-y: auto;">
|
||||
<ui:repeat value="#{rolesBean.roleSelectionne.utilisateursAssignes}" var="user">
|
||||
<div class="flex align-items-center mb-2">
|
||||
<i class="pi pi-user text-blue-500 mr-2"></i>
|
||||
<span class="text-900">#{user.nom} #{user.prenom}</span>
|
||||
</div>
|
||||
</ui:repeat>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</p:dialog>
|
||||
|
||||
</div>
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
@@ -0,0 +1,166 @@
|
||||
<!DOCTYPE html>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/templates/main-template.xhtml">
|
||||
|
||||
<ui:define name="title">Catalogue des Types d'Organisation</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<h:form id="formTypes">
|
||||
<p:messages id="messages" showDetail="true" closable="true" />
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="mb-1">Catalogue des Types d'Organisation</h5>
|
||||
<span class="text-600">
|
||||
Gestion centrale des types utilisés par les organisations (Lions Club, Association, Coopérative, ...).
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<p:commandButton value="Nouveau type"
|
||||
icon="pi pi-plus"
|
||||
styleClass="ui-button-success"
|
||||
actionListener="#{typeOrganisationsAdminBean.preparerNouveauType}"
|
||||
update=":formTypes:dlgType"
|
||||
oncomplete="PF('dlgType').show();" />
|
||||
<p:commandButton value="Rafraîchir"
|
||||
icon="pi pi-refresh"
|
||||
styleClass="ui-button-secondary ml-2"
|
||||
actionListener="#{typeOrganisationsAdminBean.chargerTypes}"
|
||||
update="@form" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<p:dataTable id="dtTypes"
|
||||
value="#{typeOrganisationsAdminBean.types}"
|
||||
var="type"
|
||||
paginator="true"
|
||||
rows="20"
|
||||
rowsPerPageTemplate="10,20,50"
|
||||
paginatorPosition="bottom"
|
||||
emptyMessage="Aucun type trouvé">
|
||||
|
||||
<p:column headerText="Code" sortBy="#{type.code}" style="width: 160px;">
|
||||
<h:outputText value="#{type.code}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Libellé" sortBy="#{type.libelle}">
|
||||
<h:outputText value="#{type.libelle}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Description">
|
||||
<h:outputText value="#{type.description}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Ordre" style="width: 80px; text-align: center;">
|
||||
<h:outputText value="#{type.ordreAffichage}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Actif" style="width: 90px; text-align: center;">
|
||||
<p:tag value="#{type.actif ? 'Actif' : 'Inactif'}"
|
||||
severity="#{type.actif ? 'success' : 'danger'}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Actions" style="width: 140px; text-align: center;">
|
||||
<p:commandButton icon="pi pi-pencil"
|
||||
title="Modifier"
|
||||
styleClass="ui-button-rounded ui-button-warning mr-2"
|
||||
update=":formTypes:dlgType"
|
||||
actionListener="#{typeOrganisationsAdminBean.setTypeSelectionne(type)}"
|
||||
oncomplete="PF('dlgType').show();" />
|
||||
|
||||
<p:commandButton icon="pi pi-ban"
|
||||
title="Désactiver"
|
||||
styleClass="ui-button-rounded ui-button-secondary"
|
||||
update="@form"
|
||||
actionListener="#{typeOrganisationsAdminBean.desactiverType(type.id)}">
|
||||
<p:confirm header="Confirmation"
|
||||
message="Désactiver ce type d'organisation ?"
|
||||
icon="pi pi-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
</p:column>
|
||||
</p:dataTable>
|
||||
</div>
|
||||
|
||||
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade" responsive="true" width="350">
|
||||
<p:commandButton value="Non" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
|
||||
onclick="PF('confirmDialog').hide()" />
|
||||
<p:commandButton value="Oui" type="button" styleClass="ui-button-danger" icon="pi pi-check" />
|
||||
</p:confirmDialog>
|
||||
|
||||
<!-- Dialogue création / édition type -->
|
||||
<p:dialog id="dlgType"
|
||||
widgetVar="dlgType"
|
||||
header="Type d'Organisation"
|
||||
modal="true"
|
||||
resizable="false"
|
||||
responsive="true"
|
||||
width="600">
|
||||
|
||||
<div class="ui-fluid">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12 md:col-4">
|
||||
<p:outputLabel for="code" value="Code *" />
|
||||
<p:inputText id="code"
|
||||
value="#{typeOrganisationsAdminBean.typeCourant.code}"
|
||||
required="true"
|
||||
requiredMessage="Code: une donnée est requise."
|
||||
maxlength="50" />
|
||||
<p:message for="code" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-8">
|
||||
<p:outputLabel for="libelle" value="Libellé *" />
|
||||
<p:inputText id="libelle"
|
||||
value="#{typeOrganisationsAdminBean.typeCourant.libelle}"
|
||||
required="true"
|
||||
requiredMessage="Libellé: une donnée est requise."
|
||||
maxlength="150" />
|
||||
<p:message for="libelle" />
|
||||
</div>
|
||||
<div class="field col-12">
|
||||
<p:outputLabel for="description" value="Description" />
|
||||
<p:inputTextarea id="description"
|
||||
value="#{typeOrganisationsAdminBean.typeCourant.description}"
|
||||
rows="3"
|
||||
maxlength="500" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<p:outputLabel for="ordre" value="Ordre d'affichage" />
|
||||
<p:inputNumber id="ordre"
|
||||
value="#{typeOrganisationsAdminBean.typeCourant.ordreAffichage}"
|
||||
decimalPlaces="0"
|
||||
minValue="0" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<p:selectBooleanCheckbox id="actif"
|
||||
value="#{typeOrganisationsAdminBean.typeCourant.actif}" />
|
||||
<p:outputLabel for="actif" value="Actif" styleClass="ml-2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<f:facet name="footer">
|
||||
<p:commandButton value="Annuler"
|
||||
icon="pi pi-times"
|
||||
onclick="PF('dlgType').hide();"
|
||||
styleClass="ui-button-secondary" />
|
||||
|
||||
<p:commandButton value="Enregistrer"
|
||||
icon="pi pi-check"
|
||||
process="@form"
|
||||
update=":formTypes:dtTypes :formTypes:messages"
|
||||
actionListener="#{typeOrganisationsAdminBean.enregistrerType}"
|
||||
oncomplete="if(!args.validationFailed) PF('dlgType').hide();" />
|
||||
</f:facet>
|
||||
</p:dialog>
|
||||
</h:form>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user