This commit is contained in:
kenza 2026-08-05 13:35:11 +01:00
parent 5197187cf7
commit e43c82ea9d
20 changed files with 1214 additions and 472 deletions

View File

@ -4,20 +4,26 @@
*/
package com.triz.trizservice.bean;
import com.triz.trizservice.modeles.Centre;
import com.triz.trizservice.modeles.ServiceGroupe;
import com.triz.trizservice.modeles.ServiceIncrementation;
import com.triz.trizservice.modeles.ServiceMember;
import com.triz.trizservice.modeles.ServiceUser;
import com.triz.trizservice.modeles.ServicehistoriqueConnection;
import com.triz.trizservice.modeles.ServiceHistoriqueManipulation;
import com.triz.trizservice.modeles.ServiceUserCentre;
import com.triz.trizservice.service.TransactionService;
import com.triz.util.UtilContext;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.faces.event.AjaxBehaviorEvent;
/**
*
@ -38,6 +44,7 @@ public class FormUserBean {
private List<ServiceHistoriqueManipulation> listehistManipulation = new ArrayList<>();
private List<ServiceGroupe> listeGroups;
private ServiceMember member;
private Centre currentCenter;
@Autowired
public TransactionService service;
@ -50,6 +57,7 @@ public class FormUserBean {
System.out.println("//--------------init()FormUserBean ");
user = context.getCurrentUser();
listeGroups = service.getAllGroups();
currentCenter = context.getCurrentEtablissement();
if (modifier != null) {
if (modifier.equals("true")) {
@ -63,6 +71,8 @@ public class FormUserBean {
System.out.println("Utilisateur" + userSelected);
listeHistCnx = service.getListHistoriqueConnectionByUsers(userSelected);
listehistManipulation = service.getListHistoriqueManipulationByUsersByEntreprise(userSelected);
confirmationMp = userSelected.getUserpw();
context.saveNewManipulation("User", userSelected.getUserid(), "consulter user", new Date(), new Date(), user, "", "");
} else {
if (canEdit) {
isNew = true;
@ -79,17 +89,68 @@ public class FormUserBean {
}
public String saveUser() {
if (userSelected.getUserpw() != null && !userSelected.getUserpw().equals(confirmationMp)) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Les mots de passe ne correspondent pas", null));
return null;
}
if (isNew) {
context.saveNewManipulation("User", userSelected.getUserid(), "Ajouter user", new Date(), new Date(), user, "", "");
} else {
if (canEdit) {
ServiceMember oldMember = service.getGroupByUser(user);
if (member.getFkGroupe().getId() == oldMember.getFkGroupe().getId()) {
context.saveNewManipulation("User", userSelected.getUserid(), "modifier groupe user", new Date(), new Date(), user, oldMember.getFkGroupe().getNomGroupe(),
member.getFkGroupe().getNomGroupe());
}
ServiceUser oldUser = service.getUserById(user1);
if (userSelected.getUserpw().equalsIgnoreCase(oldUser.getUserpw())) {
context.saveNewManipulation("User", userSelected.getUserid(), "modifier pw user", new Date(), new Date(), user, "",
"");
}
if (userSelected.getActif().equalsIgnoreCase(oldUser.getActif())) {
context.saveNewManipulation("User", userSelected.getUserid(), "modifier Statut user", new Date(), new Date(), user, oldUser.getActif(),
userSelected.getActif());
}
if (userSelected.getPrenom().equalsIgnoreCase(oldUser.getPrenom())) {
context.saveNewManipulation("User", userSelected.getUserid(), "modifier prenom user", new Date(), new Date(), user, oldUser.getPrenom(),
userSelected.getPrenom());
}
if (userSelected.getNom().equalsIgnoreCase(oldUser.getNom())) {
context.saveNewManipulation("User", userSelected.getUserid(), "modifier nom user", new Date(), new Date(), user, oldUser.getNom(),
userSelected.getNom());
}
if (userSelected.getTelephone().equalsIgnoreCase(oldUser.getTelephone())) {
context.saveNewManipulation("User", userSelected.getUserid(), "modifier telephone user", new Date(), new Date(), user, oldUser.getTelephone(),
userSelected.getTelephone());
}
if (userSelected.getMail().equalsIgnoreCase(oldUser.getMail())) {
context.saveNewManipulation("User", userSelected.getUserid(), "modifier mail user", new Date(), new Date(), user, oldUser.getMail(),
userSelected.getMail());
}
context.saveNewManipulation("User", userSelected.getUserid(), "modifier user", new Date(), new Date(), user, "", "");
}
}
service.saveUser(userSelected);
member.setFkUser(userSelected);
ServiceUserCentre services = new ServiceUserCentre();
services.setFkCentre(currentCenter);
services.setFkUser(userSelected);
service.save(services);
service.saveMembership(member);
return voirUser();
}
public String voirUser() {
System.out.println("isNew " + isNew);
System.out.println("canEdit " + canEdit);
if (!isNew) {
if (!canEdit) {
return "list.xhtml?faces-redirect=true";
} else {
return "form.xhtml?faces-redirect=true&user1=" + userSelected.getUserid();
}
} else {
@ -188,4 +249,49 @@ public class FormUserBean {
public void setMember(ServiceMember member) {
this.member = member;
}
public String deleteUser() {
if (userSelected != null) {
userSelected.setActif("false");
// TODO: adapte l'appel selon ton DAO/service existant, ex:
service.saveUser(userSelected);
// ou si tu utilises un pattern différent (ex: Hibernate Criteria/session direct) :
// userDao.update(userSelected);
context.saveNewManipulation("User", userSelected.getUserid(), "Supprimer user", new Date(), new Date(), user, "", "");
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"L'utilisateur a été supprimé avec succès", null));
return voirUser();
}
return null;
}
private String confirmationMp;
public String getConfirmationMp() {
return confirmationMp;
}
public void setConfirmationMp(String confirmationMp) {
this.confirmationMp = confirmationMp;
}
public void verifierConfirmationMp(AjaxBehaviorEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
String clientId = event.getComponent().getClientId(context);
if (confirmationMp == null || confirmationMp.isEmpty()) {
return;
}
String pw = userSelected.getUserpw();
if (pw == null || !pw.equals(confirmationMp)) {
context.addMessage(clientId,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Les mots de passe ne correspondent pas", null));
confirmationMp = null;
}
}
}

View File

@ -4,7 +4,10 @@
*/
package com.triz.trizservice.bean;
import com.triz.trizservice.modeles.ServiceGroupe;
import com.triz.trizservice.modeles.ServiceMember;
import com.triz.trizservice.modeles.ServiceUser;
import com.triz.trizservice.security.impl.UserPresence;
import com.triz.trizservice.service.TransactionService;
import com.triz.util.UtilContext;
import java.util.List;
@ -17,10 +20,10 @@ import org.springframework.stereotype.Component;
*
* @author Asma
*/
@Component("userBean")
@Scope("view")
public class UserBean {
private ServiceUser user;
private ServiceUser userSelected;
private List<ServiceUser> listeUser;
@ -35,7 +38,7 @@ public class UserBean {
System.out.println("//--------------init()ClientBean ");
user = context.getCurrentUser();
listeUser = service.getAllUsers();
System.out.println("listeClient: "+listeUser);
System.out.println("listeClient: " + listeUser);
}
public String ajouterUser() {
@ -69,4 +72,26 @@ public class UserBean {
public void setListeUser(List<ServiceUser> listeUser) {
this.listeUser = listeUser;
}
public String getGroupeByUser(ServiceUser user) {
if (user == null) {
return null;
}
ServiceMember member = service.getGroupByUser(user);
return member.getFkGroupe().getNomGroupe();
}
public String isUserConnected(ServiceUser user) {
if ("true".equalsIgnoreCase(user.getActif())) {
if (UserPresence.isConnected(user.getUserid()) == true) {
return "connected";
} else {
return "disconnected";
}
} else {
return "inactif";
}
}
}

View File

@ -21,21 +21,24 @@ import org.springframework.stereotype.Component;
*/
@FacesConverter("groupeConverter")
@Component
public class GroupeConverter implements Converter{
public class GroupeConverter implements Converter {
@Autowired
protected transient TransactionService service;
@Override
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
try {
System.out.println("service "+ service);
UUID id = UUID.fromString(value);
return service.getGroupsById(id);
} catch (NumberFormatException e) {
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Entreprise n'existe pas.");
if (value == null || value.trim().isEmpty()) {
return null;
}
return null;
try {
UUID id = UUID.fromString(value);
return service.getGroupsById(id);
} catch (IllegalArgumentException e) {
return null;
}
}
@Override

View File

@ -39,7 +39,7 @@ public class ServiceMember implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@GeneratedValue
@Basic(optional = false)
@Column(name = "id")
private UUID id;

View File

@ -9,6 +9,7 @@ import java.util.UUID;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
@ -34,6 +35,7 @@ public class ServiceUserCentre implements Serializable {
@Id
@Basic(optional = false)
@NotNull
@GeneratedValue
@Column(name = "id")
private UUID id;
@JoinColumn(name = "fk_centre", referencedColumnName = "id")

View File

@ -61,6 +61,9 @@ public class ServicehistoriqueConnection implements Serializable {
@JoinColumn(name = "fk_centre", referencedColumnName = "id")
@ManyToOne
private Centre fkCentre;
@Column(name = "last_activity")
@Temporal(TemporalType.TIMESTAMP)
private Date lastActivity;
public ServicehistoriqueConnection() {
}
@ -142,6 +145,12 @@ public class ServicehistoriqueConnection implements Serializable {
this.fkCentre = fkCentre;
}
public Date getLastActivity() {
return lastActivity;
}
public void setLastActivity(Date lastActivity) {
this.lastActivity = lastActivity;
}
}

View File

@ -18,11 +18,18 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.core.Authentication;
import com.triz.util.UtilURL;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
/**
*
@ -31,6 +38,8 @@ import org.springframework.stereotype.Service;
@Service
public class CostumSuccesHandler extends SavedRequestAwareAuthenticationSuccessHandler {
private HttpServletRequest requestTest;
@Autowired
private TransactionService transactionService;
@ -44,27 +53,45 @@ public class CostumSuccesHandler extends SavedRequestAwareAuthenticationSuccessH
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
requestTest = request;
setDefaultTargetUrl("/" + multiEtablissement());
super.onAuthenticationSuccess(request, response, authentication);
}
private void saveConnection(ServiceUser user, Centre etablissement) {
private void saveConnection(ServiceUser user, Centre etablissement) throws UnknownHostException {
ServicehistoriqueConnection his = new ServicehistoriqueConnection();
his.setId(UUID.randomUUID());
his.setFkUser(user);
his.setDate(new Date());
his.setHeur(new Date());
his.setAdresseIp("");
his.setLastActivity(new Date());
String ip = InetAddress.getLocalHost().getHostAddress();
his.setAdresseIp(ip);
his.setFkCentre(etablissement);
transactionService.save(his);
RequestContextHolder.currentRequestAttributes()
.setAttribute(
"HISTORIQUE_CONNEXION_ID",
his.getId(),
RequestAttributes.SCOPE_SESSION);
}
public String multiEtablissement() {
public String multiEtablissement() throws UnknownHostException {
// useDistribution = UtilGetParametre.useTrizDistribution();
ServiceUser user = context.getCurrentUser();
UserPresence.connect(user.getUserid());
requestTest.getSession().setAttribute(
"CONNECTED_USER",
user.getUserid());
System.out.println("user 22"
+ UserPresence.isConnected(user.getUserid())
);
System.out.println("-------------------- multi etablissement");
List<Centre> listUserEtab = transactionService.getAllStockEtablissementFromUsersEtablissementByUser(user);
System.out.println("-------------------- listUserEtab " + listUserEtab);

View File

@ -0,0 +1,27 @@
package com.triz.trizservice.security.impl;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
Object userId
= se.getSession().getAttribute("CONNECTED_USER");
if (userId != null) {
UserPresence.disconnect(userId.toString());
System.out.println(
"User disconnected : " + userId
);
}
}
}

View File

@ -0,0 +1,22 @@
package com.triz.trizservice.security.impl;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class UserPresence {
private static final Set<String> CONNECTED_USERS
= ConcurrentHashMap.newKeySet();
public static void connect(String userId) {
CONNECTED_USERS.add(userId);
}
public static void disconnect(String userId) {
CONNECTED_USERS.remove(userId);
}
public static boolean isConnected(String userId) {
return CONNECTED_USERS.contains(userId);
}
}

View File

@ -17,6 +17,7 @@ import com.triz.trizservice.modeles.ServiceHistoriqueManipulation;
import com.triz.trizservice.modeles.ServiceHistoriqueManipulation;
import com.triz.trizservice.modeles.ServiceUserCentre;
import com.triz.trizservice.modeles.Wilaya;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
@ -116,4 +117,8 @@ public interface DaoService {
public ServiceFonctiongroupe getFonctiongroupeById(UUID id);
public <T extends Serializable> void save(final T object);
public <T extends Serializable> void delete(final T object);
}

View File

@ -6,7 +6,6 @@
*/
package com.triz.trizservice.service;
import com.triz.trizservice.modeles.Centre;
import com.triz.trizservice.modeles.ServiceFonctiongroupe;
import com.triz.trizservice.modeles.ServiceFonctionnaliter;
@ -19,6 +18,7 @@ import com.triz.trizservice.modeles.ServiceHistoriqueManipulation;
import com.triz.trizservice.modeles.ServiceHistoriqueManipulation;
import com.triz.trizservice.modeles.ServiceUserCentre;
import com.triz.trizservice.modeles.Wilaya;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
@ -34,7 +34,7 @@ public interface TransactionService {
public boolean isItTimeToChangePass();
public ServiceUser getUserById(String userId) ;
public ServiceUser getUserById(String userId);
public List<ServiceMember> getGroupsByUser(ServiceUser user);
@ -104,9 +104,9 @@ public interface TransactionService {
public List<Centre> getAllStockEtablissementFromUsersEtablissementByUser(ServiceUser user);
public ServiceUserCentre getAllUserCentreByCentreByUser(Centre etablissement,ServiceUser user);
public ServiceUserCentre getAllUserCentreByCentreByUser(Centre etablissement, ServiceUser user);
public List<ServiceFonctionnaliter> getFonctionServerByUsersByEtablissement(ServiceUser user,Centre etablissement);
public List<ServiceFonctionnaliter> getFonctionServerByUsersByEtablissement(ServiceUser user, Centre etablissement);
public ServicehistoriqueConnection getLastStockHistoriqueConnectionByUsers(ServiceUser user);
@ -117,4 +117,8 @@ public interface TransactionService {
public int getNbrFonctionnaliteParGroupe(ServiceGroupe groupe);
public ServiceFonctiongroupe getFonctiongroupeById(UUID id);
public <T extends Serializable> void save(final T object);
public <T extends Serializable> void delete(final T object);
}

View File

@ -17,6 +17,7 @@ import com.triz.trizservice.modeles.ServicehistoriqueConnection;
import com.triz.trizservice.modeles.ServiceHistoriqueManipulation;
import com.triz.trizservice.modeles.ServiceUserCentre;
import com.triz.trizservice.modeles.Wilaya;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@ -242,7 +243,7 @@ public class DaoServiceImpl implements DaoService {
@Override
public List<ServiceHistoriqueManipulation> getListHistoriqueManipulationByUsersByEntreprise(ServiceUser user) {
return getCurrentSession()
.createQuery("select e from ServiceHistoriqueManipulation e where e.fkManipulateur = :user", ServiceHistoriqueManipulation.class)
.createQuery("select e from ServiceHistoriqueManipulation e where e.fkUser = :user", ServiceHistoriqueManipulation.class)
.setParameter("user", user)
.list();
}
@ -296,12 +297,23 @@ public class DaoServiceImpl implements DaoService {
@Override
public int getNbrFonctionnaliteParGroupe(ServiceGroupe groupe) {
Long count = (Long) getCurrentSession().createQuery("select count(m) from ServiceGroupe m, ServiceFonctiongroupe f where m.id=f.fkGroupe.id and m.id=:groupe ").setParameter("groupe", groupe.getId()).uniqueResult();
Long count = (Long) getCurrentSession().createQuery("select count(m) from ServiceGroupe m, ServiceFonctiongroupe f where m.id=f.fkGroupe.id and m.id=:groupe ").setParameter("groupe", groupe.getId()).uniqueResult();
return count.intValue();
}
@Override
public ServiceFonctiongroupe getFonctiongroupeById(UUID id) {
return (ServiceFonctiongroupe)getCurrentSession().createQuery("select m from ServiceFonctiongroupe m where m.id=:id ").setParameter("id", id).setMaxResults(1).uniqueResult();
return (ServiceFonctiongroupe) getCurrentSession().createQuery("select m from ServiceFonctiongroupe m where m.id=:id ").setParameter("id", id).setMaxResults(1).uniqueResult();
}
@Override
public <T extends Serializable> void save(final T object) {
getCurrentSession().saveOrUpdate(object);
}
@Override
public <T extends Serializable> void delete(final T object) {
System.out.println("delete");
getCurrentSession().delete(object);
}
}

View File

@ -19,6 +19,7 @@ import com.triz.trizservice.modeles.ServiceUserCentre;
import com.triz.trizservice.modeles.Wilaya;
import com.triz.trizservice.service.DaoService;
import com.triz.trizservice.service.TransactionService;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
@ -263,7 +264,7 @@ public class TransactionServiceImpl implements TransactionService {
@Transactional("transactionManager")
@Override
public ServiceUserCentre getAllUserCentreByCentreByUser(Centre etablissement,ServiceUser user){
public ServiceUserCentre getAllUserCentreByCentreByUser(Centre etablissement, ServiceUser user) {
return daoService.getAllUserCentreByCentreByUser(etablissement, user);
}
@ -279,29 +280,39 @@ public class TransactionServiceImpl implements TransactionService {
return daoService.getLastHistoriqueConnectionByUsers(user);
}
@Transactional("transactionManager")
@Override
public List<Wilaya> getAllWilaya() {
return daoService.getAllWilaya();
return daoService.getAllWilaya();
}
@Transactional("transactionManager")
@Override
public int getNbrUtilisateurParGroupe(ServiceGroupe groupe) {
return daoService.getNbrUtilisateurParGroupe(groupe);
return daoService.getNbrUtilisateurParGroupe(groupe);
}
@Transactional("transactionManager")
@Override
public int getNbrFonctionnaliteParGroupe(ServiceGroupe groupe) {
return daoService.getNbrFonctionnaliteParGroupe(groupe);
return daoService.getNbrFonctionnaliteParGroupe(groupe);
}
@Transactional("transactionManager")
@Override
public ServiceFonctiongroupe getFonctiongroupeById(UUID id) {
return daoService.getFonctiongroupeById(id);
return daoService.getFonctiongroupeById(id);
}
@Transactional("transactionManager")
@Override
public <T extends Serializable> void save(T object) {
daoService.save(object);
}
@Transactional("transactionManager")
@Override
public <T extends Serializable> void delete(T object) {
daoService.delete(object);
}
}

View File

@ -585,7 +585,7 @@ SELECT 'admin', id FROM service_groupe WHERE nom_groupe = 'admin' LIMIT 1;
-- --- Fonctionnalite "User" ---
INSERT INTO service_fonctionnaliter (id,nom)
VALUES ('User','User');
VALUES ('user','User');
-- --- Droits du groupe admin sur la fonctionnalite "User" ---
INSERT INTO service_fonctiongroupe (fk_groupe, fk_fonctionnalite, can_create, can_update, can_update_date, can_delete)
@ -623,3 +623,6 @@ INSERT INTO service_fonctionnaliter (id, nom) VALUES
ALTER TABLE service_fonctiongroupe
ADD COLUMN can_see boolean;
INSERT INTO service_fonctionnaliter (id, nom) VALUES
('modifier_groupe', 'Modifier le groupe');

View File

@ -9,7 +9,6 @@
<h:form id="layoutTopbarForm">
<style>
/* MODIF : variable partagée avec menu.xhtml pour garantir un alignement exact */
:root {
--app-topbar-height: 70px;
}
@ -20,7 +19,7 @@
left: 0;
right: 0;
z-index: 500 !important;
height: var(--app-topbar-height) !important; /* MODIF : hauteur fixe et explicite, plus dépendante du contenu */
height: var(--app-topbar-height) !important;
display: flex;
align-items: stretch;
padding: 0;
@ -30,7 +29,7 @@
#layoutTopbarForm .layout-topbar.custom-topbar .layout-topbar-left {
background-color: #0D1B2E !important;
width: var(--sidebar-width, 238px) !important;
height: 100% !important; /* MODIF : occupe toute la hauteur du topbar, plus de calcul basé sur le contenu */
height: 100% !important;
flex-shrink: 0;
position: relative;
display: flex;
@ -40,7 +39,7 @@
#layoutTopbarForm .layout-topbar.custom-topbar .layout-topbar-right {
background-color: #F8FAFC !important;
height: 100% !important; /* MODIF : idem côté droit */
height: 100% !important;
flex: 1 1 auto;
display: flex;
align-items: center;
@ -69,10 +68,6 @@
font-size: 14px;
}
/* ===================================================== */
/* ETAT MENU FERME */
/* ===================================================== */
#layoutTopbarForm .layout-topbar.custom-topbar .layout-topbar-left.topbar-left-collapsed {
width: 238px !important;
background: #F8FAFC !important;
@ -111,7 +106,6 @@
transition: color 0.3s ease;
}
/* Supprime l'espace entre le topbar left et le menu */
#layoutMenuForm .layout-menu-wrapper,
#layoutMenuForm .layout-menu-container {
margin-top: 0 !important;
@ -133,14 +127,25 @@
padding-right: 25px;
}
/* Date + notification */
/* MODIF : titre dynamique du menuitem actif, collé après le bouton toggle */
.topbar-page-title {
font-weight: 700;
font-size: 20px;
color: #0D1B2E;
font-family: 'Inter', sans-serif;
margin-right: auto;
margin-left: 35px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.topbar-actions {
display: flex;
align-items: center;
gap: 22px;
}
/* Date */
.topbar-date {
color: #94A3B8;
font-size: 14px;
@ -150,7 +155,6 @@
align-items: center;
}
/* Conteneur notification */
.notification-container {
position: relative;
display: inline-flex;
@ -160,7 +164,6 @@
transform: translateY(-8px);
}
/* Bouton notification */
.notification-button {
background: transparent !important;
border: none !important;
@ -187,7 +190,6 @@
line-height: 1 !important;
}
/* Badge */
.notification-badge {
position: absolute;
@ -220,16 +222,13 @@
<div class="layout-topbar-left ">
<!-- Logo texte -->
<div class="topbar-brand" style="display:flex; margin-left: 15px;width: 100%">
<!-- Logo -->
<div style=" align-self: center;text-align: center; width: 2.50rem;height: 2.50rem;background-color: #0D9488;border-radius: 5px; padding: 5px;margin-right: 5px">
<p:graphicImage id="app-logo" name="images/Triztech-.png" library="layout" style=" width: 1.80rem;
height: 1.80rem;filter: brightness(0) invert(3)" />
</div>
<!-- Text -->
<div class="topbar-brand-text" style="margin-top: 5px">
<div class="topbar-title" >
<span class="logo-main" style="font-size:14px;font-family: 'Inter',sans-serif;">TRIZ</span>
@ -241,20 +240,17 @@
</div>
</div>
<!-- BOUTON TOGGLE SIDEBAR -->
<a class="layout-menu-button shadow-6" data-p-ripple="true" >
<i class="pi pi-list"></i>
</a>
</div>
<div class="layout-topbar-right">
<!-- MODIF : titre du menuitem actif -->
<span id="topbarPageTitle" class="topbar-page-title"></span>
<div class="topbar-actions">
<span id="currentDateTime" class="topbar-date">
@ -278,60 +274,12 @@
<h:outputStylesheet name="styles/#{app.layout}.css" library="layout" />
<!-- OPTIONAL DEPENDENCIES -->
<h:outputStylesheet name="primeflex/primeflex.min.css" library="layout"/>
<h:outputStylesheet name="ripple/ripple.css" library="layout" rendered="#{app.ripple}" />
<h:outputStylesheet name="styles/demo.css" library="demo" />
<script>
//<![CDATA[
if (!window.__topbarToggleInit) {
window.__topbarToggleInit = true;
function syncLayoutToSidebar() {
var sidebar = document.querySelector('#layoutTopbarForm .layout-topbar-left');
if (!sidebar)
return;
var realWidth = sidebar.getBoundingClientRect().width;
}
window.syncLayoutToSidebar = syncLayoutToSidebar;
document.addEventListener('click', function (e) {
var btn = e.target.closest ? e.target.closest('#layoutTopbarForm .layout-menu-button') : null;
if (!btn)
return;
var topbarLeft = document.querySelector('#layoutTopbarForm .layout-topbar-left');
if (!topbarLeft)
return;
topbarLeft.classList.toggle('topbar-left-collapsed');
document.body.classList.toggle('app-sidebar-collapsed');
var collapsed = document.body.classList.contains('app-sidebar-collapsed');
// MODIF : recherche plus large de l'icône (au cas où btn ne serait pas le bon conteneur)
var icon = btn.querySelector('i.pi') || document.querySelector('#layoutTopbarForm .layout-menu-button i.pi');
console.log('[toggle-debug] collapsed =', collapsed, '| icon trouvé =', !!icon, '| classes avant =', icon ? icon.className : 'N/A');
[0, 100, 200, 320].forEach(function (delay) {
setTimeout(syncLayoutToSidebar, delay);
});
}, true);
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', syncLayoutToSidebar);
} else {
syncLayoutToSidebar();
}
window.addEventListener('resize', syncLayoutToSidebar);
} else {
console.warn('[toggle-debug] __topbarToggleInit déjà à true -> ce script ne s\'est PAS réattaché (normal si tu n\'as pas rechargé la page, ANORMAL si tu viens de recharger et vois quand même ce warning)');
}
function updateDateTime() {
var now = new Date();
var options = {weekday: 'long', day: 'numeric', month: 'long', year: 'numeric'};
@ -343,6 +291,54 @@
}
updateDateTime();
setInterval(updateDateTime, 60000);
/* MODIF : matching par dossier d'URL au lieu de la classe active-menuitem,
pour que le titre reste affiché sur form.xhtml comme sur list.xhtml */
function updateTopbarPageTitle() {
var titleEl = document.getElementById('topbarPageTitle');
if (!titleEl)
return;
var currentDir = window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/'));
var links = document.querySelectorAll('#layoutMenuForm .layout-menu a[href]');
var matchedLink = null;
links.forEach(function (link) {
if (matchedLink)
return;
var linkPath = link.getAttribute('href');
if (!linkPath || linkPath.indexOf('javascript:') === 0)
return;
var linkUrl;
try {
linkUrl = new URL(linkPath, window.location.origin);
} catch (e) {
return;
}
var linkDir = linkUrl.pathname.substring(0, linkUrl.pathname.lastIndexOf('/'));
if (linkDir === currentDir) {
matchedLink = link;
}
});
if (matchedLink) {
var textEl = matchedLink.querySelector('.layout-menuitem-text') || matchedLink;
titleEl.textContent = textEl.textContent.trim();
} else {
titleEl.textContent = '';
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', updateTopbarPageTitle);
} else {
updateTopbarPageTitle();
}
//]]>
</script>
</h:form>

View File

@ -118,6 +118,11 @@ version="3.1">-->
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>
com.triz.trizservice.security.impl.SessionListener
</listener-class>
</listener>
<mime-mapping>
<extension>ttf</extension>
<mime-type>application/font-sfnt</mime-type>

View File

@ -145,10 +145,9 @@
<div style="display: flex; gap: 5px;">
<p:commandButton value="#{msg['distribution.page.supprimer']}" icon="pi pi-trash"
rendered="#{formGroupBean.canEdit and !formGroupBean.isNew}"
action="#{formGroupBean.supprimeGroupe()}" ajax="false"
styleClass="ui-button-danger"
rendered="#{utilControleAccess.isshowPrivilegeRemove('groupes')}"/>
rendered="#{utilControleAccess.isshowPrivilegeRemove('groupes') and formGroupBean.canEdit and !formGroupBean.isNew}"/>
<p:commandButton value="#{msg['distribution.page.enregistrer']}" icon="pi pi-save"
rendered="#{formGroupBean.canEdit}"
@ -156,10 +155,9 @@
styleClass="ui-button-success" />
<p:commandButton value="#{msg['distribution.page.modifier']}" icon="pi pi-pencil"
rendered="#{!formGroupBean.canEdit}"
action="#{formGroupBean.editGroupe()}"
styleClass="modifier-btn"
rendered="#{utilControleAccess.isshowPrivilegeUpdate('groupes')}"/>
rendered="#{utilControleAccess.isshowPrivilegeUpdate('groupes') and !formGroupBean.canEdit}"/>
</div>
</div>

View File

@ -24,7 +24,7 @@
display: flex !important;
flex-direction: column !important;
justify-content: center !important;
min-height: calc(100vh - 350px) !important; /* ajuste selon hauteur topbar+breadcrumb */
min-height: calc(100vh - 200px) !important; /* ajuste selon hauteur topbar+breadcrumb */
}
/* Conteneur tabview */
@ -145,7 +145,7 @@
<div class="card">
<p:dataTable id="dataTable" var="groupe"
rows="30" paginator="true" draggableColumns="true"
rows="5" paginator="true" draggableColumns="true"
value="#{groupBean.listeGroupe}"
selection="#{groupBean.groupeSelected}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"

View File

@ -3,6 +3,8 @@
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
template="/WEB-INF/layout/template.xhtml">
<f:metadata>
<f:viewParam name="user1" value="#{formUserBean.user1}" />
@ -14,252 +16,591 @@
<ui:define name="content">
#{formUserBean.init()}
<h:form>
<div class="card">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;">
<div style="width: 150px;">
<p:commandButton value="#{msg['distribution.page.etatVGlobal.retour']}" icon="pi pi-arrow-left"
action="#{formUserBean.voirUser()}" ajax="false"
styleClass="ui-button-primary" />
</div>
<style>
<div style=" text-align: right; display: flex; gap: 5px;">
<p:commandButton value="#{msg['distribution.page.enregistrer']}" icon="pi pi-save"
rendered="#{formUserBean.canEdit}"
action="#{formUserBean.saveUser()}"
update="@form"
styleClass="ui-button-success" />
.user-card-profile,
.user-card-right {
border-radius: 16px !important;
box-shadow: 0 1px 4px rgba(0,0,0,0.08) !important;
border: 1px solid #E5E7EB !important;
}
.user-card-profile .ui-panel-content,
.user-card-right .ui-panel-content {
border-radius: 16px !important;
height: 100%;
}
<p:commandButton value="#{msg['distribution.page.modifier']}" icon="pi pi-pencil"
rendered="#{!formUserBean.canEdit}"
action="#{formUserBean.editUser()}"
styleClass="ui-button-primary" />
</div>
.user-cards-row {
display: flex;
align-items: stretch;
gap: 1.5%;
margin-bottom: 1rem;
margin-top: 1rem;
}
.user-card-profile-wrapper {
width: 33%;
}
.user-card-right-wrapper {
width: 65.5%;
}
.user-avatar {
width: 90px;
height: 90px;
border-radius: 50%;
background-color: #DBEAFE;
color: #0D9488;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.8rem;
font-weight: 700;
font-family: 'Inter', sans-serif;
margin: 10px auto 18px auto;
}
</div>
<div style="width: 100%; height: 100%; display: flex; margin-bottom: 1px;" >
<p:card id="card" style="width: 35%; height: 750px; text-align: center; max-height: 100%" rendered="#{!formUserBean.canEdit}">
<div style="flex-grow: 1; text-align: center; font-size: 1.3rem; font-weight: bold; color: #3F51B5;">
<h:outputText value="#{formUserBean.userSelected.userid}" />
.user-fullname {
text-align: center;
font-size: 1.15rem;
font-weight: 700;
color: #0D1B2E;
margin-bottom: 25px;
}
.info-block {
text-align: left;
margin-bottom: 5px;
}
.info-row {
display: flex;
align-items: center;
padding: 12px 4px;
}
.info-row i {
color: #0D9488 !important;
font-size: 1rem;
margin-right: 8px;
width: 16px;
flex-shrink: 0;
}
.info-label {
color: #0D9488 !important;
font-weight: 600 !important;
font-size: 0.98rem;
display: flex;
align-items: center;
width: 160px;
flex-shrink: 0;
}
.info-value {
color: #334155;
font-size: 1rem;
text-align: left;
}
.info-divider {
border: none;
border-top: 1px solid #E5E7EB;
margin: 10px 0;
}
.status-chip {
display: inline-block;
background-color: #0D9488;
color: #ffffff;
font-size: 0.78rem;
font-weight: 600;
padding: 3px 14px;
border-radius: 20px;
}
.status-chip.inactive {
background-color: #EF4444;
}
.btn-outline-gray,
.btn-outline-gray.ui-button {
background-color: #ffffff !important;
border: 1px solid #E2E8F0 !important;
color: #334155 !important;
border-radius: 10px !important;
padding: 8px 18px !important;
font-weight: 500 !important;
}
.btn-outline-gray:hover {
background-color: #F3F4F6 !important;
}
.btn-teal-pill,
.btn-teal-pill.ui-button {
background-color: #0D9488 !important;
border-color: #0D9488 !important;
color: #ffffff !important;
border-radius: 10px !important;
padding: 8px 18px !important;
font-weight: 500 !important;
}
.btn-teal-pill:hover {
background-color: #0b7d73 !important;
}
.btn-red-pill,
.btn-red-pill.ui-button {
background-color: #EF4444 !important;
border-color: #EF4444 !important;
color: #ffffff !important;
border-radius: 10px !important;
padding: 8px 18px !important;
font-weight: 500 !important;
}
.btn-red-pill:hover {
background-color: #DC2626 !important;
}
.form-tabs .ui-tabs-nav {
background-color: transparent !important;
border: none !important;
border-bottom: 1px solid #E5E7EB !important;
padding-left: 4px;
display: flex !important;
gap: 8px;
}
.form-tabs .ui-tabs-nav li {
margin-right: 0 !important;
padding: 0 !important;
display: flex !important;
}
.form-tabs .ui-tabs-nav li a {
background-color: transparent !important;
border: none !important;
border-radius: 8px 8px 0 0 !important;
color: #64748B !important;
font-weight: 500 !important;
padding: 10px 16px !important;
margin: 0 !important;
display: flex !important;
align-items: center !important;
height: 100% !important;
box-sizing: border-box !important;
transition: background-color 0.2s ease, color 0.2s ease;
}
.form-tabs .ui-tabs-nav li a i {
color: inherit !important;
margin-right: 6px;
}
.form-tabs .ui-tabs-nav li:not(.ui-state-active):not(.ui-tabs-selected) a:hover {
background-color: rgba(13, 148, 136, 0.1) !important;
color: #0D9488 !important;
}
.form-tabs .ui-tabs-nav li.ui-state-active a,
.form-tabs .ui-tabs-nav li.ui-tabs-selected a {
background-color: rgba(13, 148, 136, 0.12) !important;
color: #0D9488 !important;
border-bottom: 2px solid #0D9488 !important;
font-weight: 600 !important;
}
.form-tabs .ui-tabs-panel {
padding: 20px 4px !important;
}
.table-subheader {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.table-subheader-title {
font-weight: 700;
font-size: 0.95rem;
color: #0D1B2E;
}
.btn-export {
background-color: #ffffff !important;
border: 1px solid #dee2e6 !important;
color: #0D9488 !important;
}
.btn-export:hover {
background-color: #e6f5f4 !important;
border-color: #0D9488 !important;
}
.user-card-right .ui-datatable-tablewrapper table td,
.user-card-right .ui-datatable-tablewrapper table th {
vertical-align: middle !important;
text-align: center !important;
}
.edit-field-row {
display: flex;
align-items: center;
margin-bottom: 18px;
}
.edit-field-label {
color: #0D9488 !important;
font-weight: 600 !important;
font-size: 0.98rem;
width: 160px;
flex-shrink: 0;
display: flex;
align-items: center;
}
.edit-field-label i {
margin-right: 8px;
color: #0D9488 !important;
}
.edit-field-input .ui-inputtext,
.edit-field-input .ui-selectonemenu,
.edit-field-input .ui-password {
width: 100% !important;
background-color: #F3F4F6 !important;
border: 1px solid #E5E7EB !important;
border-radius: 8px !important;
}
.edit-field-input {
flex: 1;
max-width: 380px;
}
/* MODIF : message d'erreur de confirmation MP */
.ui-message-error {
color: #EF4444 !important;
font-weight: 500;
}
</style>
<!-- MODIF : id explicite ajouté au form pour fiabiliser le ciblage ajax/messages -->
<h:form id="userForm">
<div class="user-cards-row">
<div class="user-card-profile-wrapper">
<p:card id="card" styleClass="user-card-profile" style="height: 100%;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;">
<div style="width: 150px;">
<p:commandButton value="#{msg['distribution.page.etatVGlobal.retour']}" icon="pi pi-arrow-left"
action="#{formUserBean.voirUser()}" ajax="false"
styleClass="btn-outline-gray" />
</div>
<div style=" text-align: right; display: flex; gap: 8px;">
<p:commandButton value="#{msg['distribution.page.supprimer']}" icon="pi pi-trash"
action="#{formUserBean.deleteUser()}"
rendered="#{utilControleAccess.isshowPrivilegeRemove('user') and formUserBean.canEdit}"
styleClass="btn-red-pill" />
<p:commandButton value="#{msg['distribution.page.enregistrer']}" icon="pi pi-save"
rendered="#{formUserBean.canEdit}"
action="#{formUserBean.saveUser()}"
update="@form"
styleClass="btn-teal-pill" />
<p:commandButton value="#{msg['distribution.page.modifier']}" icon="pi pi-pencil"
rendered="#{!formUserBean.canEdit and utilControleAccess.isshowPrivilegeUpdate('user')}"
action="#{formUserBean.editUser()}"
styleClass="btn-teal-pill" />
</div>
</div>
<div class="user-avatar">
#{fn:substring(formUserBean.userSelected.nom,0,1)}#{fn:substring(formUserBean.userSelected.prenom,0,1)}
</div>
<p:panelGrid columns="2" style="margin-top: 30px; text-align:left">
<p:column>
<i class="pi pi-user" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['distribution.page.user.nom']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:outputLabel id="id" value="#{formUserBean.userSelected.nom}" />
</p:column>
<!-- ===================== MODE CONSULTATION ===================== -->
<h:panelGroup rendered="#{!formUserBean.canEdit}">
<div class="user-fullname">
<h:outputText value="#{formUserBean.userSelected.nom} #{formUserBean.userSelected.prenom}" />
</div>
<p:column>
<i class="pi pi-users" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['distribution.page.user.prenom']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:outputLabel id="nom" value="#{formUserBean.userSelected.prenom}" />
</p:column>
<div class="info-block">
<div class="info-row">
<span class="info-label"><i class="pi pi-user"></i>#{msg['distribution.page.user.nom']}</span>
<span class="info-value"><h:outputText value="#{formUserBean.userSelected.nom}" /></span>
</div>
<p:column>
<i class="pi pi-phone" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['stock.page.fournisseur.Telephone']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:outputLabel id="code" value="#{formUserBean.userSelected.telephone}" />
</p:column>
<div class="info-row">
<span class="info-label"><i class="pi pi-users"></i>#{msg['distribution.page.user.prenom']}</span>
<span class="info-value"><h:outputText value="#{formUserBean.userSelected.prenom}" /></span>
</div>
<p:column>
<i class="pi pi-envelope" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['stock.page.fournisseur.mail']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:outputLabel id="mail" value="#{formUserBean.userSelected.mail}" />
</p:column>
</p:panelGrid>
<div class="info-row">
<span class="info-label"><i class="pi pi-phone"></i>#{msg['stock.page.fournisseur.Telephone']}</span>
<span class="info-value"><h:outputText value="#{formUserBean.userSelected.telephone}" /></span>
</div>
<p:divider />
<div class="info-row">
<span class="info-label"><i class="pi pi-envelope"></i>#{msg['stock.page.fournisseur.mail']}</span>
<span class="info-value"><h:outputText value="#{formUserBean.userSelected.mail}" /></span>
</div>
</div>
<p:panelGrid columns="2" style="margin-top: 30px; text-align:left">
<p:column>
<i class="pi pi-check-circle" style="margin-right: 5px; color: green;"></i>
<p:outputLabel value="#{msg['distribution.page.client.actif']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<h:outputText value="#{formUserBean.userSelected.actif ? 'Oui' : 'Non'}" />
</p:column>
</p:panelGrid>
<hr class="info-divider" />
<p:divider />
<div class="info-block">
<div class="info-row">
<span class="info-label"><i class="pi pi-check-circle"></i>#{msg['distribution.page.client.actif']}</span>
<span class="info-value">
<span class="status-chip #{formUserBean.userSelected.actif ne 'true' ? 'inactive' : ''}">
#{formUserBean.userSelected.actif eq 'true' ? 'Actif' : 'Inactif'}
</span>
</span>
</div>
</div>
<p:panelGrid columns="2" style="margin-top: 30px; text-align:left">
<hr class="info-divider" />
<div class="info-block">
<div class="info-row">
<span class="info-label"><i class="pi pi-users"></i>#{msg['distribution.page.user.groupe']}</span>
<span class="info-value"><h:outputText value="#{formUserBean.member.fkGroupe.nomGroupe}" /></span>
</div>
<div class="info-row">
<span class="info-label"><i class="pi pi-user"></i>Nom d'utilisateur</span>
<span class="info-value"><h:outputText value="#{formUserBean.userSelected.userid}" /></span>
</div>
</div>
</h:panelGroup>
<!-- ===================== MODE EDITION ===================== -->
<h:panelGroup rendered="#{formUserBean.canEdit}">
<div class="edit-field-row">
<span class="edit-field-label"><i class="pi pi-user"></i>#{msg['distribution.page.user.nom']}</span>
<div class="edit-field-input">
<p:inputText id="nom" value="#{formUserBean.userSelected.nom}" />
</div>
</div>
<div class="edit-field-row">
<span class="edit-field-label"><i class="pi pi-users"></i>#{msg['distribution.page.user.prenom']}</span>
<div class="edit-field-input">
<p:inputText id="prenom" value="#{formUserBean.userSelected.prenom}" />
</div>
</div>
<div class="edit-field-row">
<span class="edit-field-label"><i class="pi pi-phone"></i>#{msg['stock.page.fournisseur.Telephone']}</span>
<div class="edit-field-input">
<p:inputText id="telephone" value="#{formUserBean.userSelected.telephone}" />
</div>
</div>
<div class="edit-field-row">
<span class="edit-field-label"><i class="pi pi-envelope"></i>#{msg['stock.page.fournisseur.mail']}</span>
<div class="edit-field-input">
<p:inputText id="mail" value="#{formUserBean.userSelected.mail}" />
</div>
</div>
<hr class="info-divider" />
<div class="edit-field-row">
<span class="edit-field-label"><i class="pi pi-check-circle"></i>#{msg['distribution.page.client.actif']}</span>
<div class="edit-field-input">
<p:selectOneMenu value="#{formUserBean.userSelected.actif}">
<f:selectItem itemLabel="Oui" itemValue="true" />
<f:selectItem itemLabel="Non" itemValue="false" />
</p:selectOneMenu>
</div>
</div>
<hr class="info-divider" />
<div class="edit-field-row">
<span class="edit-field-label"><i class="pi pi-users"></i>#{msg['distribution.page.user.groupe']}</span>
<div class="edit-field-input">
<p:selectOneMenu id="groupe"
converter="groupeConverter"
value="#{formUserBean.member.fkGroupe}"
rendered="#{utilControleAccess.isshowPrivilegeUpdate('modifier_groupe')}">
<f:converter binding="#{groupeConverter}" />
<f:selectItem itemLabel="#{msg['distribution.select']}" noSelectionOption="true" />
<f:selectItems value="#{formUserBean.listeGroups}" var="groupe"
itemLabel="#{groupe.nomGroupe}" itemValue="#{groupe}" />
</p:selectOneMenu>
</div>
</div>
<div class="edit-field-row">
<span class="edit-field-label"><i class="pi pi-user"></i>Nom d'utilisateur</span>
<div class="edit-field-input">
<p:inputText id="user" value="#{formUserBean.userSelected.userid}" pt:autocomplete="off" />
</div>
</div>
<div class="edit-field-row" rendered="#{formUserBean.member.fkGroupe.id ne 'admin' or (utilContext.currentUser.userid eq formUserBean.userSelected.userid)}">
<span class="edit-field-label"><i class="pi pi-lock"></i>#{msg['distribution.page.user.password']}</span>
<div class="edit-field-input">
<p:password id="pw" value="#{formUserBean.userSelected.userpw}"
toggleMask="true" redisplay="true" pt:autocomplete="off" />
</div>
</div>
<!-- MODIF : champ de confirmation du mot de passe, variable séparée (formUserBean.confirmationMp) -->
<div class="edit-field-row" rendered="#{formUserBean.member.fkGroupe.id ne 'admin' or (utilContext.currentUser.userid eq formUserBean.userSelected.userid)}">
<span class="edit-field-label"><i class="pi pi-lock"></i>Confirmation MP</span>
<div class="edit-field-input">
<p:password id="confirmPw" value="#{formUserBean.confirmationMp}"
toggleMask="true" redisplay="true" pt:autocomplete="off">
<!-- MODIF : process inclut "pw" pour envoyer sa valeur actuelle au serveur -->
<p:ajax event="change" process="pw confirmPw"
listener="#{formUserBean.verifierConfirmationMp}"
update="confirmPwMsg confirmPw" />
</p:password>
<p:message id="confirmPwMsg" for="confirmPw" style="display:block; margin-top:4px; font-size:0.85rem;" />
</div>
</div>
<script>
//<![CDATA[
(function () {
function neutraliserAutofill() {
var userField = document.querySelector('input[id$=":user"]');
var pwField = document.querySelector('input[id$=":pw_input"]');
var confirmPwField = document.querySelector('input[id$=":confirmPw_input"]');
if (userField && !userField.dataset.autofillFixed) {
userField.setAttribute('readonly', 'readonly');
userField.dataset.autofillFixed = 'true';
userField.addEventListener('focus', function () {
userField.removeAttribute('readonly');
});
}
if (pwField && !pwField.dataset.autofillFixed) {
pwField.setAttribute('readonly', 'readonly');
pwField.dataset.autofillFixed = 'true';
pwField.addEventListener('focus', function () {
pwField.removeAttribute('readonly');
});
}
if (confirmPwField && !confirmPwField.dataset.autofillFixed) {
confirmPwField.setAttribute('readonly', 'readonly');
confirmPwField.dataset.autofillFixed = 'true';
confirmPwField.addEventListener('focus', function () {
confirmPwField.removeAttribute('readonly');
});
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', neutraliserAutofill);
} else {
neutraliserAutofill();
}
setTimeout(neutraliserAutofill, 300);
})();
//]]>
</script>
</h:panelGroup>
<p:column>
<i class="pi pi-users" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['distribution.page.user.groupe']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:outputLabel id="group" value="#{formUserBean.member.fkGroupe.nomGroupe}" />
</p:column>
</p:panelGrid>
</p:card>
<div style="width: 75%; height: 100%; margin-left: 1%;">
<p:card style=" width: 100%; min-height: 750px; top: 160px; height: 100% " rendered="#{!formUserBean.canEdit}" >
<p:tabView scrollable="true">
<p:tab title="#{msg['distribution.page.user.historique.connexion']}" >
<p:dataTable id="dataTable" var="histCnx"
rows="30" paginator="true" draggableColumns="true"
value="#{formUserBean.listeHistCnx}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="20,30,40,60,80,100"
emptyMessage="#{msg['distribution.page.produit.liste.historique.non'] }"
selectionMode="single"
rowKey="#{histCnx.id}">
<p:column style=" text-align: center;" headerText="#{msg['stock.page.achat.date']}" filterBy="#{histCnx.date}" filterMatchMode="contains" sortBy="#{histCnx.date}" >
<h:outputText value="#{histCnx.date}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['stock.page.achat.heur']}" filterBy="#{histCnx.heur}" filterMatchMode="contains" sortBy="#{histCnx.heur}" >
<h:outputText value="#{histCnx.heur}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['stock.page.imprimante.adresseIp']}" filterBy="#{histCnx.adresseIp}" filterMatchMode="contains" sortBy="#{histCnx.adresseIp}" >
<h:outputText value="#{histCnx.adresseIp}" />
</p:column>
</p:dataTable>
</p:tab>
<p:tab title="#{msg['distribution.page.consulter.historiqueManip']}" >
<p:dataTable id="dataTable2" var="histManip"
rows="30" paginator="true" draggableColumns="true"
value="#{formUserBean.listehistManipulation}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="20,30,40,60,80,100"
emptyMessage="#{msg['distribution.page.produit.liste.historique.non'] }"
selectionMode="single"
rowKey="#{histManip.id}">
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.nomTable']}" filterBy="#{histManip.nomTable}" filterMatchMode="contains" sortBy="#{histManip.nomTable}" >
<h:outputText value="#{histManip.nomTable}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.idLigne']}" filterBy="#{histManip.idLigne}" filterMatchMode="contains" sortBy="#{histManip.idLigne}" >
<h:outputText value="#{histManip.idLigne}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.type.historiqueManip']}" filterBy="#{histManip.typeManipumation}" filterMatchMode="contains" sortBy="#{histManip.typeManipumation}" >
<h:outputText value="#{histManip.typeManipumation}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.dateManip']}" filterBy="#{histManip.dateManipulation}" filterMatchMode="contains" sortBy="#{histManip.dateManipulation}" >
<h:outputText value="#{histManip.dateManipulation}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.oldValeur']}" filterBy="#{histManip.oldValeur}" filterMatchMode="contains" sortBy="#{histManip.oldValeur}" >
<h:outputText value="#{histManip.oldValeur}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.newValeur']}" filterBy="#{histManip.newValeur}" filterMatchMode="contains" sortBy="#{histManip.newValeur}" >
<h:outputText value="#{histManip.newValeur}" />
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
</p:card>
</div>
</div>
<div style="width: 100%; height: 100%; display: flex; margin-bottom: 1px;" >
<p:card id="cardModif" style="width: 100%; height: 100%;" rendered="#{formUserBean.canEdit}">
<p:tabView>
<p:tab title="#{msg['distribution.page.etablissement.information']}">
<p:panelGrid columns="2" style="width: 100%; height: 100%" >
<p:column style="width: 50%">
<p:panelGrid columns="2" style="margin-top: 30px; text-align:left">
<p:column>
<i class="pi pi-user" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['distribution.authentification.user']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:inputText id="user" value="#{formUserBean.userSelected.userid}" style="width: 300px"/>
</p:column>
<p:column>
<i class="pi pi-lock" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['distribution.page.user.password']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:password id="pw" value="#{formUserBean.userSelected.userpw}" style="width: 300px"
toggleMask="true" redisplay="true"/>
</p:column>
<div class="user-card-right-wrapper">
<p:card styleClass="user-card-right" style="height: 100%;">
<p:tabView scrollable="true" styleClass="form-tabs">
<p:tab title="#{msg['distribution.page.user.historique.connexion']}">
<p:column>
<i class="pi pi-user-edit" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['distribution.page.user.nom']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:inputText id="nom" value="#{formUserBean.userSelected.nom}" style="width: 300px"/>
</p:column>
<div class="table-subheader">
<span class="table-subheader-title">#{msg['distribution.page.user.historique.connexion']}</span>
<div>
<p:commandButton styleClass="mr-2 btn-export" icon="pi pi-file-excel" title="Excel" ajax="false">
<p:dataExporter type="xls" target="dataTable" fileName="historique_connexion" />
</p:commandButton>
<p:commandButton styleClass="btn-export" icon="pi pi-file-pdf" title="PDF" ajax="false">
<p:dataExporter type="pdf" target="dataTable" fileName="historique_connexion" />
</p:commandButton>
</div>
</div>
<p:column>
<i class="pi pi-user-plus" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['distribution.page.user.prenom']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:inputText id="code" value="#{formUserBean.userSelected.prenom}" style="width: 300px"/>
</p:column>
<p:dataTable id="dataTable" var="histCnx"
rows="10" paginator="true" draggableColumns="true"
value="#{formUserBean.listeHistCnx}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="10,30,40,60,80,100"
emptyMessage="#{msg['distribution.page.produit.liste.historique.non'] }"
selectionMode="single"
rowKey="#{histCnx.id}">
<p:column>
<i class="pi pi-phone" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['stock.page.fournisseur.Telephone']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:inputText id="adresse" value="#{formUserBean.userSelected.telephone}" style="width: 300px"/>
</p:column>
<p:column>
<i class="pi pi-envelope" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['stock.page.fournisseur.mail']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:inputText id="mail" value="#{formUserBean.userSelected.mail}" style="width: 300px"/>
</p:column>
<p:column>
<i class="pi pi-check-circle" style="margin-right: 5px; color: green;"></i>
<p:outputLabel value="#{msg['distribution.page.client.actif']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:selectOneMenu value="#{formUserBean.userSelected.actif}" style="width: 300px">
<f:selectItem itemLabel="Oui" itemValue="true" />
<f:selectItem itemLabel="Non" itemValue="false" />
</p:selectOneMenu>
</p:column>
<p:column>
<i class="pi pi-users" style="margin-right: 5px"></i>
<p:outputLabel value="#{msg['distribution.page.user.groupe']}" style="color: #3F51B5; font-weight: bold" />
</p:column>
<p:column>
<p:selectOneMenu id="groupe" style="width: 310px;"
converter="groupeConverter"
value="#{formUserBean.member.fkGroupe}">
<f:converter binding="#{groupeConverter}" />
<f:selectItem itemLabel="#{msg['distribution.select']}" noSelectionOption="true" />
<f:selectItems value="#{formUserBean.listeGroups}" var="groupe"
itemLabel="#{groupe.nomGroupe}" itemValue="#{groupe}" />
</p:selectOneMenu>
</p:column>
</p:panelGrid>
<p:column style=" text-align: center;" headerText="#{msg['stock.page.achat.date']}" filterBy="#{histCnx.date}" filterMatchMode="contains" sortBy="#{histCnx.date}" >
<h:outputText value="#{histCnx.date}" />
</p:column>
</p:panelGrid>
<p:column style=" text-align: center;" headerText="#{msg['stock.page.achat.heur']}" filterBy="#{histCnx.heur}" filterMatchMode="contains" sortBy="#{histCnx.heur}" >
<h:outputText value="#{histCnx.heur}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['stock.page.imprimante.adresseIp']}" filterBy="#{histCnx.adresseIp}" filterMatchMode="contains" sortBy="#{histCnx.adresseIp}" >
<h:outputText value="#{histCnx.adresseIp}" />
</p:column>
</p:dataTable>
</p:tab>
<p:tab title="#{msg['distribution.page.consulter.historiqueManip']}">
<div class="table-subheader">
<span class="table-subheader-title">#{msg['distribution.page.consulter.historiqueManip']}</span>
<div>
<p:commandButton styleClass="mr-2 btn-export" icon="pi pi-file-excel" title="Excel" ajax="false">
<p:dataExporter type="xls" target="dataTable2" fileName="historique_manipulation" />
</p:commandButton>
<p:commandButton styleClass="btn-export" icon="pi pi-file-pdf" title="PDF" ajax="false">
<p:dataExporter type="pdf" target="dataTable2" fileName="historique_manipulation" />
</p:commandButton>
</div>
</div>
<p:dataTable id="dataTable2" var="histManip"
rows="10" paginator="true" draggableColumns="true"
value="#{formUserBean.listehistManipulation}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="10,30,40,60,80,100"
emptyMessage="#{msg['distribution.page.produit.liste.historique.non'] }"
selectionMode="single"
rowKey="#{histManip.id}">
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.nomTable']}" filterBy="#{histManip.nomTable}" filterMatchMode="contains" sortBy="#{histManip.nomTable}" >
<h:outputText value="#{histManip.nomTable}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.idLigne']}" filterBy="#{histManip.idLigne}" filterMatchMode="contains" sortBy="#{histManip.idLigne}" >
<h:outputText value="#{histManip.idLigne}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.type.historiqueManip']}" filterBy="#{histManip.typeManipulation}" filterMatchMode="contains" sortBy="#{histManip.typeManipulation}" >
<h:outputText value="#{histManip.typeManipulation}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.dateManip']}" filterBy="#{histManip.dateManipulation}" filterMatchMode="contains" sortBy="#{histManip.dateManipulation}" >
<h:outputText value="#{histManip.dateManipulation}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.oldValeur']}" filterBy="#{histManip.oldValeur}" filterMatchMode="contains" sortBy="#{histManip.oldValeur}" >
<h:outputText value="#{histManip.oldValeur}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.newValeur']}" filterBy="#{histManip.newValeur}" filterMatchMode="contains" sortBy="#{histManip.newValeur}" >
<h:outputText value="#{histManip.newValeur}" />
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
</p:card>
</div>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@ -13,9 +13,9 @@
<f:viewParam name="homeOutcome" value="/favorites/dashboard" />
<f:viewParam name="value" value="Utilisateurs" />
<f:event type="preRenderView" listener="#{userBean.init}" />
</f:metadata>
</ui:define>
<ui:define name="content">
<style>
.inactive-row {
@ -23,65 +23,211 @@
background-image: none !important;
color: #ffffff;
}
.card .ui-datatable-tablewrapper table td,
.card .ui-datatable-tablewrapper table th {
vertical-align: middle !important;
}
.card .ui-datatable-tablewrapper table td {
padding-top: 14px !important;
padding-bottom: 14px !important;
}
.page-center-wrapper {
display: flex;
align-items: center;
justify-content: center;
min-height: calc(100vh - 160px);
}
.page-center-wrapper .card {
width: 100%;
}
.table-header-title {
font-weight: 700;
font-size: 1.05rem;
color: #343a40;
}
/* MODIF: nuance teal du thème (#0D9488) au lieu du vert pistache */
.btn-green,
.btn-green.ui-button,
.btn-green .ui-button-text {
background-color: #0D9488 !important;
border-color: #0D9488 !important;
color: #ffffff !important;
}
.btn-green:hover {
background-color: #0b7d73 !important;
border-color: #0b7d73 !important;
}
.btn-green-outline,
.btn-green-outline.ui-button {
background-color: #ffffff !important;
border: 1px solid #0D9488 !important;
color: #0D9488 !important;
}
.btn-green-outline:hover {
background-color: #e6f5f4 !important;
}
.btn-view-green,
.btn-view-green.ui-button {
background-color: #0D9488 !important;
border-color: #0D9488 !important;
color: #ffffff !important;
}
.btn-view-green:hover {
background-color: #0b7d73 !important;
}
/* MODIF: boutons export Excel / PDF stylés en outline teal, icônes gardent leur couleur d'origine */
.btn-export {
background-color: #ffffff !important;
border: 1px solid #dee2e6 !important;
color: #0D9488 !important;
}
.btn-export:hover {
background-color: #e6f5f4 !important;
border-color: #0D9488 !important;
}
.status-badge {
display: inline-flex;
align-items: center;
gap: 6px;
font-weight: 500;
}
.status-dot {
width: 9px;
height: 9px;
border-radius: 50%;
display: inline-block;
}
/* MODIF: puce active en teal */
.status-dot-connected {
background-color: #0D9488; /* teal, cohérent avec ton thème */
}
.status-dot-disconnected {
background-color: #9E9E9E; /* gris */
}
.status-dot-inactive {
background-color: #ef4444; /* rouge, déjà bon */
}
/* MODIF: checkboxes du columnToggler en teal au lieu de bleu */
.ui-chkbox-box.ui-state-active,
.ui-datatable-toggler-content .ui-chkbox-box.ui-state-active {
background-color: #0D9488 !important;
border-color: #0D9488 !important;
color: #ffffff !important;
}
.ui-chkbox-box:hover,
.ui-chkbox-box.ui-state-hover {
border-color: #0D9488 !important;
}
.ui-chkbox-box.ui-state-focus {
border-color: #0D9488 !important;
box-shadow: 0 0 0 2px rgba(13, 148, 136, 0.2) !important;
}
</style>
<h:form>
<div class="card">
<p:dataTable id="dataTable" var="user"
rows="30" paginator="true" draggableColumns="true"
value="#{userBean.listeUser}"
selection="#{userBean.userSelected}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="20,30,40,60,80,100"
emptyMessage="#{msg['distribution.page.user.liste.message.non'] }"
selectionMode="single"
rowKey="#{user.userid}" >
<f:facet name="header">
<div class="flex justify-content-between align-items-center">
<div>
<div class="page-center-wrapper">
<h:form>
<div class="card">
<p:dataTable id="dataTable" var="user"
rows="30" paginator="true" draggableColumns="true"
value="#{userBean.listeUser}"
selection="#{userBean.userSelected}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="20,30,40,60,80,100"
emptyMessage="#{msg['distribution.page.user.liste.message.non'] }"
selectionMode="single"
rowKey="#{user.userid}" >
<f:facet name="header">
<div class="flex justify-content-between align-items-center">
<div>
<span class="table-header-title">#{msg['distribution.page.Utilisateurs']}</span>
</div>
<div>
<!-- MODIF: bouton export Excel -->
<p:commandButton id="xlsExport"
styleClass="mr-2 mb-2 btn-export"
type="button"
icon="pi pi-file-excel"
title="Excel">
<p:dataExporter type="xls"
target="dataTable"
fileName="utilisateurs" />
</p:commandButton>
<p:commandButton id="pdfExport"
styleClass="mr-2 mb-2 btn-export"
type="button"
icon="pi pi-file-pdf"
title="PDF">
<p:dataExporter type="pdf"
target="dataTable"
fileName="utilisateurs" />
</p:commandButton>
<p:commandButton id="toggler" styleClass="mr-2 mb-2 btn-green-outline" type="button" value="Columns" icon="pi pi-align-justify"/>
<p:columnToggler datasource="dataTable" trigger="toggler">
<p:ajax />
</p:columnToggler>
<p:commandButton title="#{msg['distribution.page.entreprise.ajouterenreprise']}" icon="pi pi-plus" styleClass="ui-button-success btn-green mr-2" action="#{userBean.ajouterUser()}" rendered="#{utilControleAccess.isshowPrivilegeAdd('user')}" />
</div>
</div>
<div>
</f:facet>
<p:commandButton id="toggler" styleClass="mr-2 mb-2" type="button" value="Columns" icon="pi pi-align-justify"/>
<p:columnToggler datasource="dataTable" trigger="toggler">
<p:ajax />
</p:columnToggler>
<p:commandButton title="#{msg['distribution.page.entreprise.ajouterenreprise']}" icon="pi pi-plus" styleClass="ui-button-success mr-2" action="#{userBean.ajouterUser()}" rendered="#{utilControleAccess.isshowPrivilegeAdd('User')}" />
<p:column style="text-align: center;" headerText="#{msg['distribution.page.user.nom']}" filterBy="#{user.nom}" filterMatchMode="contains" sortBy="#{user.nom}" >
<h:outputText value="#{user.nom}" />
</p:column>
</div>
</div>
</f:facet>
<p:column style="text-align: center;" headerText="#{msg['distribution.page.user.prenom']}" filterBy="#{user.prenom}" filterMatchMode="contains" sortBy="#{user.prenom}" >
<h:outputText value="#{user.prenom}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.user.nom']}" filterBy="#{user.nom}" filterMatchMode="contains" sortBy="#{user.nom}" >
<h:outputText value="#{user.nom}" />
</p:column>
<p:column style="text-align: center;" headerText="#{msg['stock.page.fournisseur.Telephone']}" filterBy="#{user.telephone}" filterMatchMode="contains" sortBy="#{user.telephone}" >
<h:outputText value="#{user.telephone}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['distribution.page.user.prenom']}" filterBy="#{user.prenom}" filterMatchMode="contains" sortBy="#{user.prenom}" >
<h:outputText value="#{user.prenom}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['stock.page.fournisseur.Telephone']}" filterBy="#{user.telephone}" filterMatchMode="contains" sortBy="#{user.telephone}" >
<h:outputText value="#{user.telephone}" />
</p:column>
<p:column style="text-align: center;" headerText="#{msg['stock.page.fournisseur.mail']}" filterBy="#{user.mail}" filterMatchMode="contains" sortBy="#{user.mail}" >
<h:outputText value="#{user.mail}" />
</p:column>
<p:column style="text-align: center;" headerText="#{msg['distribution.page.user.actf']}"
filterBy="#{user.actif}" filterMatchMode="contains" sortBy="#{user.actif}">
<h:outputText value="#{user.actif ? 'Oui' : 'Non'}" />
</p:column>
<p:column style="text-align: center;" headerText="Groupes">
<h:outputText value="#{userBean.getGroupeByUser(user)}" />
</p:column>
<p:column style=" text-align: center;" headerText="#{msg['stock.page.fournisseur.mail']}" filterBy="#{user.mail}" filterMatchMode="contains" sortBy="#{user.mail}" >
<h:outputText value="#{user.mail}" />
</p:column>
<p:column style="text-align: center;" headerText="Status">
<h:panelGroup styleClass="status-badge">
<span class="status-dot status-dot-connected"
style="display:#{userBean.isUserConnected(user) eq 'connected' ? 'inline-block' : 'none'};"></span>
<span class="status-dot status-dot-disconnected"
style="display:#{userBean.isUserConnected(user) eq 'disconnected' ? 'inline-block' : 'none'};"></span>
<span class="status-dot status-dot-inactive"
style="display:#{userBean.isUserConnected(user) eq 'inactif' ? 'inline-block' : 'none'};"></span>
<p:column style="width:130px; text-align: center;" exportable="false" visible="true" draggable="false" toggleable="false">
<h:outputText value="Connecté" rendered="#{userBean.isUserConnected(user) eq 'connected'}"/>
<h:outputText value="Déconnecté" rendered="#{userBean.isUserConnected(user) eq 'disconnected'}"/>
<h:outputText value="Inactif" rendered="#{userBean.isUserConnected(user) eq 'inactif'}"/>
</h:panelGroup>
</p:column>
<p:commandButton id="buttonSelect" style="height:30px; text-align: center" action="#{userBean.voirUser()}" icon="pi pi-search" title="#{msg['distribution.page.consulter']}">
<f:setPropertyActionListener value="#{user}" target="#{userBean.userSelected}" />
</p:commandButton>
<p:column style="width:130px; text-align: center;" exportable="false" visible="true" draggable="false" toggleable="false">
<p:commandButton id="buttonSelect" styleClass="btn-view-green" style="height:30px; text-align: center" action="#{userBean.voirUser()}" icon="pi pi-search" title="#{msg['distribution.page.consulter']}">
<f:setPropertyActionListener value="#{user}" target="#{userBean.userSelected}" />
</p:commandButton>
</p:column>
</p:column>
</p:dataTable>
</div>
</h:form>
</p:dataTable>
</div>
</h:form>
</div>
</ui:define>
</ui:composition>