Commit 445e1a82 authored by François-Xavier Lebastard's avatar François-Xavier Lebastard
Browse files

Merge branch 'feature/gestion_des_ecrans' into 'develop'

gestion des écrans

See merge request !59
parents d9180922 fc8cb7e7
......@@ -69,11 +69,7 @@ out/
######################
# Visual Studio Code
######################
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.vscode/
*.code-workspace
######################
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -47,6 +47,13 @@ public class Screen implements Serializable {
@Column(name = "name", nullable = false, unique = true)
private String name;
/**
* Nom de l'écran : pour l'affichage uniquement
*/
@NotNull
@Column(name = "name_bo", nullable = false, unique = true)
private String nameBo;
/**
* reference du screen pour constituer l'URL
*/
......@@ -79,19 +86,16 @@ public class Screen implements Serializable {
@Column(name = "items", nullable = false)
private String items;
@JsonIgnoreProperties(value = { "previous", "next", "form" }, allowSetters = true)
@OneToOne
@JoinColumn(unique = true)
private Screen previous;
@JsonIgnoreProperties(value = { "previous", "next", "form" }, allowSetters = true)
@OneToOne(mappedBy = "previous")
private Screen next;
@ManyToOne
@JsonIgnoreProperties(value = { "screens", "variables", "workspace" }, allowSetters = true)
private Form form;
/**
* La position de l'écran dans le back-office.
*/
@Column(name = "index")
private Integer index;
// jhipster-needle-entity-add-field - JHipster will add fields here
public Long getId() {
return id;
......@@ -115,6 +119,15 @@ public class Screen implements Serializable {
return this;
}
public Screen nameBo(final String nameBo) {
this.nameBo = nameBo;
return this;
}
public Screen index(final Integer index) {
this.index = index;
return this;
}
public void setName(String name) {
this.name = name;
}
......@@ -203,51 +216,34 @@ public class Screen implements Serializable {
this.items = items;
}
public Screen getPrevious() {
return this.previous;
public Form getForm() {
return this.form;
}
public Screen previous(Screen screen) {
this.setPrevious(screen);
public Screen form(Form form) {
this.setForm(form);
return this;
}
public void setPrevious(Screen screen) {
this.previous = screen;
}
public Screen getNext() {
return this.next;
}
public Screen next(Screen screen) {
this.setNext(screen);
return this;
public void setForm(Form form) {
this.form = form;
}
public void setNext(Screen screen) {
if (this.next != null) {
this.next.setPrevious(null);
}
if (next != null) {
next.setPrevious(this);
}
this.next = screen;
public Integer getIndex() {
return index;
}
public Form getForm() {
return this.form;
public void setIndex(Integer index) {
this.index = index;
}
public Screen form(Form form) {
this.setForm(form);
return this;
public String getNameBo() {
return nameBo;
}
public void setForm(Form form) {
this.form = form;
public void setNameBo(String nameBo) {
this.nameBo = nameBo;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here
@Override
......
......@@ -67,8 +67,6 @@ public class FilArianeController {
public String getUserHome() {
if (PermissionService.currentUserHasAuthority(AuthoritiesConstants.AUTHORITY_VIEW_WORKSPACE)) {
return Path.LIST_WORKSPACES;
} else if (PermissionService.currentUserHasAuthority(AuthoritiesConstants.AUTHORITY_VIEW_FORMS)) {
return Path.LIST_FORMS;
} else if (PermissionService.currentUserHasAuthority(AuthoritiesConstants.AUTHORITY_VIEW_FORM)) {
return Path.LIST_FORMS;
}
......
......@@ -5,10 +5,10 @@ package com.unantes.orientactive.filariane;
*/
public class Path {
public static final String HOME = "/admin/workspace/list";
public static final String HOME = "/admin/workspace";
public static final String WORKSPACE = "/admin/workspace";
public static final String FORMS = "/admin/forms";
public static final String LIST_WORKSPACES = "/admin/workspaces/list";
public static final String LIST_WORKSPACES = "/admin/workspaces";
public static final String LIST_FORMS = "/admin/forms";
}
......@@ -335,4 +335,22 @@ public class NavigationService {
throw new RequiredAnswersMissingException(requiredQuestionsWithoutAnswers);
}
}
/**
* Permet de savoir si un écran est le dernier écran du formulaire.
*
* @return Vrai si l'écran est le dernier écran, sinon faux.
*/
public boolean checkIsLastScreen(final ScreenDTO screenDTO) {
return screenService.findScreenByIndexAndFormId(screenDTO.getNextIndex(), screenDTO.getFormId()).isEmpty();
}
/**
* Permet de savoir si un écran est le premier écran du formulaire.
*
* @return Vrai si l'écran est le premier écran, sinon faux.
*/
public boolean checkIsFirstScreen(final ScreenDTO screenDTO) {
return screenDTO.getIndex() == 1;
}
}
......@@ -12,17 +12,18 @@ import com.unantes.orientactive.service.dto.NextScreenExpressionDTO;
import com.unantes.orientactive.service.dto.ScreenDTO;
import com.unantes.orientactive.service.dto.VariableDTO;
import com.unantes.orientactive.web.rest.errors.UnableToFindNextScreenException;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Ce service contient la logique de navigation d'un écran vers le suivant. Il contient également les méthodes permettants de déterminer si un item doit être affiché.
*/
......@@ -48,8 +49,9 @@ public class ScreenNavigationService {
/**
* Constructure.
* @param screenService {@link #screenService}
* @param answerService {@link #answerService}
*
* @param screenService {@link #screenService}
* @param answerService {@link #answerService}
* @param variableService {@link #variableService}
*/
public ScreenNavigationService(ScreenService screenService, AnswerService answerService, VariableService variableService) {
......@@ -64,15 +66,16 @@ public class ScreenNavigationService {
* Chaque expression de {@link Screen#getNextScreenExpressions()} est évaluée : la première qui est vérifiée donne l'écran suivant.
* Si aucune n'est vérifiée, {@link Screen#getDefaultNextScreenReference()} est utilisé s'il est non vide
* {@link Screen#getNext()} est utilisé en dernier recours.
*
* @param sessionId une session de réponses (l'identifiant commun à toutes les réponses d'un utilisateur)
* @param screen l'écran courant de l'utilisateur
* @param screen l'écran courant de l'utilisateur
* @return
* @throws UnableToFindNextScreenException la méthode a été appelée avec un écran final ou l'expression du screen courant retourne un screen qui n'existe pas
*
*/
public ScreenDTO getNextScreen(final String sessionId, final ScreenDTO screen) throws UnableToFindNextScreenException {
// il ne faut pas appeler cette méthode lorsque l'écran courant est le dernier !
if (screen.getNextId() == null) {
Optional<ScreenDTO> screenDTO = screenService.findScreenByIndexAndFormId(screen.getNextIndex(), screen.getFormId());
if (screenDTO.isEmpty()) {
throw new UnableToFindNextScreenException();
}
// initialisation d'une expression. Elle est utilisée pour evaluer les expressions permettant de déterminer les écrans suivants et pour filter les items affichés dans l'écran suivant.
......@@ -91,8 +94,9 @@ public class ScreenNavigationService {
/**
* Détermine l'écran suivant en fonction des expressions {@link ScreenDTO#getNextScreenExpressions()}.
*
* @param expression le moteur d'expressions SpEL initialisé avec les données de l'utilisateur
* @param screen l'écran courant
* @param screen l'écran courant
* @return
*/
private ScreenDTO getNextScreenFromExpressions(final Expression expression, final ScreenDTO screen) {
......@@ -112,30 +116,33 @@ public class ScreenNavigationService {
/**
* Deux écrans par défaut possibles :
* <ul>
* <li>{@link Screen#getDefaultNextScreenReference()}; utilisé si renseigné</li>
* <li>{@link Screen#getNext()}; champ obligatoire; utilisé pour définir l'ordre en back office et en dernier recours pour l'ordre en front.</li>
* <li>{@link Screen#getDefaultNextScreenReference()}; utilisé si renseigné</li>
* <li>{@link Screen#getNext()}; champ obligatoire; utilisé pour définir l'ordre en back office et en dernier recours pour l'ordre en front.</li>
* </ul>
*
* @param screen
* @return
*/
private ScreenDTO getDefaultNextScreen(final ScreenDTO screen) {
if (StringUtils.isBlank(screen.getDefaultNextScreenReference())) {
return getScreenById(screen.getNextId());
return getScreenByIndexAndFormId(screen.getNextIndex(), screen.getFormId());
}
return getScreenByRef(screen.getDefaultNextScreenReference());
}
/**
* Wrapper de la méthode {@link ScreenService#findOne(Long)}; Jette une exception si l'écran n'existe pas.
*
* @param nextId
* @return
*/
private ScreenDTO getScreenById(final Long nextId) {
return screenService.findOne(nextId).orElseThrow(() -> new UnableToFindNextScreenException("l'écran n'existe pas en base"));
private ScreenDTO getScreenByIndexAndFormId(final Integer index, final Long formId) {
return screenService.findScreenByIndexAndFormId(index, formId).orElseThrow(() -> new UnableToFindNextScreenException("l'écran n'existe pas en base"));
}
/**
* Wrapper de la méthode {@link ScreenService#findOneByReference(String)}; Jette une exception si l'écran n'existe pas.
*
* @param screenRef
* @return
*/
......@@ -147,8 +154,9 @@ public class ScreenNavigationService {
/**
* Filtre les items de l'écran courant en fonction des conditions d'affichage de chaque item.
*
* @param sessionId pour retrouver les réponses de la session courante
* @param screen un écran qui contient les items à filtrer
* @param screen un écran qui contient les items à filtrer
*/
public void filterScreenItems(final String sessionId, final ScreenDTO screen) {
final Expression expression = initializeExpression(screen.getFormId(), sessionId);
......@@ -157,7 +165,8 @@ public class ScreenNavigationService {
/**
* Filtre les items de l'écran courant en fonction des conditions d'affichage de chaque item.
* @param screen un écran qui contient les items à filtrer
*
* @param screen un écran qui contient les items à filtrer
* @param expressionEngine l'expression initialisée avec les réponses de l'utilisateur
*/
protected void filterScreenItems(final ScreenDTO screen, final Expression expressionEngine) {
......@@ -179,7 +188,8 @@ public class ScreenNavigationService {
/**
* Créer une expresison à partir de la session et du formulaire.
* @param formId pour charger les réponses et les variables associés au formulaire
*
* @param formId pour charger les réponses et les variables associés au formulaire
* @param sessionId pour charger les réponses
* @return
*/
......@@ -196,6 +206,7 @@ public class ScreenNavigationService {
/**
* Construit une lambda qui pemet de déterminer si un item doit être affiché dans une écran.
*
* @param expression une expression initialisée avec les réponses de l'utilisateur
* @return
*/
......
......@@ -2,11 +2,13 @@ package com.unantes.orientactive.repository;
import com.unantes.orientactive.domain.Screen;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Optional;
/**
......@@ -15,7 +17,6 @@ import java.util.Optional;
@SuppressWarnings("unused")
@Repository
public interface ScreenRepository extends JpaRepository<Screen, Long> {
/**
* Récupération d'un écran par sa référence.
*
......@@ -30,7 +31,10 @@ public interface ScreenRepository extends JpaRepository<Screen, Long> {
* @param formId L'identifiant du formulaire.
* @return Le premier écran du formulaire s'il existe.
*/
@Query(value = "select * from screen join form on form.id = screen.form_id where screen.previous_id is null and form.id = :formId", nativeQuery = true)
@Query(
value = "select * from screen join form on form.id = screen.form_id where screen.index = 1 and form.id = :formId",
nativeQuery = true
)
Optional<Screen> findFirstScreenOfForm(final @Param("formId") Long formId);
/**
......@@ -40,7 +44,10 @@ public interface ScreenRepository extends JpaRepository<Screen, Long> {
* @param sessionId L'identifiant de la session de l'utilisateur.
* @return L'écran précédent s'il existe.
*/
@Query(value = "select * from screen where id = (select previous.screen_id from answer current join answer previous on current.previous_id = previous.id where current.screen_id = :currentScreenId and current.session_id = :sessionId)", nativeQuery = true)
@Query(
value = "select * from screen where id = (select previous.screen_id from answer current join answer previous on current.previous_id = previous.id where current.screen_id = :currentScreenId and current.session_id = :sessionId)",
nativeQuery = true
)
Optional<Screen> findPreviousScreen(final @Param("currentScreenId") Long currentScreenId, final @Param("sessionId") String sessionId);
/**
......@@ -50,7 +57,10 @@ public interface ScreenRepository extends JpaRepository<Screen, Long> {
* @param sessionId L'identifiant de la session de l'utilisateur.
* @return L'écran suivant s'il existe.
*/
@Query(value = "select * from screen where id = (select next.screen_id from answer current join answer next on next.previous_id = current.id where current.screen_id = :currentScreenId and current.session_id = :sessionId)", nativeQuery = true)
@Query(
value = "select * from screen where id = (select next.screen_id from answer current join answer next on next.previous_id = current.id where current.screen_id = :currentScreenId and current.session_id = :sessionId)",
nativeQuery = true
)
Optional<Screen> findNextScreen(final @Param("currentScreenId") Long currentScreenId, final @Param("sessionId") String sessionId);
/**
......@@ -62,6 +72,44 @@ public interface ScreenRepository extends JpaRepository<Screen, Long> {
* @param screenId L'identifiant de l'écran.
* @return Le nombre d'écran potentiellement restant.
*/
@Query(value = "WITH RECURSIVE previous AS (SELECT id, previous_id FROM screen WHERE id = :screenId UNION SELECT s.id, s.previous_id FROM screen s INNER JOIN previous p ON p.previous_id = s.id) SELECT (select count(*) from screen where form_id = :formId) - count(pr.*) FROM previous pr", nativeQuery = true)
@Query(
value = "SELECT COUNT(*) FROM SCREEN WHERE INDEX > (SELECT INDEX FROM SCREEN WHERE ID = :screenId AND form_id = :formId) AND form_id = :formId",
nativeQuery = true
)
int countScreenLeft(final @Param("formId") Long formId, final @Param("screenId") Long screenId);
/**
* Retourne les écrans d'un formulaire selon les permissions d'un utilisateur
*
* @param idUser identifiant d'utilisateur
* @param idForm identifiant de formulaire
* @return
*/
@Query(
value = "select screen.* from form f join scope_form sf on sf.id_form = f.id join scope s on s.id = sf.id_scope join screen on f.id = screen.form_id join jhi_user u on u.id = s.id_user where u.id = :idUser and f.id = :idForm",
nativeQuery = true
)
List<Screen> findWithPermission(@Param("idUser") Long idUser, @Param("idForm") Long idForm);
/**
* Récupération de tous les écrans d'un formulaire.
*
* @param formId L'identifiant du formulaire.
* @return Les écrans.
*/
List<Screen> findAllByFormId(final Long formId);
Optional<Screen> findScreenByIndexAndFormId(final Integer index, final Long formId);
/**
* Diminue l'index des écrans d'un formulaire dont l'index est supérieur à celui passé en paramètre.
* @param formId un identifiant de formulaire
* @param index un index (position) d'écran
*/
@Query(
value = "UPDATE screen SET index = (index - 1) WHERE index > :index AND form_id = :formId",
nativeQuery = true
)
@Modifying(flushAutomatically = true, clearAutomatically = true)
void decreaseScreenIndex(@Param("formId") Long formId, @Param("index") Integer index);
}
......@@ -19,8 +19,6 @@ public final class AuthoritiesConstants {
public static final SimpleGrantedAuthority AUTHORITY_VIEW_WORKSPACE = new SimpleGrantedAuthority(VIEW_WORKSPACE);
public static final String EDIT_WORKSPACE = "EDIT_WORKSPACE";
public static final SimpleGrantedAuthority AUTHORITY_EDIT_WORKSPACE = new SimpleGrantedAuthority(EDIT_WORKSPACE);
public static final String VIEW_FORMS = "VIEW_FORMS";
public static final SimpleGrantedAuthority AUTHORITY_VIEW_FORMS = new SimpleGrantedAuthority(VIEW_FORMS);
public static final String VIEW_FORM = "VIEW_FORM";
public static final SimpleGrantedAuthority AUTHORITY_VIEW_FORM = new SimpleGrantedAuthority(VIEW_FORM);
public static final String EDIT_FORM = "EDIT_FORM";
......
......@@ -175,7 +175,7 @@ public class FormService extends PermissionService<FormDTO> {
formRepository.removePermission(user.getId(), element.getId());
}
@PreAuthorize("hasAuthority('VIEW_FORMS')")
@PreAuthorize("hasAuthority('VIEW_FORM')")
@Override
protected List<FormDTO> findWithPermission(User user, Long idParentElement) {
return formRepository
......@@ -185,7 +185,7 @@ public class FormService extends PermissionService<FormDTO> {
.collect(Collectors.toList());
}
@PreAuthorize("hasAuthority('VIEW_FORMS')")
@PreAuthorize("hasAuthority('VIEW_FORM')")
@Override
public List<FormDTO> findAllByParent(Long idParentElement) {
return formRepository
......@@ -195,7 +195,7 @@ public class FormService extends PermissionService<FormDTO> {
.collect(Collectors.toCollection(LinkedList::new));
}
@PreAuthorize("hasAuthority('VIEW_FORMS')")
@PreAuthorize("hasAuthority('VIEW_FORM')")
@Override
protected boolean hasWildcard(User user) {
return formRepository.hasWildcard(user.getId(), Role.CONTRIBUTEUR.getId());
......@@ -206,9 +206,13 @@ public class FormService extends PermissionService<FormDTO> {
return userService.findAllWithPermissionOnForm(Role.CONTRIBUTEUR.getId(), element.getId());
}
@PreAuthorize("hasAuthority('VIEW_FORMS')")
@Override
protected boolean existPermission(User user, FormDTO element) {
return formRepository.existPermission(user.getId(), element.getId());
return existPermission(user, element.getId());
}
@PreAuthorize("hasAuthority('VIEW_FORM')")
protected boolean existPermission(User user, Long formId) {
return formRepository.existPermission(user.getId(), formId);
}
}
package com.unantes.orientactive.service;
import com.unantes.orientactive.domain.Screen;
import com.unantes.orientactive.repository.ScreenRepository;
import com.unantes.orientactive.service.dto.ScreenDTO;
import com.unantes.orientactive.service.mapper.ScreenMapper;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.slf4j.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Transactional;
import com.unantes.orientactive.domain.Screen;
import com.unantes.orientactive.domain.User;
import com.unantes.orientactive.repository.ScreenRepository;
import com.unantes.orientactive.service.dto.FormDTO;
import com.unantes.orientactive.service.dto.ScreenDTO;
import com.unantes.orientactive.service.dto.ScreenPanelDTO;
import com.unantes.orientactive.service.mapper.ScreenMapper;
import com.unantes.orientactive.service.mapper.ScreenPanelMapper;
import com.unantes.orientactive.service.exception.EntityNotFoundException;
/**
* Service Implementation for managing {@link Screen}.
*/
......@@ -31,9 +35,20 @@ public class ScreenService {
private final ScreenMapper screenMapper;
public ScreenService(ScreenRepository screenRepository, ScreenMapper screenMapper) {
private final ScreenPanelMapper screenPanelMapper;
private final FormService formService;
public ScreenService(
ScreenRepository screenRepository,
ScreenMapper screenMapper,
ScreenPanelMapper screenPanelMapper,
FormService formService
) {
this.screenRepository = screenRepository;
this.screenMapper = screenMapper;
this.screenPanelMapper = screenPanelMapper;
this.formService = formService;
}
/**
......@@ -81,21 +96,6 @@ public class ScreenService {
return screenRepository.findAll().stream().map(screenMapper::toDto).collect(Collectors.toCollection(LinkedList::new));
}
/**
* Get all the screens where Next is {@code null}.
*
* @return the list of entities.
*/
@Transactional(readOnly = true)
public List<ScreenDTO> findAllWhereNextIsNull() {
log.debug("Request to get all screens where Next is null");
return StreamSupport
.stream(screenRepository.findAll().spliterator(), false)
.filter(screen -> screen.getNext() == null)
.map(screenMapper::toDto)
.collect(Collectors.toCollection(LinkedList::new));
}
/**
* Get one screen by id.
*
......@@ -115,7 +115,9 @@ public class ScreenService {
*/
public void delete(Long id) {
log.debug("Supression de l'écran d'identifiant '{}'.", id);
screenRepository.deleteById(id);
final Screen screenToDelete = screenRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(id));
screenRepository.delete(screenToDelete);
screenRepository.decreaseScreenIndex(screenToDelete.getForm().getId(), screenToDelete.getIndex());
}
/**
......@@ -181,4 +183,34 @@ public class ScreenService {
);
return screenRepository.countScreenLeft(formId, screenId);
}
/**