-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
621 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,8 @@ | |
"private": true, | ||
"packageManager": "[email protected]", | ||
"scripts": { | ||
"build": "webpack --mode production" | ||
"build": "webpack --mode production", | ||
"watch": "webpack --mode production --watch --progress" | ||
}, | ||
"devDependencies": { | ||
"@tailwindcss/typography": "^0.5.10", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package se.kassner.whattocook; | ||
|
||
import org.springframework.stereotype.Controller; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
|
||
@Controller | ||
public class AppController | ||
{ | ||
@GetMapping("/") | ||
public String home() | ||
{ | ||
return "home"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
180 changes: 180 additions & 0 deletions
180
src/main/java/se/kassner/whattocook/manage/RecipeController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
package se.kassner.whattocook.manage; | ||
|
||
import jakarta.persistence.EntityNotFoundException; | ||
import org.hibernate.exception.ConstraintViolationException; | ||
import jakarta.validation.Valid; | ||
import org.springframework.dao.DataIntegrityViolationException; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.ui.Model; | ||
import org.springframework.validation.BindingResult; | ||
import org.springframework.web.bind.annotation.*; | ||
import org.springframework.web.servlet.mvc.support.RedirectAttributes; | ||
import se.kassner.whattocook.Ingredient; | ||
import se.kassner.whattocook.IngredientRepository; | ||
import se.kassner.whattocook.Recipe; | ||
import se.kassner.whattocook.RecipeRepository; | ||
|
||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
@Controller | ||
@RequestMapping("/manage/recipe") | ||
public class RecipeController | ||
{ | ||
private final RecipeRepository recipeRepository; | ||
|
||
private final IngredientRepository ingredientRepository; | ||
|
||
public RecipeController(RecipeRepository recipeRepository, IngredientRepository ingredientRepository) | ||
{ | ||
this.recipeRepository = recipeRepository; | ||
this.ingredientRepository = ingredientRepository; | ||
} | ||
|
||
@GetMapping | ||
public String get(Model model) | ||
{ | ||
List<Recipe> recipes = recipeRepository.findAllForListing(); | ||
model.addAttribute("recipes", recipes); | ||
|
||
return "recipe/index"; | ||
} | ||
|
||
@GetMapping("/add") | ||
public String add(RecipeForm recipeForm, Model model) | ||
{ | ||
model.addAttribute("form_title", "Add recipe"); | ||
model.addAttribute("form_url", "/manage/recipe/add"); | ||
|
||
return "recipe/form"; | ||
} | ||
|
||
@PostMapping("/add") | ||
public String addPost(@Valid RecipeForm recipeForm, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) | ||
{ | ||
model.addAttribute("form_title", "Add recipe"); | ||
model.addAttribute("form_url", "/manage/recipe/add"); | ||
|
||
if (bindingResult.hasErrors()) { | ||
return "recipe/form"; | ||
} | ||
|
||
Recipe recipe = new Recipe(); | ||
recipe.setName(recipeForm.getName()); | ||
recipe.setInstructions(recipeForm.getInstructions()); | ||
recipe.setIngredients(convertIngredients(recipeForm.getIngredients())); | ||
|
||
return saveRecipe(recipe, model, redirectAttributes); | ||
} | ||
|
||
@GetMapping("/{id}/edit") | ||
public String edit(@PathVariable("id") Long recipeId, Model model, RedirectAttributes redirectAttributes) | ||
{ | ||
Recipe recipe; | ||
try { | ||
recipe = recipeRepository.getReferenceById(recipeId); | ||
} catch (EntityNotFoundException e) { | ||
redirectAttributes.addFlashAttribute("error", e.getMessage()); | ||
return "redirect:/manage/recipe"; | ||
} | ||
|
||
RecipeForm recipeForm = new RecipeForm(recipe); | ||
model.addAttribute("form_title", String.format("Edit recipe \"%s\"", recipe.getName())); | ||
model.addAttribute("form_url", String.format("/manage/recipe/%d/edit", recipe.getId())); | ||
model.addAttribute("recipeForm", recipeForm); | ||
|
||
return "recipe/form"; | ||
} | ||
|
||
@PostMapping(value = "/{id}/edit") | ||
public String edit( | ||
@PathVariable("id") Long recipeId, | ||
@Valid RecipeForm recipeForm, | ||
BindingResult bindingResult, | ||
Model model, | ||
RedirectAttributes redirectAttributes | ||
) | ||
{ | ||
Recipe recipe; | ||
try { | ||
recipe = recipeRepository.getReferenceById(recipeId); | ||
} catch (EntityNotFoundException e) { | ||
redirectAttributes.addFlashAttribute("error", e.getMessage()); | ||
return "redirect:/manage/recipe"; | ||
} | ||
|
||
model.addAttribute("form_title", String.format("Edit recipe \"%s\"", recipe.getName())); | ||
model.addAttribute("form_url", String.format("/manage/recipe/%d/edit", recipe.getId())); | ||
model.addAttribute("recipeForm", recipeForm); | ||
|
||
if (bindingResult.hasErrors()) { | ||
return "recipe/form"; | ||
} | ||
|
||
recipe.setName(recipeForm.getName()); | ||
recipe.setInstructions(recipeForm.getInstructions()); | ||
recipe.setIngredients(convertIngredients(recipeForm.getIngredients())); | ||
|
||
return saveRecipe(recipe, model, redirectAttributes); | ||
} | ||
|
||
private Set<Ingredient> convertIngredients(String[] ingredientNames) | ||
{ | ||
Set<Ingredient> recipeIngredients = new HashSet<>(); | ||
|
||
for (String ingredientName : ingredientNames) { | ||
if (ingredientName.isEmpty()) { | ||
continue; | ||
} | ||
|
||
Ingredient ingredient = ingredientRepository.getOneByName(ingredientName); | ||
|
||
if (ingredient == null) { | ||
ingredient = new Ingredient(ingredientName); | ||
ingredientRepository.save(ingredient); | ||
} | ||
|
||
recipeIngredients.add(ingredient); | ||
} | ||
|
||
return recipeIngredients; | ||
} | ||
|
||
@PostMapping("/{id}/delete") | ||
public String delete(@PathVariable Long id, RedirectAttributes redirectAttributes) | ||
{ | ||
// @TODO do not allow delete recipes assigned to an ongoing session | ||
|
||
try { | ||
Recipe recipe = recipeRepository.getReferenceById(id); | ||
recipeRepository.delete(recipe); | ||
redirectAttributes.addFlashAttribute("success", String.format("Recipe %s deleted", recipe.getName())); | ||
} catch (Exception e) { | ||
redirectAttributes.addFlashAttribute("error", e.getMessage()); | ||
} | ||
|
||
return "redirect:/manage/recipe"; | ||
} | ||
|
||
private String saveRecipe(Recipe recipe, Model model, RedirectAttributes redirectAttributes) | ||
{ | ||
try { | ||
recipeRepository.saveAndFlush(recipe); | ||
redirectAttributes.addFlashAttribute("success", String.format("Recipe \"%s\" modified", recipe.getName())); | ||
} catch (DataIntegrityViolationException e) { | ||
ConstraintViolationException cause = (ConstraintViolationException) e.getCause(); | ||
if (cause.getConstraintName().equals("recipe_name_unique")) { | ||
model.addAttribute("error", "There is a recipe with the chosen name is already registered"); | ||
} else { | ||
model.addAttribute("error", e.getMessage()); | ||
} | ||
|
||
return "recipe/form"; | ||
} catch (Exception e) { | ||
redirectAttributes.addFlashAttribute("error", e.getMessage()); | ||
} | ||
|
||
return "redirect:/manage/recipe"; | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
src/main/java/se/kassner/whattocook/manage/RecipeForm.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package se.kassner.whattocook.manage; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import org.hibernate.validator.constraints.Length; | ||
import se.kassner.whattocook.Ingredient; | ||
import se.kassner.whattocook.Recipe; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class RecipeForm | ||
{ | ||
private Long id; | ||
|
||
@NotBlank | ||
@Length(min = 2, max = 255) | ||
private String name; | ||
|
||
private String instructions; | ||
|
||
private String[] ingredients = new String[]{""}; | ||
|
||
public RecipeForm() | ||
{ | ||
} | ||
|
||
public RecipeForm(Long id, String name, String instructions, String[] ingredients) | ||
{ | ||
this.id = id; | ||
this.name = name; | ||
this.instructions = instructions; | ||
this.ingredients = ingredients; | ||
|
||
if (this.ingredients.length == 0) { | ||
this.ingredients = new String[]{""}; | ||
} | ||
} | ||
|
||
public RecipeForm(Recipe recipe) | ||
{ | ||
this.id = recipe.getId(); | ||
this.name = recipe.getName(); | ||
this.instructions = recipe.getInstructions(); | ||
this.ingredients = recipe.getIngredients().stream().map(Ingredient::getName).toArray(String[]::new); | ||
|
||
if (this.ingredients.length == 0) { | ||
this.ingredients = new String[]{""}; | ||
} | ||
} | ||
|
||
public Long getId() | ||
{ | ||
return id; | ||
} | ||
|
||
public String getName() | ||
{ | ||
return name; | ||
} | ||
|
||
public String getInstructions() | ||
{ | ||
return instructions; | ||
} | ||
|
||
public String[] getIngredients() | ||
{ | ||
return ingredients; | ||
} | ||
|
||
public void setId(Long id) | ||
{ | ||
this.id = id; | ||
} | ||
|
||
public void setName(String name) | ||
{ | ||
this.name = name; | ||
} | ||
|
||
public void setInstructions(String instructions) | ||
{ | ||
this.instructions = instructions; | ||
} | ||
|
||
public void setIngredients(String[] ingredients) | ||
{ | ||
this.ingredients = ingredients; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
html, body { | ||
width: 100%; | ||
height: 100%; | ||
} |
Oops, something went wrong.