Initial commit: GBCM Client Quarkus implementation with PrimeFaces and Freya theme

This commit is contained in:
dahoud
2025-10-06 18:45:43 +00:00
commit 9aff13a830
7 changed files with 869 additions and 0 deletions

105
.gitignore vendored Normal file
View File

@@ -0,0 +1,105 @@
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
# Gradle
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
# IntelliJ IDEA
.idea/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
# Eclipse
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
# NetBeans
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
# VS Code
.vscode/
# Mac
.DS_Store
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# Quarkus
.quarkus/
# Node modules (si utilisé pour le build frontend)
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Logs
logs
*.log
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Temporary files
*.tmp
*.temp

144
README.md Normal file
View File

@@ -0,0 +1,144 @@
# GBCM Client Implementation - Quarkus
Interface web pour la plateforme GBCM (Global Business Consulting and Management) développée avec Quarkus et PrimeFaces.
## Description
Ce module contient l'interface utilisateur web de la plateforme GBCM, permettant aux utilisateurs d'accéder aux services de consulting, coaching et gestion des ateliers.
## Technologies
- **Quarkus 3.6.0** - Framework Java moderne
- **PrimeFaces 13.0.0** - Composants JSF
- **Jakarta Faces 4.0** - Framework web
- **Freya Theme 5.0.0** - Thème PrimeFaces
- **Maven** - Gestion des dépendances
## Prérequis
- Java 17 ou supérieur
- Maven 3.8+
- PostgreSQL 13+ (production)
## Installation
1. Cloner le repository
```bash
git clone https://git.lions.dev/gbcm/gbcm-client-impl-quarkus.git
cd gbcm-client-impl-quarkus
```
2. Installer les dépendances
```bash
mvn clean install
```
3. Configuration
Copier `application.properties.example` vers `application.properties` et configurer :
- URL du serveur API GBCM
- Base de données
- Paramètres de sécurité
## Développement
### Démarrage en mode développement
```bash
mvn quarkus:dev
```
L'application sera accessible sur http://localhost:8080/gbcm
### Build de production
```bash
mvn clean package -Pnative
```
## Structure du projet
```
src/
├── main/
│ ├── java/com/gbcm/client/
│ │ ├── beans/ # Managed Beans JSF
│ │ ├── converters/ # Convertisseurs
│ │ ├── validators/ # Validateurs
│ │ └── config/ # Configuration
│ ├── resources/
│ │ ├── META-INF/resources/ # Ressources web
│ │ └── application.properties
│ └── webapp/
│ ├── templates/ # Templates PrimeFaces
│ ├── pages/ # Pages JSF
│ └── WEB-INF/
└── test/ # Tests unitaires
```
## Fonctionnalités
### Authentification
- Connexion/déconnexion sécurisée
- Gestion des rôles (Admin, Coach, Client)
- Réinitialisation de mot de passe
### Dashboard
- Tableaux de bord personnalisés par rôle
- Métriques et KPIs
- Notifications en temps réel
### Gestion des Services
- Programmes Strategic Workshops
- Sessions de coaching individuel
- Coaching à la demande
- Projets spéciaux
### Administration
- Gestion des utilisateurs
- Configuration système
- Rapports et analytics
## API Integration
Ce client communique avec l'API GBCM via REST :
- Base URL configurée dans `application.properties`
- Authentification JWT
- Gestion automatique des tokens
## Tests
```bash
# Tests unitaires
mvn test
# Tests d'intégration
mvn verify
```
## Déploiement
### Docker
```bash
docker build -t gbcm-client .
docker run -p 8080:8080 gbcm-client
```
### Production
1. Build de l'application
2. Configuration des variables d'environnement
3. Déploiement sur serveur d'application
## Configuration
### Variables d'environnement principales
- `GBCM_SERVER_API_URL` - URL de l'API serveur
- `DATABASE_URL` - URL de la base de données
- `JWT_SECRET` - Secret pour les tokens JWT
## Support
Pour toute question ou problème :
- Email: support@gbcm.com
- Documentation: https://docs.gbcm.com
## Licence
Propriétaire - GBCM LLC © 2024

