Continue transition vers exceptions + DTO
This commit is contained in:
parent
a1cc594acd
commit
26110beac2
|
@ -28,5 +28,5 @@ HELP.md
|
|||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
/logs/
|
||||
*.log
|
||||
/workdir/
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@Deprecated(since = "1.3.0")
|
||||
public class FileHandler {
|
||||
|
||||
protected String name;
|
||||
|
|
|
@ -7,6 +7,7 @@ import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Deprecated(since = "1.3.0")
|
||||
public class ImageHandler extends FileHandler {
|
||||
|
||||
public static final String IMAGES_LOCATION = ColorRecipesExplorerApplication.UPLOAD_LOCATION + "/images";
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.springframework.web.servlet.ModelAndView;
|
|||
public class ModelResponseBuilder extends ResponseBuilder<ModelResponseBuilder, ModelAndView> {
|
||||
|
||||
private static final String PATH_PARAMETER_PATTERN = "(\\{\\w+\\})";
|
||||
private static final String REDIRECT_PATH_PREFIX = "redirect:/";
|
||||
|
||||
private ModelAndView model;
|
||||
|
||||
|
@ -26,13 +27,17 @@ public class ModelResponseBuilder extends ResponseBuilder<ModelResponseBuilder,
|
|||
return this;
|
||||
}
|
||||
|
||||
public ModelResponseBuilder withRedirect(String path, Object... parameters) {
|
||||
for (Object parameter : parameters) path = path.replaceFirst(PATH_PARAMETER_PATTERN, parameter.toString());
|
||||
model.setViewName("redirect:/" + path);
|
||||
public ModelResponseBuilder withView(String path, Object... parameters) {
|
||||
path = replaceInPath(path, parameters);
|
||||
model.setViewName(path);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ModelResponseBuilder withRedirect(String path, Object... parameters) {
|
||||
return withView(REDIRECT_PATH_PREFIX + path, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addResponseCodeToAttribute(String responseCodeType, String responseMessagePath, String[] parameters) {
|
||||
addAttribute(responseCodeType, responseMessagePath);
|
||||
|
@ -47,4 +52,12 @@ public class ModelResponseBuilder extends ResponseBuilder<ModelResponseBuilder,
|
|||
|
||||
return model;
|
||||
}
|
||||
|
||||
private String replaceInPath(String path, Object... parameters) {
|
||||
for (Object parameter : parameters) {
|
||||
path = path.replaceFirst(PATH_PARAMETER_PATTERN, parameter.toString());
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,14 @@ public enum ResponseDataType {
|
|||
MATERIAL_TYPE("materialType", MaterialType.class),
|
||||
MATERIAL_TYPES("materialTypes", ArrayList.class, MATERIAL_TYPE),
|
||||
MATERIAL_TYPE_NAME("materialTypeName", String.class),
|
||||
MATERIALS_JSON("materialsJson", String.class),
|
||||
|
||||
RECIPE("recipe", Recipe.class),
|
||||
RECIPES("recipes", ArrayList.class, RECIPE),
|
||||
RECIPE_ID("recipeId", Long.class),
|
||||
RECIPE_CODE("recipeCode", String.class),
|
||||
RECIPE_MAP("recipeMap", HashMap.class),
|
||||
RECIPE_JSON("recipeJson", String.class),
|
||||
|
||||
RECIPE_STEP("recipeStep", RecipeStep.class),
|
||||
RECIPE_STEPS("recipeSteps", ArrayList.class, RECIPE_STEP),
|
||||
|
@ -28,6 +30,7 @@ public enum ResponseDataType {
|
|||
MIX("mix", Mix.class),
|
||||
MIXES("mixes", ArrayList.class, MIX),
|
||||
MIX_ID("mixId", Long.class),
|
||||
MIX_JSON("mixJson", String.class),
|
||||
|
||||
MIX_TYPE("mixType", MixType.class),
|
||||
MIX_TYPES("mixTypes", ArrayList.class, MIX_TYPE),
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.model.dto;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class RecipeEditorFormDto {
|
||||
|
||||
private Recipe recipe;
|
||||
private List<String> step;
|
||||
|
||||
}
|
|
@ -47,13 +47,24 @@ public class FilesService {
|
|||
*
|
||||
* @param input L'InputStream
|
||||
* @return Le InputStream transformé en String
|
||||
* @throws IOException Si la transformation vers un String échoue
|
||||
* @throws IOException La transformation vers un String a échoué
|
||||
*/
|
||||
public String readInputStreamAsString(InputStream input) throws IOException {
|
||||
byte[] data = FileCopyUtils.copyToByteArray(input);
|
||||
return new String(data, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le contenu d'un fichier dans un tableau de Byte.
|
||||
*
|
||||
* @param path Le chemin vers le fichier
|
||||
* @return Le contenu du fichier dans un tableau de Byte
|
||||
* @throws IOException La lecture du fichier a échoué
|
||||
*/
|
||||
public byte[] readFileAsBytes(String path) throws IOException {
|
||||
return Files.readAllBytes(Paths.get(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Écrit un fichier Multipart sur le disque.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.services.files;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.ColorRecipesExplorerApplication;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Service
|
||||
public class ImagesService {
|
||||
|
||||
private static final String IMAGES_DIRECTORY = "images";
|
||||
|
||||
private FilesService filesService;
|
||||
|
||||
@Autowired
|
||||
public ImagesService(FilesService filesService) {
|
||||
this.filesService = filesService;
|
||||
}
|
||||
|
||||
public byte[] readImage(String name) {
|
||||
try {
|
||||
return filesService.readFileAsBytes(getPath(name));
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Erreur lors de la lecture d'une image: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String getPath(String name) {
|
||||
return String.format("%s/%s/%s", ColorRecipesExplorerApplication.UPLOAD_LOCATION, IMAGES_DIRECTORY, name);
|
||||
}
|
||||
|
||||
}
|
|
@ -26,11 +26,6 @@ public class CompanyService extends GenericService<Company, CompanyDao> {
|
|||
super.delete(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidForCreation(Company entity) {
|
||||
return super.isValidForCreation(entity) && !existsByName(entity.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si une bannière correspondant à un nom existe.
|
||||
*
|
||||
|
|
|
@ -42,19 +42,17 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
* @return Les produits disponibles pour ce mélange
|
||||
*/
|
||||
public Collection<Material> getAvailableMaterialsForMixId(Long recipeId, Long mixId) {
|
||||
Recipe recipe = recipeService.getById(recipeId);
|
||||
return existsById(mixId) ? getAvailableMaterialsForMix(recipe, getById(mixId)) : getAvailableMaterialsForNewMix(recipe);
|
||||
return existsById(mixId) ? getAvailableMaterialsForMix(getById(mixId)) : getAvailableMaterialsForNewMix(recipeService.getById(recipeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les produits disponibles pour un mélange existant.
|
||||
*
|
||||
* @param recipe La recette dans laquelle se trouve le mélange
|
||||
* @param mix Le mélange
|
||||
* @param mix Le mélange
|
||||
* @return Les produits disponibles pour ce mélange
|
||||
*/
|
||||
public Collection<Material> getAvailableMaterialsForMix(Recipe recipe, Mix mix) {
|
||||
return getAvailableMaterialsForNewMix(recipe)
|
||||
public Collection<Material> getAvailableMaterialsForMix(Mix mix) {
|
||||
return getAvailableMaterialsForNewMix(mix.getRecipe())
|
||||
.stream()
|
||||
.filter(m -> !m.equals(mix.getMixType().getMaterial()))
|
||||
.collect(Collectors.toList());
|
||||
|
@ -153,12 +151,22 @@ public class MixService extends GenericService<Mix, MixDao> {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean deleteMix(Mix mix) {
|
||||
if (mixQuantityService.deleteAll(mix.getMixQuantities())) {
|
||||
return super.delete(mix);
|
||||
}
|
||||
@Deprecated(since = "1.3.0", forRemoval = true)
|
||||
public void deleteMix(Mix mix) {
|
||||
mixQuantityService.deleteAll(mix.getMixQuantities());
|
||||
delete(mix);
|
||||
}
|
||||
|
||||
return false;
|
||||
@Override
|
||||
public void delete(Mix mix) {
|
||||
mixQuantityService.deleteAll(mix.getMixQuantities());
|
||||
/
|
||||
super.delete(mix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(Long id) {
|
||||
delete(getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.fyloz.trial.colorrecipesexplorer.core.services.model;
|
|||
import dev.fyloz.trial.colorrecipesexplorer.core.io.file.FileHandler;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.file.ImageHandler;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.*;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.RecipeEditorFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.RecipeExplorerFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.GenericService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.dao.RecipeDao;
|
||||
|
@ -61,6 +62,7 @@ public class RecipeService extends GenericService<Recipe, RecipeDao> {
|
|||
return mappedByCompany(getAll());
|
||||
}
|
||||
|
||||
@Deprecated(since = "1.3.0", forRemoval = true)
|
||||
public Recipe updateRecipe(Recipe newRecipe, Recipe storedRecipe, MultiValueMap<String, Object> form) {
|
||||
storedRecipe.setName(newRecipe.getName());
|
||||
storedRecipe.setCompany(newRecipe.getCompany());
|
||||
|
@ -73,6 +75,20 @@ public class RecipeService extends GenericService<Recipe, RecipeDao> {
|
|||
return convertAndCreateSteps(storedRecipe, form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour une recette ainsi que ses étapes.
|
||||
*
|
||||
* @param recipeDto Les informations de la recette à mettre à jour
|
||||
* @return La recette mise à jour
|
||||
*/
|
||||
@Transactional
|
||||
public Recipe updateRecipeAndSteps(RecipeEditorFormDto recipeDto) {
|
||||
Recipe recipe = recipeDto.getRecipe();
|
||||
|
||||
stepService.createAllForRecipe(recipe, recipeDto.getStep());
|
||||
return update(recipeDto.getRecipe());
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour les informations d'une recette trouvées dans l'explorateur de recette.
|
||||
*
|
||||
|
@ -230,4 +246,8 @@ public class RecipeService extends GenericService<Recipe, RecipeDao> {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getImageFileName(Recipe recipe) {
|
||||
return String.format("%s_%s", recipe.getId(), recipe.getName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,43 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.core.services.model;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.RecipeStep;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.GenericService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.dao.StepDao;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class StepService extends GenericService<RecipeStep, StepDao> {
|
||||
|
||||
@Autowired
|
||||
public StepService(StepDao stepDao) {
|
||||
super(stepDao);
|
||||
super(stepDao, RecipeStep.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une étape pour une recette.
|
||||
*
|
||||
* @param recipe La recette
|
||||
* @param message Le message de l'étape à créer
|
||||
*/
|
||||
public void createForRecipe(Recipe recipe, String message) {
|
||||
save(new RecipeStep(recipe, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée toutes les étapes pour une recette.
|
||||
*
|
||||
* @param recipe La recette
|
||||
* @param messages Tous les messages des étapes à créer
|
||||
*/
|
||||
@Transactional
|
||||
public void createAllForRecipe(Recipe recipe, List<String> messages) {
|
||||
messages.forEach(m -> createForRecipe(recipe, m));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public class MixCreatorController {
|
|||
modelResponseBuilder
|
||||
.addResponseData(ResponseDataType.RECIPE, recipe)
|
||||
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
|
||||
.addAttribute("materialsJson", materialService.asJson(mixService.getAvailableMaterialsForNewMix(recipe)));
|
||||
.addResponseData(ResponseDataType.MATERIALS_JSON, materialService.asJson(mixService.getAvailableMaterialsForNewMix(recipe)));
|
||||
|
||||
if (materialService.getAll().isEmpty())
|
||||
modelResponseBuilder.addResponseData(ResponseDataType.BLOCK_BUTTON, true);
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.editors;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseDataType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Mix;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.MixCreationFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.*;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.utils.ControllerUtils;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MaterialTypeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.MixService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -14,9 +16,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Optional;
|
||||
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.StringBank.*;
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
||||
|
||||
@Controller
|
||||
|
@ -24,89 +24,46 @@ public class MixEditorController {
|
|||
|
||||
private MixService mixService;
|
||||
private MaterialService materialService;
|
||||
private RecipeService recipeService;
|
||||
private MixTypeService mixTypeService;
|
||||
private MaterialTypeService materialTypeService;
|
||||
|
||||
@Autowired
|
||||
public MixEditorController(MixService mixService, MaterialService materialService, RecipeService recipeService, MixTypeService mixTypeService, MaterialTypeService materialTypeService) {
|
||||
public MixEditorController(MixService mixService, MaterialService materialService, MaterialTypeService materialTypeService) {
|
||||
this.mixService = mixService;
|
||||
this.materialService = materialService;
|
||||
this.recipeService = recipeService;
|
||||
this.mixTypeService = mixTypeService;
|
||||
this.materialTypeService = materialTypeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Affiche la page d'édition d'un mélange.
|
||||
* Cette méthode requiert l'identifiant du mélange à modifier dans l'URL.
|
||||
*
|
||||
* @param model Le Model injecté par Thymeleaf
|
||||
* @param id L'identifiant du mélange à modifier
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@GetMapping(EDITOR_MIX_SPECIFIC)
|
||||
public ModelAndView getPage(ModelAndView model, @PathVariable Long id) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model)
|
||||
.withView(EDITOR_MIX_SPECIFIC.replaceAll("/\\{id}", ""));
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model).withView(EDITOR_MIX);
|
||||
|
||||
try {
|
||||
Mix mix = mixService.getById(id);
|
||||
|
||||
Optional<Mix> optionalMix = mixService.getById(id);
|
||||
if (optionalMix.isEmpty()) {
|
||||
return modelResponseBuilder
|
||||
.withView(ControllerUtils.redirect(EDITOR_RECIPE))
|
||||
.addResponseData(ResponseDataType.MIX, mix)
|
||||
.addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
|
||||
.addResponseData(ResponseDataType.MIX_JSON, mixService.asJson(mix))
|
||||
.addResponseData(ResponseDataType.MATERIALS_JSON, materialService.asJson(mixService.getAvailableMaterialsForMix(mix)))
|
||||
.build();
|
||||
|
||||
} catch (EntityNotFoundException ex) {
|
||||
return modelResponseBuilder
|
||||
.withRedirect(EDITOR_RECIPE)
|
||||
.build();
|
||||
}
|
||||
|
||||
Mix mix = optionalMix.get();
|
||||
|
||||
return modelResponseBuilder
|
||||
.addResponseData(ResponseDataType.MIX, mix)
|
||||
.addResponseData(ResponseDataType.RECIPE, mix.getRecipe())
|
||||
.addAttribute(MATERIAL_TYPE, mix.getMixType().getMaterial().getMaterialType())
|
||||
.addAttribute(MATERIAL_TYPES, materialTypeService.getAll())
|
||||
.addAttribute("mixJson", materialService.asJson(mix))
|
||||
.addAttribute("materialsJson", mixService.asJson(mixService.getAvailableMaterialsForMix(mix.getRecipe(), mix)))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet à l'utilisateur de modifier un mélange.
|
||||
* <p>
|
||||
* La mise à jour échouera si:
|
||||
* - L'utilisateur n'est pas autorisé à exécuter cette action
|
||||
* - Le mélange n'existe pas
|
||||
* - Un des produits n'existe pas
|
||||
* - Une erreur est survenue lors de la mise à jour dans la base de données
|
||||
* <p>
|
||||
* Modèle de la page:
|
||||
* - error: Contient le message d'erreur, s'il y a lieu
|
||||
* <p>
|
||||
* REQUIERT UNE AUTORISATION
|
||||
*
|
||||
* @param form Le formulaire du mélange entré par l'utilisateur
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@PostMapping(value = EDITOR_MIX, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public ModelAndView saveMix(@ModelAttribute @Valid MixCreationFormDto formDto, @RequestParam("mixId") Long id) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
public ModelAndView updateMix(@ModelAttribute @Valid MixCreationFormDto formDto, @RequestParam("mixId") Long id) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder().withRedirect(EDITOR_RECIPE_SPECIFIC, formDto.getRecipe().getId());
|
||||
|
||||
Optional<Mix> optionalMix = mixService.getById(id);
|
||||
if (optionalMix.isEmpty()) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id);
|
||||
try {
|
||||
Mix mix = mixService.getById(id);
|
||||
|
||||
return getPage(modelResponseBuilder.build(), id);
|
||||
}
|
||||
|
||||
Mix mix = optionalMix.get();
|
||||
modelResponseBuilder.withRedirect(EDITOR_RECIPE_SPECIFIC, mix.getRecipe().getId());
|
||||
|
||||
ModelResponseBuilder editResult = mixService.edit(mix, formDto);
|
||||
if (editResult != null) {
|
||||
return getPage(
|
||||
modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.ERROR_SAVING)
|
||||
.build(),
|
||||
id);
|
||||
mixService.edit(mix, formDto);
|
||||
} catch (EntityNotFoundException ex) {
|
||||
return getPage(modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id).build(), id);
|
||||
}
|
||||
|
||||
return modelResponseBuilder.build();
|
||||
|
@ -114,25 +71,19 @@ public class MixEditorController {
|
|||
|
||||
@GetMapping(REMOVER_MIX_SPECIFIC)
|
||||
public ModelAndView deleteMix(@PathVariable Long id) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder("");
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
|
||||
Optional<Mix> optionalMix = mixService.getById(id);
|
||||
if (optionalMix.isEmpty()) {
|
||||
return getPage(modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.MIX_NOT_FOUND, id)
|
||||
.build(),
|
||||
id);
|
||||
try {
|
||||
Mix mix = mixService.getById(id);
|
||||
mixService.delete(mix);
|
||||
|
||||
return modelResponseBuilder
|
||||
.withRedirect(EDITOR_RECIPE_SPECIFIC, mix.getRecipe().getId())
|
||||
.build();
|
||||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.MIX_NOT_FOUND, id);
|
||||
}
|
||||
|
||||
Mix mix = optionalMix.get();
|
||||
modelResponseBuilder.withView(ControllerUtils.redirect(EDITOR_RECIPE_SPECIFIC.replace("{recipeID}", String.valueOf(mix.getRecipe().getId()))));
|
||||
|
||||
if (!mixService.deleteMix(mix)) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING);
|
||||
|
||||
return getPage(modelResponseBuilder.build(), id);
|
||||
}
|
||||
|
||||
return modelResponseBuilder.build();
|
||||
return getPage(modelResponseBuilder.build(), id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,22 @@
|
|||
package dev.fyloz.trial.colorrecipesexplorer.web.controller.editors;
|
||||
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.exception.model.EntityNotFoundException;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilder;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseDataType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.dto.RecipeEditorFormDto;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.CompanyService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
||||
|
||||
@Controller
|
||||
|
@ -34,17 +31,8 @@ public class RecipeEditorController {
|
|||
this.companyService = companyService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Affiche la page listant toutes les recettes.
|
||||
* <p>
|
||||
* Modèle de la page:
|
||||
* - recipes: Contient un Map de toutes les recettes triées par compagnie
|
||||
*
|
||||
* @param model Le Model injecté par Thymeleaf
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@GetMapping(EDITOR_RECIPE)
|
||||
public ModelAndView listRecipes(ModelAndView model) {
|
||||
public ModelAndView getPage(ModelAndView model) {
|
||||
return new ModelResponseBuilder(model)
|
||||
.withView(EDITOR_RECIPE)
|
||||
.addResponseData(ResponseDataType.RECIPE_MAP, recipeService.getRecipesByCompany())
|
||||
|
@ -52,74 +40,38 @@ public class RecipeEditorController {
|
|||
}
|
||||
|
||||
@GetMapping(EDITOR_RECIPE_SPECIFIC)
|
||||
public ModelAndView showEditPage(ModelAndView model, @PathVariable Long id, Recipe recipe) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model)
|
||||
.withView(EDITOR_RECIPE_EDITOR);
|
||||
public ModelAndView getEditPage(ModelAndView model, @PathVariable Long id, Recipe recipe) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model).withView(EDITOR_RECIPE_EDITOR);
|
||||
|
||||
if (recipe.getName() == null || recipe.getCompany() == null) {
|
||||
Optional<Recipe> optionalRecipe = recipeService.getById(id);
|
||||
try {
|
||||
if (recipe == null) recipe = recipeService.getById(id);
|
||||
|
||||
if (optionalRecipe.isEmpty()) {
|
||||
return listRecipes(
|
||||
modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
recipe = optionalRecipe.get();
|
||||
modelResponseBuilder
|
||||
.addResponseData(ResponseDataType.RECIPE, recipe)
|
||||
.addResponseData(ResponseDataType.COMPANIES, companyService.getAll())
|
||||
.addResponseData(ResponseDataType.MIXES, recipeService.getSortedMixes(recipe))
|
||||
.addResponseData(ResponseDataType.IMAGES, recipeService.getImageFiles(recipe))
|
||||
.addResponseData(ResponseDataType.RECIPE_JSON, recipeService.asJson(recipe));
|
||||
} catch (EntityNotFoundException ex) {
|
||||
return getPage(modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, id).build());
|
||||
}
|
||||
|
||||
return modelResponseBuilder
|
||||
.addResponseData(ResponseDataType.RECIPE, recipe)
|
||||
.addResponseData(ResponseDataType.COMPANIES, companyService.getAll())
|
||||
.addResponseData(ResponseDataType.MIXES, recipeService.getSortedMixes(recipe))
|
||||
.addResponseData(ResponseDataType.IMAGES, recipeService.getImageFiles(recipe))
|
||||
.addAttribute("recipeJSON", recipeService.asJson(recipe))
|
||||
.build();
|
||||
return modelResponseBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet à l'utilisateur de modifier une recette.
|
||||
* <p>
|
||||
* La mise à jour échouera si:
|
||||
* - L'utilisateur n'est pas autorisé à exécuter cette action
|
||||
* - La recette n'existe pas
|
||||
* - Une erreur est survenue lors de la mise à jour dans la base de données
|
||||
* <p>
|
||||
* Modèle de la page:
|
||||
* - error: Contient le message d'erreur, s'il y a lieu
|
||||
* - recipeCode: Contient la couleur d'une recette
|
||||
* <p>
|
||||
* REQUIERT UNE AUTORISATION
|
||||
*
|
||||
* @param recipe La recette à modifier
|
||||
* @param form Le formulaire entré par l'utilisateur
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@PostMapping(value = EDITOR_RECIPE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
@Transactional
|
||||
public ModelAndView saveRecipe(Recipe recipe, @RequestBody MultiValueMap<String, Object> form) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder("");
|
||||
Long recipeId = recipe.getId();
|
||||
public ModelAndView updateRecipe(RecipeEditorFormDto recipeDto) {
|
||||
ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();
|
||||
|
||||
Optional<Recipe> optionalStoredRecipe = recipeService.getById(recipeId);
|
||||
if (optionalStoredRecipe.isEmpty()) {
|
||||
return listRecipes(
|
||||
modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, recipeId)
|
||||
.build());
|
||||
try {
|
||||
recipeService.updateRecipeAndSteps(recipeDto);
|
||||
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_RECIPE, recipeDto.getRecipe().getName());
|
||||
} catch (EntityNotFoundException ex) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.RECIPE_NOT_FOUND, recipeDto.getRecipe().getId()).build();
|
||||
}
|
||||
|
||||
Optional<Recipe> optionalRecipe = recipeService.updateRecipe(recipe, optionalStoredRecipe.get(), form);
|
||||
if (optionalRecipe.isPresent()) {
|
||||
modelResponseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_RECIPE, optionalRecipe.get().getName());
|
||||
return listRecipes(modelResponseBuilder.build());
|
||||
}
|
||||
|
||||
return listRecipes(
|
||||
modelResponseBuilder
|
||||
.addResponseCode(ResponseCode.ERROR_SAVING)
|
||||
.build());
|
||||
return getPage(modelResponseBuilder.build());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ModelResponseBuilde
|
|||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseCode;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.io.response.ResponseDataType;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.model.Recipe;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.files.ImagesService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.services.model.RecipeService;
|
||||
import dev.fyloz.trial.colorrecipesexplorer.core.utils.ControllerUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -31,28 +32,19 @@ import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;
|
|||
public class ImageFilesController {
|
||||
|
||||
private RecipeService recipeService;
|
||||
private ImagesService imagesService;
|
||||
|
||||
@Autowired
|
||||
public ImageFilesController(RecipeService recipeService) {
|
||||
public ImageFilesController(RecipeService recipeService, ImagesService imagesService) {
|
||||
this.recipeService = recipeService;
|
||||
this.imagesService = imagesService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère l'image voulue sous forme JPEG.
|
||||
*
|
||||
* @param image Le nom de l'image
|
||||
* @return L'image en JPEG.
|
||||
*/
|
||||
@GetMapping(IMAGES_FILES)
|
||||
public ResponseEntity<byte[]> getImage(@PathVariable String image) {
|
||||
ImageHandler imageHandler = new ImageHandler(image, recipeService);
|
||||
|
||||
byte[] content = imageHandler.readFile();
|
||||
if (content == null) return ResponseEntity.notFound().build();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.IMAGE_JPEG);
|
||||
return new ResponseEntity<>(content, headers, HttpStatus.OK);
|
||||
return new ResponseEntity<>(imagesService.readImage(image), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,8 +54,8 @@ public class ImageFilesController {
|
|||
* Modèle de la page:
|
||||
* - id: Contient l'identifiant de la recette
|
||||
*
|
||||
* @param model Le Model injecté par Thymeleaf
|
||||
* @param id L'identifiant de la recette
|
||||
* @param model Le Model injecté par Thymeleaf
|
||||
* @param id L'identifiant de la recette
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@GetMapping(ADD_IMAGE_SPECIFIC)
|
||||
|
@ -90,8 +82,8 @@ public class ImageFilesController {
|
|||
* <p>
|
||||
* REQUIERT UNE AUTORISATION
|
||||
*
|
||||
* @param id L'identifiant de la recette
|
||||
* @param image L'image uploadée
|
||||
* @param id L'identifiant de la recette
|
||||
* @param image L'image uploadée
|
||||
* @return La page à afficher.
|
||||
*/
|
||||
@PostMapping(ADD_IMAGE)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<link href="/css/form.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body th:with="nbrMaterials = 0">
|
||||
<body th:with="nbrMaterials = 0, recipe = ${mix.recipe}">
|
||||
<!-- Fragment de l'entête -->
|
||||
<header th:include="fragments.html :: header(false)"></header>
|
||||
<!-- Corps de la page -->
|
||||
|
|
Loading…
Reference in New Issue