Continue transition vers exceptions + DTO

This commit is contained in:
FyloZ 2020-02-19 06:46:31 -05:00
parent a1cc594acd
commit 26110beac2
17 changed files with 220 additions and 199 deletions

2
.gitignore vendored
View File

@ -28,5 +28,5 @@ HELP.md
### VS Code ###
.vscode/
/logs/
*.log
/workdir/

View File

@ -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;

View File

@ -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";

View File

@ -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;
}
}

View File

@ -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),

View File

@ -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;
}

View File

@ -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.
*

View File

@ -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);
}
}

View File

@ -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.
*

View File

@ -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));
}
/**

View File

@ -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());
}
}

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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)

View File

@ -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 -->