156
pom.xml Normal file
View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gbcm</groupId>
<artifactId>gbcm-client-impl-quarkus</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>GBCM Client Implementation - Quarkus</name>
<description>Interface web GBCM avec Quarkus et PrimeFaces</description>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Versions -->
<quarkus.version>3.6.0</quarkus.version>
<primefaces.version>13.0.0</primefaces.version>
<freya.version>5.0.0</freya.version>
<jakarta.faces.version>4.0.1</jakarta.faces.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Quarkus Core -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-undertow</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-reactive-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
<!-- Jakarta Faces (JSF) -->
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-impl</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- PrimeFaces -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>${primefaces.version}</version>
<classifier>jakarta</classifier>
</dependency>
<!-- Freya Theme -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>freya</artifactId>
<version>${freya.version}</version>
<classifier>jakarta</classifier>
</dependency>
<!-- CDI -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<!-- Validation -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
</dependency>
<!-- JSON Processing -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jackson</artifactId>
</dependency>
<!-- GBCM Server API -->
<dependency>
<groupId>com.gbcm</groupId>
<artifactId>gbcm-server-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>prime-repo</id>
<name>PrimeFaces Maven Repository</name>
<url>https://repository.primefaces.org</url>
</repository>
</repositories>
</project>

View File

@@ -0,0 +1,195 @@
package com.gbcm.client.beans.auth;
import com.gbcm.client.service.GBCMServerClient;
import com.gbcm.server.api.dto.UserDTO;
import com.gbcm.server.api.dto.LoginRequestDTO;
import com.gbcm.server.api.dto.LoginResponseDTO;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.io.Serializable;
/**
* Managed Bean pour la gestion de l'authentification
*/
@Named("authBean")
@SessionScoped
public class AuthBean implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private GBCMServerClient serverClient;
// Propriétés de connexion
private String email;
private String password;
private boolean rememberMe;
// Utilisateur connecté
private UserDTO currentUser;
private String authToken;
private boolean authenticated = false;
/**
* Tentative de connexion
*/
public String login() {
try {
LoginRequestDTO loginRequest = new LoginRequestDTO();
loginRequest.setEmail(email);
loginRequest.setPassword(password);
loginRequest.setRememberMe(rememberMe);
LoginResponseDTO response = serverClient.login(loginRequest);
if (response.isSuccess()) {
this.currentUser = response.getUser();
this.authToken = response.getToken();
this.authenticated = true;
// Message de succès
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Connexion réussie",
"Bienvenue " + currentUser.getFirstName()));
// Redirection selon le rôle
return redirectAfterLogin();
} else {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur de connexion",
response.getMessage()));
return null;
}
} catch (Exception e) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur système",
"Impossible de se connecter au serveur"));
return null;
}
}
/**
* Déconnexion
*/
public String logout() {
try {
if (authToken != null) {
serverClient.logout(authToken);
}
} catch (Exception e) {
// Log l'erreur mais continue la déconnexion
}
// Nettoyage de la session
this.currentUser = null;
this.authToken = null;
this.authenticated = false;
this.email = null;
this.password = null;
this.rememberMe = false;
// Invalidation de la session JSF
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "/index?faces-redirect=true";
}
/**
* Redirection après connexion selon le rôle
*/
private String redirectAfterLogin() {
if (currentUser == null) {
return "/index?faces-redirect=true";
}
switch (currentUser.getRole()) {
case "ADMIN":
return "/pages/admin/dashboard?faces-redirect=true";
case "COACH":
return "/pages/coaching/dashboard?faces-redirect=true";
case "CLIENT":
return "/pages/dashboard/client?faces-redirect=true";
default:
return "/pages/dashboard/home?faces-redirect=true";
}
}
/**
* Navigation vers le profil
*/
public String goToProfile() {
return "/pages/profile/edit?faces-redirect=true";
}
/**
* Navigation vers les paramètres
*/
public String goToSettings() {
return "/pages/settings/general?faces-redirect=true";
}
/**
* Vérification des permissions
*/
public boolean hasRole(String role) {
return authenticated && currentUser != null &&
role.equals(currentUser.getRole());
}
public boolean isAdmin() {
return hasRole("ADMIN");
}
public boolean isCoach() {
return hasRole("COACH");
}
public boolean isClient() {
return hasRole("CLIENT");
}
// Getters et Setters
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
public UserDTO getCurrentUser() {
return currentUser;
}
public String getAuthToken() {
return authToken;
}
public boolean isAuthenticated() {
return authenticated;
}
}

