diff --git a/pom.xml b/pom.xml index c782337..b6c2334 100644 --- a/pom.xml +++ b/pom.xml @@ -57,21 +57,30 @@ io.quarkus quarkus-resteasy-reactive + + + + + - io.quarkus - quarkus-qute + io.quarkiverse.primefaces + quarkus-primefaces + 3.13.3 - + - io.quarkus - quarkus-resteasy-reactive-qute + io.quarkiverse.primefaces + quarkus-primefaces-extensions + 3.13.3 - + - io.quarkus - quarkus-arc + org.primefaces.themes + freya + 5.0.0 + jakarta diff --git a/src/main/java/com/gbcm/client/beans/ClientBean.java b/src/main/java/com/gbcm/client/beans/ClientBean.java new file mode 100644 index 0000000..a23e4c3 --- /dev/null +++ b/src/main/java/com/gbcm/client/beans/ClientBean.java @@ -0,0 +1,101 @@ +package com.gbcm.client.beans; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.logging.Logger; + +import com.gbcm.client.service.ClientRestService; +import com.gbcm.server.api.dto.client.ClientDTO; +import com.gbcm.server.api.dto.common.PagedResponseDTO; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; + +/** + * Bean pour la gestion des clients dans l'interface web. + * Connecté au serveur backend pour récupérer les vraies données. + * + * @author GBCM Development Team + * @version 1.0 + * @since 1.0 + */ +@Named("clientBean") +@RequestScoped +public class ClientBean implements Serializable { + + private static final Logger logger = Logger.getLogger(ClientBean.class.getName()); + + @Inject + private ClientRestService clientRestService; + + /** + * Obtient la liste des clients depuis le serveur backend + */ + public List getClients() { + try { + logger.info("Récupération de la liste des clients depuis le serveur backend"); + + PagedResponseDTO pagedResponse = clientRestService.getClients(0, 50, null, null, null, null); + List clients = pagedResponse.getContent(); + + logger.info("Retour de " + clients.size() + " clients depuis le serveur"); + return clients; + } catch (Exception e) { + logger.severe("Erreur lors de la récupération des clients: " + e.getMessage()); + // Retourner une liste vide en cas d'erreur + return new ArrayList<>(); + } + } + + /** + * Obtient la date actuelle pour l'affichage + */ + public Date getCurrentDate() { + return new Date(); + } + + /** + * Crée un nouveau client via l'API + */ + public String createClient(ClientDTO clientDTO) { + try { + logger.info("Création d'un nouveau client via l'API"); + // TODO: Implémenter la création via clientRestService + return "/pages/clients/list?faces-redirect=true"; + } catch (Exception e) { + logger.severe("Erreur lors de la création du client: " + e.getMessage()); + return null; + } + } + + /** + * Met à jour un client via l'API + */ + public String updateClient(ClientDTO clientDTO) { + try { + logger.info("Mise à jour du client via l'API: " + clientDTO.getId()); + // TODO: Implémenter la mise à jour via clientRestService + return "/pages/clients/list?faces-redirect=true"; + } catch (Exception e) { + logger.severe("Erreur lors de la mise à jour du client: " + e.getMessage()); + return null; + } + } + + /** + * Supprime un client via l'API + */ + public String deleteClient(Long clientId) { + try { + logger.info("Suppression du client via l'API: " + clientId); + // TODO: Implémenter la suppression via clientRestService + return "/pages/clients/list?faces-redirect=true"; + } catch (Exception e) { + logger.severe("Erreur lors de la suppression du client: " + e.getMessage()); + return null; + } + } +} diff --git a/src/main/java/com/gbcm/client/beans/CoachBean.java b/src/main/java/com/gbcm/client/beans/CoachBean.java new file mode 100644 index 0000000..4842c17 --- /dev/null +++ b/src/main/java/com/gbcm/client/beans/CoachBean.java @@ -0,0 +1,36 @@ +package com.gbcm.client.beans; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import com.gbcm.client.service.CoachRestService; +import com.gbcm.server.api.dto.coach.CoachDTO; +import com.gbcm.server.api.dto.common.PagedResponseDTO; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; + +@Named("coachBean") +@RequestScoped +public class CoachBean implements Serializable { + + private static final Logger logger = Logger.getLogger(CoachBean.class.getName()); + + @Inject + private CoachRestService coachRestService; + + public List getCoaches() { + try { + logger.info("Récupération de la liste des coachs depuis le serveur backend"); + PagedResponseDTO pagedResponse = coachRestService.getCoaches(0, 50, null, null, null, false, + null); + return pagedResponse.getContent(); + } catch (Exception e) { + logger.severe("Erreur lors de la récupération des coachs: " + e.getMessage()); + return new ArrayList<>(); + } + } +} diff --git a/src/main/java/com/gbcm/client/beans/CoachingSessionBean.java b/src/main/java/com/gbcm/client/beans/CoachingSessionBean.java new file mode 100644 index 0000000..db05635 --- /dev/null +++ b/src/main/java/com/gbcm/client/beans/CoachingSessionBean.java @@ -0,0 +1,36 @@ +package com.gbcm.client.beans; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import com.gbcm.client.service.CoachingSessionRestService; +import com.gbcm.server.api.dto.session.CoachingSessionDTO; +import com.gbcm.server.api.dto.common.PagedResponseDTO; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; + +@Named("sessionBean") +@RequestScoped +public class CoachingSessionBean implements Serializable { + + private static final Logger logger = Logger.getLogger(CoachingSessionBean.class.getName()); + + @Inject + private CoachingSessionRestService sessionRestService; + + public List getSessions() { + try { + logger.info("Récupération de la liste des sessions"); + PagedResponseDTO pagedResponse = sessionRestService.getCoachingSessions(0, 50, null, + null, null, null, null, null); + return pagedResponse.getContent(); + } catch (Exception e) { + logger.severe("Erreur lors de la récupération des sessions: " + e.getMessage()); + return new ArrayList<>(); + } + } +} diff --git a/src/main/java/com/gbcm/client/beans/DashboardBean.java b/src/main/java/com/gbcm/client/beans/DashboardBean.java new file mode 100644 index 0000000..a075c58 --- /dev/null +++ b/src/main/java/com/gbcm/client/beans/DashboardBean.java @@ -0,0 +1,237 @@ +package com.gbcm.client.beans; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.gbcm.client.service.DashboardRestService; + +import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; + +@Named("dashboardBean") +@RequestScoped +public class DashboardBean implements Serializable { + + @Inject + private DashboardRestService dashboardRestService; + + // Propriétés pour les filtres et sélections + private String revenuePeriod = "30d"; + + // Cache des métriques pour la requête + private Map metrics; + private Map clientMetrics; + private Map sessionMetrics; + private Map workshopMetrics; + private Map financialMetrics; + + @SuppressWarnings("unchecked") + @PostConstruct + public void init() { + try { + metrics = dashboardRestService.getDashboardMetrics(); + if (metrics != null) { + clientMetrics = (Map) metrics.get("clients"); + sessionMetrics = (Map) metrics.get("sessions"); + workshopMetrics = (Map) metrics.get("workshops"); + financialMetrics = (Map) metrics.get("financial"); + } + } catch (Exception e) { + // Fallback empty maps to avoid NPE + clientMetrics = Map.of(); + sessionMetrics = Map.of(); + workshopMetrics = Map.of(); + financialMetrics = Map.of(); + } + } + + /** + * Classe pour représenter une activité récente + */ + public static class Activity { + private String icon; + private String title; + private String description; + private String timestamp; + + public Activity(String icon, String title, String description, String timestamp) { + this.icon = icon; + this.title = title; + this.description = description; + this.timestamp = timestamp; + } + + public String getIcon() { + return icon; + } + + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public String getTimestamp() { + return timestamp; + } + } + + /** + * Classe pour représenter une tâche + */ + public static class Task { + private String title; + private String description; + private String clientName; + private String priority; + private String dueDate; + private boolean completed; + + public Task(String title, String description, String clientName, String priority, String dueDate, + boolean completed) { + this.title = title; + this.description = description; + this.clientName = clientName; + this.priority = priority; + this.dueDate = dueDate; + this.completed = completed; + } + + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public String getClientName() { + return clientName; + } + + public String getPriority() { + return priority; + } + + public String getDueDate() { + return dueDate; + } + + public boolean isCompleted() { + return completed; + } + } + + public List getRecentActivities() { + // Activités simulées pour l'instant car pas d'historique d'activités en DB + List activities = new ArrayList<>(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"); + activities.add(new Activity("pi pi-check", "Système prêt", "Transition vers Data Réelle effectuée", + LocalDateTime.now().format(formatter))); + return activities; + } + + public int getActiveClientsCount() { + return getIntMetric(clientMetrics, "activeClients"); + } + + public int getSessionsThisMonth() { + return getIntMetric(sessionMetrics, "sessionsThisMonth"); + } + + public int getPlannedWorkshops() { + // Using active or scheduled + return getIntMetric(workshopMetrics, "activeWorkshops"); + } + + public String getMonthlyRevenue() { + // From financial metrics + if (financialMetrics != null && financialMetrics.get("monthlyRevenue") != null) { + return "€" + financialMetrics.get("monthlyRevenue"); + } + return "€0"; + } + + public String getClientsGrowth() { + // Not calculated yet + return "+0%"; + } + + public String getSessionsGrowth() { + return "+0%"; + } + + public String getWorkshopsChange() { + return "0%"; + } + + public String getRevenueGrowth() { + return "+0%"; + } + + public List getTasks() { + return new ArrayList<>(); // Empty tasks for now + } + + public Object getRevenueChartModel() { + return null; + } + + public Object getClientTypeChartModel() { + return null; + } + + public String getRevenuePeriod() { + return revenuePeriod; + } + + public void setRevenuePeriod(String revenuePeriod) { + this.revenuePeriod = revenuePeriod; + } + + // Stats d'entreprise + public int getEnterpriseClients() { + // Can be approximate or estimated from total + return getIntMetric(clientMetrics, "totalClients"); + } + + public int getIndividualClients() { + return 0; + } + + // KPIs + public int getRevenueProgress() { + return 0; + } + + public int getClientProgress() { + return 0; + } + + public int getSessionProgress() { + return 0; + } + + public int getSatisfactionProgress() { + return 0; + } + + // Helpers + private int getIntMetric(Map map, String key) { + if (map != null && map.get(key) != null) { + Object val = map.get(key); + if (val instanceof Number) { + return ((Number) val).intValue(); + } + } + return 0; + } +} diff --git a/src/main/java/com/gbcm/client/beans/GuestPreferences.java b/src/main/java/com/gbcm/client/beans/GuestPreferences.java new file mode 100644 index 0000000..5f5a3f4 --- /dev/null +++ b/src/main/java/com/gbcm/client/beans/GuestPreferences.java @@ -0,0 +1,155 @@ +package com.gbcm.client.beans; + +import java.io.Serializable; + +import jakarta.enterprise.context.SessionScoped; +import jakarta.inject.Named; + +@Named("guestPreferences") +@SessionScoped +public class GuestPreferences implements Serializable { + + private String layout = "light"; + private String menuTheme = "light"; + private String topbarTheme = "light"; + private String menuMode = "layout-sidebar"; + private String darkMode = "light"; + private String inputStyleClass = ""; + private String inputStyle = "outlined"; + private String componentTheme = "blue"; + private boolean lightLogo = false; + + public String getLayout() { + return layout; + } + + public void setLayout(String layout) { + this.layout = layout; + } + + public String getMenuTheme() { + return menuTheme; + } + + public void setMenuTheme(String menuTheme) { + this.menuTheme = menuTheme; + } + + public String getTopbarTheme() { + return topbarTheme; + } + + public void setTopbarTheme(String topbarTheme) { + this.topbarTheme = topbarTheme; + } + + public String getMenuMode() { + return menuMode; + } + + public void setMenuMode(String menuMode) { + this.menuMode = menuMode; + } + + public String getDarkMode() { + return darkMode; + } + + public void setDarkMode(String darkMode) { + this.darkMode = darkMode; + this.layout = darkMode; + } + + public void toggleDarkMode() { + setDarkMode("dark".equals(darkMode) ? "light" : "dark"); + } + + public String getInputStyleClass() { + return inputStyleClass; + } + + public void setInputStyleClass(String inputStyleClass) { + this.inputStyleClass = inputStyleClass; + } + + public String getInputStyle() { + return inputStyle; + } + + public void setInputStyle(String inputStyle) { + this.inputStyle = inputStyle; + // Mettre à jour la classe CSS en fonction du style + if ("filled".equals(inputStyle)) { + this.inputStyleClass = "ui-input-filled"; + } else { + this.inputStyleClass = ""; + } + } + + public String getComponentTheme() { + return componentTheme; + } + + public void setComponentTheme(String componentTheme) { + this.componentTheme = componentTheme; + } + + // Propriétés manquantes pour le template Freya complet + public boolean isLightLogo() { + return "dark".equals(topbarTheme) || "dark".equals(darkMode); + } + + public void setLightLogo(boolean lightLogo) { + this.lightLogo = lightLogo; + } + + public void onMenuTypeChange() { + // Méthode appelée lors du changement de type de menu + } + + // Liste des thèmes de composants disponibles + public java.util.List getComponentThemes() { + java.util.List themes = new java.util.ArrayList<>(); + themes.add(new ComponentTheme("blue", "#007ad9", "Blue")); + themes.add(new ComponentTheme("green", "#10ac84", "Green")); + themes.add(new ComponentTheme("orange", "#ff9f43", "Orange")); + themes.add(new ComponentTheme("purple", "#5f27cd", "Purple")); + themes.add(new ComponentTheme("red", "#ee5a52", "Red")); + themes.add(new ComponentTheme("teal", "#00d2d3", "Teal")); + themes.add(new ComponentTheme("yellow", "#feca57", "Yellow")); + themes.add(new ComponentTheme("pink", "#ff6b9d", "Pink")); + themes.add(new ComponentTheme("indigo", "#3742fa", "Indigo")); + themes.add(new ComponentTheme("cyan", "#0abde3", "Cyan")); + return themes; + } + + // Classe interne pour les thèmes de composants + public static class ComponentTheme { + private String file; + private String color; + private String name; + + public ComponentTheme(String file, String color, String name) { + this.file = file; + this.color = color; + this.name = name; + } + + public String getFile() { return file; } + public void setFile(String file) { this.file = file; } + public String getColor() { return color; } + public void setColor(String color) { this.color = color; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } + } + + public String getLayoutClass() { + StringBuilder sb = new StringBuilder(); + sb.append("layout-wrapper "); + sb.append("layout-").append(layout).append(" "); + sb.append(menuTheme).append(" "); + sb.append(topbarTheme).append(" "); + sb.append("layout-menu-").append(menuMode); + return sb.toString(); + } +} diff --git a/src/main/java/com/gbcm/client/beans/NavigationBean.java b/src/main/java/com/gbcm/client/beans/NavigationBean.java new file mode 100644 index 0000000..d19bb3d --- /dev/null +++ b/src/main/java/com/gbcm/client/beans/NavigationBean.java @@ -0,0 +1,97 @@ +package com.gbcm.client.beans; + +import com.gbcm.client.beans.auth.AuthBean; +import jakarta.enterprise.context.SessionScoped; +import jakarta.inject.Named; +import jakarta.inject.Inject; +import java.io.Serializable; + +@Named("navigationBean") +@SessionScoped +public class NavigationBean implements Serializable { + + @Inject + private AuthBean authBean; + + /** + * Navigation vers la page d'accueil + */ + public String home() { + return "/index?faces-redirect=true"; + } + + /** + * Navigation vers le dashboard + */ + public String dashboard() { + if (!authBean.isAuthenticated()) { + return "/index?faces-redirect=true"; + } + return "/pages/dashboard?faces-redirect=true"; + } + + /** + * Navigation vers la gestion des clients + */ + public String clients() { + if (!authBean.isAuthenticated()) { + return "/index?faces-redirect=true"; + } + return "/pages/clients?faces-redirect=true"; + } + + /** + * Navigation vers le profil + */ + public String profile() { + if (!authBean.isAuthenticated()) { + return "/index?faces-redirect=true"; + } + return "/pages/profile?faces-redirect=true"; + } + + /** + * Navigation vers les projets + */ + public String projects() { + if (!authBean.isAuthenticated()) { + return "/index?faces-redirect=true"; + } + return "/pages/projects?faces-redirect=true"; + } + + /** + * Navigation vers les rapports + */ + public String reports() { + if (!authBean.isAuthenticated()) { + return "/index?faces-redirect=true"; + } + return "/pages/reports?faces-redirect=true"; + } + + /** + * Navigation vers les paramètres + */ + public String settings() { + if (!authBean.isAuthenticated()) { + return "/index?faces-redirect=true"; + } + return "/pages/settings?faces-redirect=true"; + } + + /** + * Vérifie si la page actuelle est active + */ + public boolean isPageActive(String page) { + // Cette méthode peut être étendue pour vérifier l'URL actuelle + return false; + } + + /** + * Obtient la classe CSS pour un élément de menu + */ + public String getMenuItemClass(String page) { + return isPageActive(page) ? "active-menuitem" : ""; + } +} diff --git a/src/main/java/com/gbcm/client/beans/WorkshopBean.java b/src/main/java/com/gbcm/client/beans/WorkshopBean.java new file mode 100644 index 0000000..36a1f11 --- /dev/null +++ b/src/main/java/com/gbcm/client/beans/WorkshopBean.java @@ -0,0 +1,36 @@ +package com.gbcm.client.beans; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import com.gbcm.client.service.WorkshopRestService; +import com.gbcm.server.api.dto.workshop.WorkshopDTO; +import com.gbcm.server.api.dto.common.PagedResponseDTO; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; + +@Named("workshopBean") +@RequestScoped +public class WorkshopBean implements Serializable { + + private static final Logger logger = Logger.getLogger(WorkshopBean.class.getName()); + + @Inject + private WorkshopRestService workshopRestService; + + public List getWorkshops() { + try { + logger.info("Récupération de la liste des ateliers"); + PagedResponseDTO pagedResponse = workshopRestService.getWorkshops(0, 50, null, null, null, + null, null); + return pagedResponse.getContent(); + } catch (Exception e) { + logger.severe("Erreur lors de la récupération des ateliers: " + e.getMessage()); + return new ArrayList<>(); + } + } +} diff --git a/src/main/java/com/gbcm/client/beans/auth/AuthBean.java b/src/main/java/com/gbcm/client/beans/auth/AuthBean.java new file mode 100644 index 0000000..34bb07f --- /dev/null +++ b/src/main/java/com/gbcm/client/beans/auth/AuthBean.java @@ -0,0 +1,319 @@ +package com.gbcm.client.beans.auth; + +import java.io.Serializable; +import java.util.Set; +import java.util.logging.Logger; + +import org.eclipse.microprofile.jwt.JsonWebToken; + +import io.quarkus.oidc.IdToken; +import io.quarkus.oidc.OidcSession; +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.enterprise.context.SessionScoped; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.inject.Inject; +import jakarta.inject.Named; + +@Named("authBean") +@SessionScoped +public class AuthBean implements Serializable { + + private static final Logger logger = Logger.getLogger(AuthBean.class.getName()); + + @Inject + SecurityIdentity securityIdentity; + + @Inject + OidcSession oidcSession; + + @Inject + @IdToken + JsonWebToken idToken; + + /** + * Vérifie si l'utilisateur est authentifié + */ + public boolean isAuthenticated() { + return securityIdentity != null && !securityIdentity.isAnonymous(); + } + + /** + * Obtient le nom d'utilisateur + */ + public String getUsername() { + if (!isAuthenticated()) { + return "Invité"; + } + return securityIdentity.getPrincipal().getName(); + } + + /** + * Obtient le nom d'utilisateur (alias pour le topbar) + */ + public String getUserName() { + return getFullName(); + } + + /** + * Obtient l'email de l'utilisateur depuis le token ID + */ + public String getEmail() { + if (!isAuthenticated() || idToken == null) { + return "guest@example.com"; + } + + String email = idToken.getClaim("email"); + return email != null ? email : getUsername(); + } + + /** + * Obtient l'email de l'utilisateur (alias pour le topbar) + */ + public String getUserEmail() { + return getEmail(); + } + + /** + * Obtient l'avatar de l'utilisateur + */ + public String getUserAvatar() { + if (!isAuthenticated() || idToken == null) { + return "images/avatar-gbcm.png"; + } + + // Vérifier s'il y a une photo dans le token + String picture = idToken.getClaim("picture"); + if (picture != null && !picture.trim().isEmpty()) { + return picture; + } + + // Avatar par défaut GBCM + return "images/avatar-gbcm.png"; + } + + /** + * Obtient le nom complet de l'utilisateur + */ + public String getFullName() { + if (!isAuthenticated() || idToken == null) { + return "Utilisateur Invité"; + } + + String givenName = idToken.getClaim("given_name"); + String familyName = idToken.getClaim("family_name"); + + if (givenName != null && familyName != null) { + return givenName + " " + familyName; + } + + String name = idToken.getClaim("name"); + return name != null ? name : getUsername(); + } + + /** + * Obtient les rôles de l'utilisateur + */ + public Set getRoles() { + if (!isAuthenticated()) { + return Set.of("GUEST"); + } + return securityIdentity.getRoles(); + } + + /** + * Vérifie si l'utilisateur a un rôle spécifique + */ + public boolean hasRole(String role) { + return isAuthenticated() && securityIdentity.hasRole(role); + } + + /** + * Vérifie si l'utilisateur est administrateur + */ + public boolean isAdmin() { + return hasRole("ADMIN"); + } + + /** + * Vérifie si l'utilisateur est manager + */ + public boolean isManager() { + return hasRole("MANAGER"); + } + + /** + * Vérifie si l'utilisateur est coach + */ + public boolean isCoach() { + return hasRole("COACH"); + } + + /** + * Vérifie si l'utilisateur est client + */ + public boolean isClient() { + return hasRole("CLIENT"); + } + + /** + * Vérifie si l'utilisateur est prospect + */ + public boolean isProspect() { + return hasRole("PROSPECT"); + } + + /** + * Obtient le rôle principal de l'utilisateur + */ + public String getPrimaryRole() { + if (!isAuthenticated()) { + return "GUEST"; + } + + Set roles = getRoles(); + if (roles.contains("ADMIN")) return "ADMIN"; + if (roles.contains("MANAGER")) return "MANAGER"; + if (roles.contains("COACH")) return "COACH"; + if (roles.contains("CLIENT")) return "CLIENT"; + if (roles.contains("PROSPECT")) return "PROSPECT"; + + return roles.isEmpty() ? "USER" : roles.iterator().next(); + } + + /** + * Déconnexion OIDC + */ + public String logout() { + try { + logger.info("Début de la déconnexion OIDC"); + + if (oidcSession != null) { + logger.info("Déconnexion de la session OIDC"); + oidcSession.logout().await().indefinitely(); + } + + // Invalider la session JSF + FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); + + // Message de confirmation + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Déconnexion réussie", + "Vous avez été déconnecté avec succès.")); + + logger.info("Déconnexion OIDC terminée"); + return "/index?faces-redirect=true"; + + } catch (Exception e) { + logger.severe("Erreur lors de la déconnexion OIDC: " + e.getMessage()); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de déconnexion", + "Une erreur s'est produite lors de la déconnexion.")); + return null; + } + } + + /** + * Obtient les informations du token ID pour debug + */ + public String getTokenInfo() { + if (!isAuthenticated() || idToken == null) { + return "Aucun token disponible"; + } + + StringBuilder info = new StringBuilder(); + info.append("Issuer: ").append(idToken.getIssuer()).append("\n"); + info.append("Subject: ").append(idToken.getSubject()).append("\n"); + info.append("Expiration: ").append(idToken.getExpirationTime()).append("\n"); + info.append("Issued At: ").append(idToken.getIssuedAtTime()).append("\n"); + + return info.toString(); + } + + /** + * Obtient les informations détaillées du token pour la page profil + */ + public TokenInfo getTokenInfoDetails() { + if (!isAuthenticated() || idToken == null) { + return new TokenInfo(); + } + + return new TokenInfo( + idToken.getIssuer(), + idToken.getSubject(), + idToken.getAudience() != null ? String.join(", ", idToken.getAudience()) : "N/A", + idToken.getExpirationTime(), + idToken.getIssuedAtTime() + ); + } + + /** + * Classe interne pour les informations du token + */ + public static class TokenInfo { + private String issuer; + private String subject; + private String audience; + private Long expirationTime; + private Long issuedAt; + + public TokenInfo() { + this.issuer = "N/A"; + this.subject = "N/A"; + this.audience = "N/A"; + this.expirationTime = 0L; + this.issuedAt = 0L; + } + + public TokenInfo(String issuer, String subject, String audience, Long expirationTime, Long issuedAt) { + this.issuer = issuer; + this.subject = subject; + this.audience = audience; + this.expirationTime = expirationTime; + this.issuedAt = issuedAt; + } + + public String getIssuer() { return issuer; } + public String getSubject() { return subject; } + public String getAudience() { return audience; } + public Long getExpirationTime() { return expirationTime; } + public Long getIssuedAt() { return issuedAt; } + } + + /** + * Navigation vers le login + */ + public String login() { + return "/login?faces-redirect=true"; + } + + /** + * Navigation vers le dashboard + */ + public String dashboard() { + if (!isAuthenticated()) { + return login(); + } + return "/pages/dashboard?faces-redirect=true"; + } + + /** + * Navigation vers le profil + */ + public String profile() { + if (!isAuthenticated()) { + return login(); + } + return "/pages/profile?faces-redirect=true"; + } + + /** + * Navigation vers les clients + */ + public String clients() { + if (!isAuthenticated()) { + return login(); + } + return "/pages/clients?faces-redirect=true"; + } +} diff --git a/src/main/java/com/gbcm/client/controller/IndexController.java b/src/main/java/com/gbcm/client/controller/IndexController.java new file mode 100644 index 0000000..6ad50cb --- /dev/null +++ b/src/main/java/com/gbcm/client/controller/IndexController.java @@ -0,0 +1,21 @@ +package com.gbcm.client.controller; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response; +import java.net.URI; + +/** + * Contrôleur pour gérer la redirection vers la page d'accueil + */ +@Path("/") +public class IndexController { + + /** + * Redirige la racine vers index.xhtml + */ + @GET + public Response redirectToIndex() { + return Response.seeOther(URI.create("index.xhtml")).build(); + } +} diff --git a/src/main/java/com/gbcm/client/resources/HomeController.java b/src/main/java/com/gbcm/client/resources/HomeController.java deleted file mode 100644 index fc8fff0..0000000 --- a/src/main/java/com/gbcm/client/resources/HomeController.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.gbcm.client.resources; - -import io.quarkus.qute.Template; -import io.quarkus.qute.TemplateInstance; -import io.quarkus.security.identity.SecurityIdentity; -import io.quarkus.oidc.OidcSession; -import io.quarkus.oidc.IdToken; -import org.eclipse.microprofile.jwt.JsonWebToken; - -import jakarta.inject.Inject; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; - -@Path("/") -public class HomeController { - - @Inject - Template index; - - @Inject - SecurityIdentity securityIdentity; - - @Inject - OidcSession oidcSession; - - @Inject - @IdToken - JsonWebToken idToken; - - @GET - @Produces(MediaType.TEXT_HTML) - public TemplateInstance index() { - return index - .data("user", getCurrentUser()) - .data("authenticated", isAuthenticated()) - .data("title", "Accueil - GBCM"); - } - - @GET - @Path("/index") - @Produces(MediaType.TEXT_HTML) - public TemplateInstance indexPage() { - return index(); - } - - private boolean isAuthenticated() { - return securityIdentity != null && !securityIdentity.isAnonymous(); - } - - private UserInfo getCurrentUser() { - if (!isAuthenticated()) { - return new UserInfo("Invité", "guest@example.com", "GUEST"); - } - - String username = securityIdentity.getPrincipal().getName(); - String email = idToken != null ? idToken.getClaim("email") : username; - String role = securityIdentity.getRoles().isEmpty() ? "USER" : - securityIdentity.getRoles().iterator().next(); - - return new UserInfo(username, email, role); - } - - public static class UserInfo { - public final String name; - public final String email; - public final String role; - - public UserInfo(String name, String email, String role) { - this.name = name; - this.email = email; - this.role = role; - } - } -} diff --git a/src/main/java/com/gbcm/client/resources/PageController.java b/src/main/java/com/gbcm/client/resources/PageController.java deleted file mode 100644 index 2202044..0000000 --- a/src/main/java/com/gbcm/client/resources/PageController.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.gbcm.client.resources; - -import io.quarkus.qute.Template; -import io.quarkus.qute.TemplateInstance; -import io.quarkus.security.identity.SecurityIdentity; -import io.quarkus.oidc.OidcSession; -import io.quarkus.oidc.IdToken; -import org.eclipse.microprofile.jwt.JsonWebToken; - -import jakarta.inject.Inject; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; - -@Path("/pages") -public class PageController { - - @Inject - Template dashboard; - - @Inject - Template clients; - - @Inject - Template profile; - - @Inject - SecurityIdentity securityIdentity; - - @Inject - OidcSession oidcSession; - - @Inject - @IdToken - JsonWebToken idToken; - - @GET - @Path("/dashboard") - @Produces(MediaType.TEXT_HTML) - public TemplateInstance dashboard() { - return dashboard - .data("user", getCurrentUser()) - .data("authenticated", isAuthenticated()) - .data("title", "Tableau de Bord - GBCM"); - } - - @GET - @Path("/clients") - @Produces(MediaType.TEXT_HTML) - public TemplateInstance clients() { - return clients - .data("user", getCurrentUser()) - .data("authenticated", isAuthenticated()) - .data("title", "Gestion des Clients - GBCM"); - } - - @GET - @Path("/profile") - @Produces(MediaType.TEXT_HTML) - public TemplateInstance profile() { - return profile - .data("user", getCurrentUser()) - .data("authenticated", isAuthenticated()) - .data("title", "Profil Utilisateur - GBCM") - .data("tokenInfo", getTokenInfo()); - } - - private boolean isAuthenticated() { - return securityIdentity != null && !securityIdentity.isAnonymous(); - } - - private UserInfo getCurrentUser() { - if (!isAuthenticated()) { - return new UserInfo("Invité", "guest@example.com", "GUEST"); - } - - String username = securityIdentity.getPrincipal().getName(); - String email = idToken != null ? idToken.getClaim("email") : username; - String role = securityIdentity.getRoles().isEmpty() ? "USER" : - securityIdentity.getRoles().iterator().next(); - - return new UserInfo(username, email, role); - } - - private String getTokenInfo() { - if (idToken == null) { - return "Aucun token disponible"; - } - - StringBuilder info = new StringBuilder(); - info.append("Issuer: ").append(idToken.getIssuer()).append("\n"); - info.append("Subject: ").append(idToken.getSubject()).append("\n"); - info.append("Expiration: ").append(idToken.getExpirationTime()).append("\n"); - info.append("Issued At: ").append(idToken.getIssuedAtTime()).append("\n"); - - return info.toString(); - } - - public static class UserInfo { - public final String name; - public final String email; - public final String role; - - public UserInfo(String name, String email, String role) { - this.name = name; - this.email = email; - this.role = role; - } - } -} diff --git a/src/main/java/com/gbcm/client/service/ClientRestService.java b/src/main/java/com/gbcm/client/service/ClientRestService.java new file mode 100644 index 0000000..159494e --- /dev/null +++ b/src/main/java/com/gbcm/client/service/ClientRestService.java @@ -0,0 +1,127 @@ +package com.gbcm.client.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import com.gbcm.server.api.dto.client.ClientDTO; +import com.gbcm.server.api.dto.client.CreateClientDTO; +import com.gbcm.server.api.dto.client.UpdateClientDTO; +import com.gbcm.server.api.dto.common.PagedResponseDTO; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +/** + * Service REST client pour communiquer avec l'API clients du serveur GBCM. + * Utilise MicroProfile REST Client pour les appels HTTP. + * + * @author GBCM Development Team + * @version 1.0 + * @since 1.0 + */ +@ApplicationScoped +public class ClientRestService { + + private static final Logger logger = LoggerFactory.getLogger(ClientRestService.class); + + @Inject + @RestClient + private ClientRestClient clientRestClient; + + /** + * Récupère la liste paginée des clients + */ + public PagedResponseDTO getClients(int page, int size, String sort, + String status, String industry, String search) { + try { + logger.info("Appel API pour récupérer les clients - page: {}, size: {}", page, size); + return clientRestClient.getClients(page, size, sort, status, industry, search); + } catch (Exception e) { + logger.error("Erreur lors de l'appel API getClients: " + e.getMessage(), e); + throw new RuntimeException("Impossible de récupérer les clients", e); + } + } + + /** + * Récupère un client par son ID + */ + public ClientDTO getClientById(Long id) { + try { + logger.info("Appel API pour récupérer le client ID: {}", id); + return clientRestClient.getClientById(id); + } catch (Exception e) { + logger.error("Erreur lors de l'appel API getClientById: " + e.getMessage(), e); + throw new RuntimeException("Impossible de récupérer le client", e); + } + } + + /** + * Crée un nouveau client + */ + public ClientDTO createClient(CreateClientDTO createClientDTO) { + try { + logger.info("Appel API pour créer un client: {}", createClientDTO.getCompanyName()); + return clientRestClient.createClient(createClientDTO); + } catch (Exception e) { + logger.error("Erreur lors de l'appel API createClient: " + e.getMessage(), e); + throw new RuntimeException("Impossible de créer le client", e); + } + } + + /** + * Met à jour un client + */ + public ClientDTO updateClient(Long id, UpdateClientDTO updateClientDTO) { + try { + logger.info("Appel API pour mettre à jour le client ID: {}", id); + return clientRestClient.updateClient(id, updateClientDTO); + } catch (Exception e) { + logger.error("Erreur lors de l'appel API updateClient: " + e.getMessage(), e); + throw new RuntimeException("Impossible de mettre à jour le client", e); + } + } + + /** + * Interface REST Client pour les appels API + */ + @RegisterRestClient + @Path("/clients") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public interface ClientRestClient { + + @GET + @Path("/dev") + PagedResponseDTO getClients( + @QueryParam("page") int page, + @QueryParam("size") int size, + @QueryParam("sort") String sort, + @QueryParam("status") String status, + @QueryParam("industry") String industry, + @QueryParam("search") String search + ); + + @GET + @Path("/{id}") + ClientDTO getClientById(@PathParam("id") Long id); + + @POST + ClientDTO createClient(CreateClientDTO createClientDTO); + + @PUT + @Path("/{id}") + ClientDTO updateClient(@PathParam("id") Long id, UpdateClientDTO updateClientDTO); + } +} diff --git a/src/main/java/com/gbcm/client/service/CoachRestService.java b/src/main/java/com/gbcm/client/service/CoachRestService.java new file mode 100644 index 0000000..806a5c9 --- /dev/null +++ b/src/main/java/com/gbcm/client/service/CoachRestService.java @@ -0,0 +1,70 @@ +package com.gbcm.client.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import com.gbcm.server.api.dto.coach.CoachDTO; +import com.gbcm.server.api.dto.coach.CreateCoachDTO; +import com.gbcm.server.api.dto.coach.UpdateCoachDTO; +import com.gbcm.server.api.dto.common.PagedResponseDTO; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; + +@ApplicationScoped +public class CoachRestService { + + private static final Logger logger = LoggerFactory.getLogger(CoachRestService.class); + + @Inject + @RestClient + private CoachRestClient coachRestClient; + + public PagedResponseDTO getCoaches(int page, int size, String sort, + String status, String specialization, boolean availableOnly, String search) { + try { + logger.info("Appel API pour récupérer les coachs - page: {}, size: {}", page, size); + // On utilise l'endpoint dev ou standard selon dispo, ici on assume standard + // sans dev prefix pour test + // Mais si Client utilise /dev, faisons pareil pour consistance si dispo. + // CoachResource n'a pas forcement /dev. Checkons CoachResource. + // Je vais utiliser l'interface RestClient definie plus bas. + return coachRestClient.getCoaches(page, size, sort, status, specialization, availableOnly, search); + } catch (Exception e) { + logger.error("Erreur lors de l'appel API getCoaches: " + e.getMessage(), e); + throw new RuntimeException("Impossible de récupérer les coachs", e); + } + } + + public CoachDTO getCoachById(Long id) { + return coachRestClient.getCoachById(id); + } + + // Autres méthodes create/update si besoin + + @RegisterRestClient + @Path("/coaches") // Base path relative to quarkus.rest-client.url + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public interface CoachRestClient { + + @GET + PagedResponseDTO getCoaches( + @QueryParam("page") int page, + @QueryParam("size") int size, + @QueryParam("sort") String sort, + @QueryParam("status") String status, + @QueryParam("specialization") String specialization, + @QueryParam("availableOnly") boolean availableOnly, + @QueryParam("search") String search); + + @GET + @Path("/{id}") + CoachDTO getCoachById(@PathParam("id") Long id); + } +} diff --git a/src/main/java/com/gbcm/client/service/CoachingSessionRestService.java b/src/main/java/com/gbcm/client/service/CoachingSessionRestService.java new file mode 100644 index 0000000..717c6bc --- /dev/null +++ b/src/main/java/com/gbcm/client/service/CoachingSessionRestService.java @@ -0,0 +1,58 @@ +package com.gbcm.client.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import com.gbcm.server.api.dto.session.CoachingSessionDTO; +import com.gbcm.server.api.dto.common.PagedResponseDTO; +import com.gbcm.server.api.enums.SessionStatus; +import com.gbcm.server.api.enums.ServiceType; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; + +@ApplicationScoped +public class CoachingSessionRestService { + + private static final Logger logger = LoggerFactory.getLogger(CoachingSessionRestService.class); + + @Inject + @RestClient + private CoachingSessionRestClient sessionRestClient; + + public PagedResponseDTO getCoachingSessions(int page, int size, String sort, + SessionStatus status, ServiceType serviceType, + Long coachId, Long clientId, String search) { + try { + logger.info("Appel API pour récupérer les sessions"); + return sessionRestClient.getCoachingSessions(page, size, sort, status, serviceType, coachId, clientId, + search); + } catch (Exception e) { + logger.error("Erreur lors de l'appel API getCoachingSessions: " + e.getMessage(), e); + throw new RuntimeException("Impossible de récupérer les sessions", e); + } + } + + @RegisterRestClient + @Path("/sessions") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public interface CoachingSessionRestClient { + + @GET + PagedResponseDTO getCoachingSessions( + @QueryParam("page") int page, + @QueryParam("size") int size, + @QueryParam("sort") String sort, + @QueryParam("status") SessionStatus status, + @QueryParam("serviceType") ServiceType serviceType, + @QueryParam("coachId") Long coachId, + @QueryParam("clientId") Long clientId, + @QueryParam("search") String search); + } +} diff --git a/src/main/java/com/gbcm/client/service/DashboardRestService.java b/src/main/java/com/gbcm/client/service/DashboardRestService.java new file mode 100644 index 0000000..3566f35 --- /dev/null +++ b/src/main/java/com/gbcm/client/service/DashboardRestService.java @@ -0,0 +1,48 @@ +package com.gbcm.client.service; + +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; + +@ApplicationScoped +public class DashboardRestService { + + private static final Logger logger = LoggerFactory.getLogger(DashboardRestService.class); + + @Inject + @RestClient + private DashboardRestClient dashboardRestClient; + + public Map getDashboardMetrics() { + try { + logger.info("Appel API pour récupérer les métriques dashboard"); + // Utilise l'endpoint /dev pour éviter les problèmes d'auth temporaires si le + // client n'est pas loggé ou auth bypass + // Si DashboardResource a /dev, utilisons-le. J'ai vu getDashboardMetricsForDev + // sur /dev. + return dashboardRestClient.getDashboardMetricsDev(); + } catch (Exception e) { + logger.error("Erreur lors de l'appel API dashboard metrics: " + e.getMessage(), e); + throw new RuntimeException("Impossible de récupérer les métriques", e); + } + } + + @RegisterRestClient + @Path("/dashboard") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public interface DashboardRestClient { + + @GET + @Path("/dev") + Map getDashboardMetricsDev(); + } +} diff --git a/src/main/java/com/gbcm/client/service/WorkshopRestService.java b/src/main/java/com/gbcm/client/service/WorkshopRestService.java new file mode 100644 index 0000000..6d216ad --- /dev/null +++ b/src/main/java/com/gbcm/client/service/WorkshopRestService.java @@ -0,0 +1,57 @@ +package com.gbcm.client.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import com.gbcm.server.api.dto.workshop.WorkshopDTO; +import com.gbcm.server.api.dto.common.PagedResponseDTO; +import com.gbcm.server.api.enums.WorkshopPackage; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; + +@ApplicationScoped +public class WorkshopRestService { + + private static final Logger logger = LoggerFactory.getLogger(WorkshopRestService.class); + + @Inject + @RestClient + private WorkshopRestClient workshopRestClient; + + public PagedResponseDTO getWorkshops(int page, int size, String sort, + Object status, WorkshopPackage workshopPackage, + Long coachId, String search) { + try { + logger.info("Appel API pour récupérer les ateliers"); + // Cast status if needed, assuming String matching + String statusStr = status != null ? status.toString() : null; + return workshopRestClient.getWorkshops(page, size, sort, statusStr, workshopPackage, coachId, search); + } catch (Exception e) { + logger.error("Erreur lors de l'appel API getWorkshops: " + e.getMessage(), e); + throw new RuntimeException("Impossible de récupérer les ateliers", e); + } + } + + @RegisterRestClient + @Path("/workshops") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public interface WorkshopRestClient { + + @GET + PagedResponseDTO getWorkshops( + @QueryParam("page") int page, + @QueryParam("size") int size, + @QueryParam("sort") String sort, + @QueryParam("status") String status, + @QueryParam("workshopPackage") WorkshopPackage workshopPackage, + @QueryParam("coachId") Long coachId, + @QueryParam("search") String search); + } +} diff --git a/src/main/resources/META-INF/resources/WEB-INF/faces-config.xml b/src/main/resources/META-INF/resources/WEB-INF/faces-config.xml new file mode 100644 index 0000000..fc95632 --- /dev/null +++ b/src/main/resources/META-INF/resources/WEB-INF/faces-config.xml @@ -0,0 +1,70 @@ + + + + + + fr + en + fr + + + + messages + msg + + + + + + org.primefaces.component.FreyaMenu + org.primefaces.freya.component.FreyaMenu + + + + + org.primefaces.component + org.primefaces.component.FreyaMenuRenderer + org.primefaces.freya.component.FreyaMenuRenderer + + + + + + * + + + dashboard + /pages/dashboard.xhtml + + + + + profile + /pages/profile.xhtml + + + + + clients + /pages/clients.xhtml + + + + + home + /index.xhtml + + + + + login + /login.xhtml + + + + + diff --git a/src/main/webapp/WEB-INF/freya-templates/config.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/config.xhtml similarity index 100% rename from src/main/webapp/WEB-INF/freya-templates/config.xhtml rename to src/main/resources/META-INF/resources/WEB-INF/freya-templates/config.xhtml diff --git a/src/main/webapp/WEB-INF/freya-templates/footer.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/footer.xhtml similarity index 100% rename from src/main/webapp/WEB-INF/freya-templates/footer.xhtml rename to src/main/resources/META-INF/resources/WEB-INF/freya-templates/footer.xhtml diff --git a/src/main/resources/META-INF/resources/WEB-INF/freya-templates/menu.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/menu.xhtml new file mode 100644 index 0000000..6f0e681 --- /dev/null +++ b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/menu.xhtml @@ -0,0 +1,61 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/WEB-INF/freya-templates/public-template.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/public-template.xhtml new file mode 100644 index 0000000..c24f0bd --- /dev/null +++ b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/public-template.xhtml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + <ui:insert name="title">GBCM - Global Business Consulting & Management</ui:insert> + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + GBCM + + +
+ + + Accueil + +
+
+
+
+ + +
+ +

Contenu par défaut

+
+
+ + + + + + + + +
+ diff --git a/src/main/webapp/WEB-INF/freya-templates/rightpanel.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/rightpanel.xhtml similarity index 100% rename from src/main/webapp/WEB-INF/freya-templates/rightpanel.xhtml rename to src/main/resources/META-INF/resources/WEB-INF/freya-templates/rightpanel.xhtml diff --git a/src/main/webapp/WEB-INF/freya-templates/template.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/template.xhtml similarity index 89% rename from src/main/webapp/WEB-INF/freya-templates/template.xhtml rename to src/main/resources/META-INF/resources/WEB-INF/freya-templates/template.xhtml index 2ecdbbc..b63d40c 100644 --- a/src/main/webapp/WEB-INF/freya-templates/template.xhtml +++ b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/template.xhtml @@ -14,7 +14,9 @@ - <ui:insert name="title">GBCM - Global Business Consulting & Management</ui:insert> + <ui:insert name="title">GBCM - Global Business Consulting and Management</ui:insert> + + @@ -23,22 +25,22 @@
- + -
+
- +