Tutoriel : Créer un accueil de rubrique en refronte
Vue d'ensemble
Un accueil de rubrique permet définir un écran à afficher lorsque l'utilisateur se rend sur la rubrique. Il peut être de différents types (moteur de recherche, fiche, liste automatique...). La documentation utilisateur est disponible ici : https://docs.ksup.org/fr/version-6-7/utiliser/rubriques # TODO : URL à éditer
Architecture générale
L'accueil de rubrique suit le pattern MVC de Spring et s'intègre dans l'architecture K-Sup avec les composants suivants :
- Classe d'accueil de rubrique : Hérite de
DefaultPageAccueilRubrique - Bean de page d'accueil : Implémente
BeanPageAccueil - View Model : Modèle de vue pour le front
- View Preparer : Prépare les données pour la vue
- Configuration : Configuration Spring
Étapes de création
Le tutoriel ci-dessous nous permettra de créer un accueil de rubrique qui affiche un titre et une description.
Créer le Bean de page d'accueil
Cette classe représente les données relatives à la page d'accueil, dans fr.votreprojet.votremodule.rubrique. La classe doit implémenter BeanPageAccueil.
package fr.votreprojet.votremodule.rubrique;
import java.io.Serial;
import org.apache.commons.lang3.StringUtils;
import com.kportal.extension.module.plugin.rubrique.BeanPageAccueil;
/**
* Bean de la page d'accueil pour [Description de votre module].
*/
public class VotreModuleBeanPageAccueil implements BeanPageAccueil {
/**
* serialVersionUID.
*/
@Serial
private static final long serialVersionUID = -5646188278620975957L;
/**
* Le titre à afficher.
*/
private String titre;
/**
* La description à afficher.
*/
private String description;
@Override
public String getUrlRubrique(final String codeRubrique, final String langue, final boolean ampersands) {
return StringUtils.EMPTY; // Indispensable actuellement pour le front legacy
}
@Override
public String getUrlModification(final String codeRubrique, final String langue, final boolean ampersands) {
return StringUtils.EMPTY; // Indispensable actuellement pour le front legacy
}
@Override
public String getLibelleAffichable() {
return StringUtils.EMPTY; // Indispensable actuellement pour le front legacy
}
public String getTitre() {
return titre;
}
public void setTitre(final String titre) {
this.titre = titre;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
}
- Notes :
- Les méthodes
getUrlRubrique,getUrlModificationetgetLibelleAffichbleétaient utilisées pour le front legacy. Il est encore nécessaire de les implémenter jusqu'à ce que le ticket CORE-7775 soit résolu.
- Les méthodes
Créer la classe d'accueil de rubrique
Il faut ensuite créer la classe fr.votreprojet.votremodule.rubrique.VotreModuleAccueilRubrique représentant l'accueil de rubrique (enregistrement et affichage en BO). Elle doit
hériter de DefaultPageAccueilRubrique. Elle contient les méthodes preparerPRINCIPAL et traiterPRINCIPAL relatives à l'enregistrement et l'affichage de l'accueil de rubrique
en BO :
package fr.votreprojet.votremodule.rubrique;
import java.io.Serial;
import java.util.Map;
import com.kportal.extension.module.plugin.rubrique.DefaultPageAccueilRubrique;
/**
* Accueil de rubrique permettant d'afficher [Description de votre fonctionnalité].
*/
public class VotreModuleAccueilRubrique extends DefaultPageAccueilRubrique<VotreModuleBeanPageAccueil> {
/**
* Le type d'accueil de rubrique.
*/
public static final String TYPE_ACCUEIL_RUBRIQUE = "8010";
/**
* serialVersionUID.
*/
@Serial
private static final long serialVersionUID = 2744706230254106056L;
@Override
public void preparerPRINCIPAL(final Map<String, Object> infoBean, final VotreModuleBeanPageAccueil beanPageAccueil) {
// Logique de préparation des données si nécessaire
infoBean.put("TITRE", beanPageAccueil.getTitre());
infoBean.put("DESCRIPTION", beanPageAccueil.getDescription());
}
@Override
public void traiterPRINCIPAL(final Map<String, Object> infoBean, final VotreModuleBeanPageAccueil beanPageAccueil) {
// Logique de traitement des données si nécessaire
beanPageAccueil.setTitre((String) infoBean.get("TITRE"));
beanPageAccueil.setDescription((String) infoBean.get("DESCRIPTION"));
}
}
- La constante
TYPE_ACCUEIL_RUBRIQUEreprésente le code de l'accueil de rubrique. Il doit être unique - Dans la méthode
preparerPRINCIPAL, on affecte à l'infobean les données qui seront affichées en back-office. - Dans la méthode
traiterPRINCIPAL, on récupère les données de l'infobean pour pouvoir ensuite les enregistrer en base.
Créer le modèle de vue
Il faut ensuite créer un modèle de vue, permettant d'afficher les données. Dans notre cas, nous allons afficher un titre et une description contribués en back-office au sein d'une page. Dans
fr.votreprojet.votremodule.view.model, on vient créer une classe VotreModuleViewModel.
package fr.votreprojet.votremodule.view.model;
import com.kosmos.body.BodyViewModel;
/**
* Modèle de vue pour l'affichage de [Description].
*/
public class VotreModuleViewModel extends BodyViewModel {
/**
* Le titre.
*/
private String titre;
/**
* La description.
*/
private String description;
/**
* Constructeur.
*/
public VotreModuleViewModel() {
super();
}
// Getters et setters
public String getTitre() {
return titre;
}
public void setTitre(final String titre) {
this.titre = titre;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
}
- Notes :
- Dans cet exemple, nous souhaitons afficher des données au sein d'une page sur un site K-Sup. Nous reprenons donc l'entête et le pied de page définis par défaut pour le site.
Afin de ne surcharger que le contenu relatif au corps de la page, nous étendons
BodyViewModel. (cf. Principe d'intégration)).
- Dans cet exemple, nous souhaitons afficher des données au sein d'une page sur un site K-Sup. Nous reprenons donc l'entête et le pied de page définis par défaut pour le site.
Afin de ne surcharger que le contenu relatif au corps de la page, nous étendons
Créer le préparateur de vue
La classe fr.votreprojet.votremodule.view.preparer.VotreModuleViewPreparer permet de préparer les données qui vont être affichées.
package fr.votreprojet.votremodule.view.preparer;
import java.util.List;
import java.util.Map;
import com.kosmos.context.front.FrontContext;
import com.kosmos.context.front.SectionContext;
import com.kosmos.preparer.IViewPreparer;
import com.kosmos.section.home.AbstractSectionHomeViewPreparer;
/**
* Préparateur de la vue de [Description].
*/
public class VotreModuleViewPreparer extends AbstractSectionHomeViewPreparer<VotreModuleViewModel> {
@Override
public boolean accept(final FrontContext context) {
return super.accept(context) && SectionContext.of(context).getBeanPageAccueil() instanceof VotreModuleBeanPageAccueil;
}
@Override
public VotreModuleViewModel prepare(final FrontContext context, final Map<String, List<IViewPreparer>> preparers) {
final VotreModuleViewModel viewModel = super.prepare(context, preparers);
final SectionContext sectionContext = SectionContext.of(context);
// Préparer les données du viewModel
final VotreModuleBeanPageAccueil beanPageAccueil = (VotreModuleBeanPageAccueil) sectionContext.getBeanPageAccueil();
viewModel.setTitre(beanPageAccueil.getTitre());
viewModel.setDescription(beanPageAccueil.getDescription());
return viewModel;
}
}
- *Notes :
- La classe étend de
AbstractSectionHomeViewPreparerpuisqu'on veut afficher des données au sein d'une page K-Sup. Pour d'autres affichages, d'autres préparateurs de vue abstraits sont disponibles. - Méthode
accept: cette méthode permet de savoir si le préparateur de vue peut préparer les données pour le bean de page d'accueil courant ; - Méthode
prepare: cette méthode va préparer les données à afficher. Puisqu'on est au sein d'une page K-Sup, on récupère le contexte de la section (SectionContext).
- La classe étend de
Fichiers de propriétés pour l'internationalisation
On crée les fichiers relatifs aux traductions dans src/main/resources. Par exemple, pour les messages en français, on crée le fichier Application_votremodule_fr_FR.properties
avec :
# Votre Module
## Accueil de rubrique
RUBRIQUE.PAGE_ACCUEIL_VOTRE_MODULE=Votre premier accueil de rubrique
VOTRE_PROJET.VOTRE_MODULE.RUBRIQUE.PAGE_ACCUEIL.BO.TITRE=Titre
VOTRE_PROJET.VOTRE_MODULE.RUBRIQUE.PAGE_ACCUEIL.BO.DESCRIPTION=Description
Configuration XML Spring
Il faut ensuite configurer les beans pour votre accueil de rubrique dans le fichier src/main/resources/spring/votreprojet-votremodule.xml Pour les paramètres du préparateur de
vue, vous pouvez vous référer à la documentation Principes d'intégration des vues
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<util:constant id="ORDRE_CRITIQUE" static-field="org.springframework.core.Ordered.HIGHEST_PRECEDENCE"/>
<!-- Préparateur de vue pour votre module -->
<bean id="votreModuleViewPreparer" class="fr.votreprojet.votremodule.view.preparer.VotreModuleViewPreparer" parent="abstractSectionHomeViewPreparer">
<property name="order" ref="ORDRE_CRITIQUE"/>
<property name="view" value="/templates/votretemplate/template/votremodule/index.jsp"/>
<property name="includedSiteTemplate">
<list>
<value>...</value>
</list>
</property>
</bean>
<!-- Accueil de rubrique pour votre module -->
<bean id="votreModuleAccueilRubrique" class="fr.votreprojet.votremodule.rubrique.VotreModuleAccueilRubrique">
<property name="typeRubrique">
<util:constant static-field="fr.votreprojet.votremodule.rubrique.VotreModuleAccueilRubrique.TYPE_ACCUEIL_RUBRIQUE"/>
</property>
<property name="libelle" value="RUBRIQUE.PAGE_ACCUEIL_VOTRE_MODULE"/>
<property name="interne" value="true"/>
<property name="pathSaisieBo" value="/WEB-INF/jsp/votremodule/bo/saisie.jsp"/>
</bean>
</beans>
- Notes :
- Déclaration du préparateur de vue
votreModuleViewPreparer:- order : L'ordre de priorité du préparateur de vue. Pour des préparateurs de vue liés au projet, on utilisera la priorité Spring
HIGHEST_PRECEDENCE; - view : Le chemin vers la jsp de la vue ;
- includedSiteTemplate / excludedSiteTemplate : Les templates de site à inclure/exclure ;
- type : Le type de vue (ici, il est déclaré dans le bean
abstractSectionHomeViewPreparer) ;
- order : L'ordre de priorité du préparateur de vue. Pour des préparateurs de vue liés au projet, on utilisera la priorité Spring
- Déclaration de l'accueil de rubrique
votreModuleAccueilRubrique:- typeRubrique : Le code de votre nouvel accueil de rubrique. Il doit être unique ;
- libelle : Le libellé qui apparaîtra dans la liste déroulante "Type d'écran" (Gestion des sites > Rubriques > Ma Rubrique > Informations générales > Page d'accueil > Type d'écran) ;
- interne : Indique si la redirection vers la page d'accueil sera faite de manière invisible pour l'utilisateur (via un forward de la requête) ou non (via un redirect de la requête). Dans le cas d'une redirection "interne", l'URL du navigateur reste celle de la rubrique. Cela permet de masquer l'URL "technique".
- pathSaisieBo (optionnel) : Une JSP qui sera affichée pour la saisie en BO.
- Déclaration du préparateur de vue
Affichage des données
Back-office
Afin de permettre au contributeur de renseigner un titre et une description, nous avons déclaré dans notre bean votreModuleAccueilRubrique une JSP permettant la saisie back-office. Elle est placée dans src/main/webapp/WEB-INF/jsp/votremodule/bo/saisie.jsp :
<jsp:useBean id="infoBean" class="com.jsbsoft.jtf.core.InfoBean" scope="request"/>
<jsp:useBean id="univFmt" class="com.univ.utils.UnivFmt" scope="page"/>
<jsp:useBean id="fmt" class="com.jsbsoft.jtf.core.FormateurJSP" scope="page"/>
<%
univFmt.insererChampSaisie(fmt, out, infoBean, "TITRE", FormateurJSP.SAISIE_OBLIGATOIRE, FormateurJSP.FORMAT_TEXTE,0, 255, module.getMessage("VOTRE_PROJET.VOTRE_MODULE.RUBRIQUE.PAGE_ACCUEIL.BO.TITRE"));
univFmt.insererChampSaisie(fmt, out, infoBean, "DESCRIPTION", FormateurJSP.SAISIE_FACULTATIVE, FormateurJSP.FORMAT_TEXTE,0, 255, module.getMessage("VOTRE_PROJET.VOTRE_MODULE.RUBRIQUE.PAGE_ACCUEIL.BO.DESCRIPTION"));
%>
- Dans la JSP de saisie back-office, il faut ajouter deux champs de saisie, l'un pour le titre (qui sera obligatoire) et l'autre pour la description, qui est facultative.
Front-office
Pour afficher nos données, il est nécessaire de créer la JSP déclarée dans le bean votreModuleViewPreparer, à l'emplacement suivant : src/main/webapp/templates/votretemplate/template/votremodule/index.jsp.
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="kuik" uri="kuik" %>
<%--@elvariable id="bodyViewModel" type="fr.votreprojet.votremodule.view.model.VotreModuleViewModel"--%>
<%--@elvariable id="mainViewModel" type="com.kosmos.template.MainViewModel"--%>
<c:if test="${not empty mainViewModel.bodyType}">
<c:set var="bodyTypeClass" value="main--${mainViewModel.bodyType}"/>
</c:if>
<main class="main ${bodyTypeClass} l-grid l-expanded-body__expander" data-layout="page">
<div class="l-content">
<kuik:heading title="${bodyViewModel.titre}" level="1" size="md" class="visually-hidden" />
<div class="box box--light box--expand">
<c:if test="${not empty bodyViewModel.description}">
<p><c:out value="${bodyViewModel.description}"/></p>
</c:if>
</div>
</div>
</main>
- L'instruction
trimDirectiveWhitespacespermet d'éviter les sauts de lignes indésirables. Si sa présence n'est pas obligatoire, elle reste fortement conseillée. - Pour afficher le titre de l'accueil de rubrique, nous utilisons la librairie
kuik. Cette librairie est présente par défaut avec le produit. Sa documentation est disponible ici. - Pour connaître le type de body sur lequel nous nous trouvons, nous pouvons récupérer la propriété
bodyType. La classe contenue dans cette propriété est utilisée pour l'intégration.
Configuration Spring
Si votre accueil de rubrique fait appel à un contrôleur (par exemple, chargement de données via l'appel à une URL dans un datagrid), il faut penser à ajouter l'annotation
@ComponentScan(basePackages = {"fr.votreprojet"}) dans la classe de configuration.
package fr.votreprojet.context;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan(basePackages = {"fr.votreprojet"})
@EnableWebMvc
public class VotreProjetConfig {
// Configuration beans si nécessaire
}