View File

@@ -0,0 +1,47 @@
# GBCM Client Configuration
quarkus.application.name=gbcm-client
quarkus.application.version=1.0.0-SNAPSHOT
# Server Configuration
quarkus.http.port=8080
quarkus.http.host=0.0.0.0
# JSF Configuration
quarkus.servlet.context-path=/gbcm
# Security Configuration
quarkus.security.auth.enabled=true
# REST Client Configuration - GBCM Server API
gbcm.server.api.url=http://localhost:8081/api/v1
quarkus.rest-client."com.gbcm.client.service.GBCMServerClient".url=${gbcm.server.api.url}
# Database Configuration (for session storage)
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=gbcm_user
quarkus.datasource.password=gbcm_password
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/gbcm_client
# Hibernate Configuration
quarkus.hibernate-orm.database.generation=update
quarkus.hibernate-orm.log.sql=false
# Logging Configuration
quarkus.log.level=INFO
quarkus.log.category."com.gbcm".level=DEBUG
# Development Configuration
%dev.quarkus.log.level=DEBUG
%dev.quarkus.hibernate-orm.log.sql=true
%dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:gbcm_client_dev;DB_CLOSE_DELAY=-1
%dev.quarkus.datasource.db-kind=h2
# Production Configuration
%prod.quarkus.log.level=WARN
%prod.quarkus.datasource.jdbc.url=${DATABASE_URL}
# PrimeFaces Configuration
primefaces.theme=freya
primefaces.font-awesome=true
primefaces.client-side-validation=true
primefaces.move-scripts-to-bottom=true

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<display-name>GBCM Client Application</display-name>
<description>Interface web GBCM pour la gestion des services de consulting</description>
<!-- JSF Configuration -->
<context-param>
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>jakarta.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>jakarta.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<!-- PrimeFaces Configuration -->
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>freya</param-value>
</context-param>
<context-param>
<param-name>primefaces.FONT_AWESOME</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>primefaces.CLIENT_SIDE_VALIDATION</param-name>
<param-value>true</param-value>
</context-param>
<!-- JSF Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<!-- Security Configuration -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Pages</web-resource-name>
<url-pattern>/pages/dashboard/*</url-pattern>
<url-pattern>/pages/coaching/*</url-pattern>
<url-pattern>/pages/workshops/*</url-pattern>
<url-pattern>/pages/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
<role-name>coach</role-name>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<!-- Welcome Files -->
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<!-- Error Pages -->
<error-page>
<error-code>404</error-code>
<location>/pages/error/404.xhtml</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/pages/error/500.xhtml</location>
</error-page>
</web-app>

View File

@@ -0,0 +1,135 @@
<!DOCTYPE html>
<html 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">
<h:head>
<title>
<ui:insert name="title">GBCM - Global Business Consulting and Management</ui:insert>
</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="description" content="GBCM - Services de conseil en management et développement professionnel"/>
<meta name="author" content="GBCM LLC"/>
<!-- Freya Theme CSS -->
<h:outputStylesheet name="primefaces-freya/theme.css"/>
<!-- Custom CSS -->
<h:outputStylesheet name="css/gbcm-custom.css"/>
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="#{request.contextPath}/resources/images/favicon.ico"/>
</h:head>
<h:body>
<div class="layout-wrapper">
<!-- Top Bar -->
<div class="layout-topbar">
<div class="layout-topbar-wrapper">
<div class="layout-topbar-left">
<h:link outcome="/index" styleClass="layout-topbar-logo">
<h:graphicImage name="images/gbcm-logo.png" alt="GBCM Logo" height="40"/>
<span class="layout-topbar-logo-text">GBCM</span>
</h:link>
</div>
<div class="layout-topbar-right">
<ul class="layout-topbar-actions">
<li>
<p:commandButton icon="pi pi-user" styleClass="p-button-text p-button-plain"
onclick="PF('userMenuDialog').show()"/>
</li>
<li>
<p:commandButton icon="pi pi-bell" styleClass="p-button-text p-button-plain"
onclick="PF('notificationDialog').show()"/>
</li>
</ul>
</div>
</div>
</div>
<!-- Sidebar Menu -->
<div class="layout-sidebar">
<div class="layout-menu">
<p:menu model="#{menuBean.menuModel}" styleClass="layout-menu-items"/>
</div>
</div>
<!-- Main Content -->
<div class="layout-main">
<div class="layout-main-content">
<!-- Breadcrumb -->
<div class="content-section">
<p:breadCrumb model="#{breadcrumbBean.breadcrumbModel}" styleClass="custom-breadcrumb"/>
</div>
<!-- Page Content -->
<div class="content-section">
<ui:insert name="content">
<p:panel header="Contenu par défaut">
<p>Aucun contenu spécifique défini pour cette page.</p>
</p:panel>
</ui:insert>
</div>
</div>
</div>
<!-- Footer -->
<div class="layout-footer">
<div class="layout-footer-wrapper">
<span>© 2024 GBCM LLC - Global Business Consulting and Management</span>
<div class="layout-footer-right">
<span>Version 1.0.0</span>
</div>
</div>
</div>
</div>
<!-- User Menu Dialog -->
<p:dialog header="Profil Utilisateur" widgetVar="userMenuDialog" modal="true"
width="400" height="300" resizable="false">
<div class="user-profile-content">
<p:outputLabel value="#{authBean.currentUser.fullName}" styleClass="user-name"/>
<p:outputLabel value="#{authBean.currentUser.email}" styleClass="user-email"/>
<div class="user-actions">
<p:commandButton value="Mon Profil" icon="pi pi-user"
action="#{authBean.goToProfile}" styleClass="p-button-outlined"/>
<p:commandButton value="Paramètres" icon="pi pi-cog"
action="#{authBean.goToSettings}" styleClass="p-button-outlined"/>
<p:commandButton value="Déconnexion" icon="pi pi-sign-out"
action="#{authBean.logout}" styleClass="p-button-danger"/>
</div>
</div>
</p:dialog>
<!-- Notification Dialog -->
<p:dialog header="Notifications" widgetVar="notificationDialog" modal="true"
width="500" height="400" resizable="false">
<p:dataTable value="#{notificationBean.notifications}" var="notification"
emptyMessage="Aucune notification">
<p:column headerText="Message">
<h:outputText value="#{notification.message}"/>
</p:column>
<p:column headerText="Date">
<h:outputText value="#{notification.createdAt}">
<f:convertDateTime pattern="dd/MM/yyyy HH:mm"/>
</h:outputText>
</p:column>
</p:dataTable>
</p:dialog>
<!-- Global Messages -->
<p:growl id="globalMessages" showDetail="true" life="5000"/>
<!-- Custom JavaScript -->
<h:outputScript name="js/gbcm-custom.js"/>
</h:body>
</html>