From 18410682de1b45737ff11cb477e77e74e0c4be6a Mon Sep 17 00:00:00 2001 From: Tim Holloway Date: Sat, 15 Jan 2022 18:06:45 -0500 Subject: [PATCH] Have downloadable shopping list --- .../mousetech/gourmetj/ShopIngredient.java | 14 +- .../mousetech/gourmetj/ShoppingListBean.java | 124 +++++++++++++++--- .../META-INF/resources/css/style.css | 1 - .../resources/META-INF/resources/main.xhtml | 11 +- .../META-INF/resources/shoppingList.xhtml | 46 +++++-- 5 files changed, 166 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/mousetech/gourmetj/ShopIngredient.java b/src/main/java/com/mousetech/gourmetj/ShopIngredient.java index 1b71036..8d8321a 100644 --- a/src/main/java/com/mousetech/gourmetj/ShopIngredient.java +++ b/src/main/java/com/mousetech/gourmetj/ShopIngredient.java @@ -25,7 +25,7 @@ public class ShopIngredient implements Comparable { * @param ingkey * @param shopCat */ - public ShopIngredient( double amount, String unit, + public ShopIngredient( Double amount, String unit, String item, String ingkey, String shopCat) { this.amount = amount; @@ -68,14 +68,14 @@ public class ShopIngredient implements Comparable { /** * @return the amount */ - public double getAmount() { + public Double getAmount() { return amount; } /** * @param amount the amount to set */ - public void setAmount(double amount) { + public void setAmount(Double amount) { this.amount = amount; } @@ -83,8 +83,12 @@ public class ShopIngredient implements Comparable { * @return the displayAmount */ public String getDisplayAmount() { + Double amt = this.getAmount(); + if ( amt == null) { + return ""; + } return IngredientDigester.displayAmount( - IngredientAmountFormat.IA_TEXT, this.getAmount(), + IngredientAmountFormat.IA_TEXT, amt, null); } @@ -112,7 +116,7 @@ public class ShopIngredient implements Comparable { } private String ingkey; - private double amount; + private Double amount; private String displayAmount; private String unit; diff --git a/src/main/java/com/mousetech/gourmetj/ShoppingListBean.java b/src/main/java/com/mousetech/gourmetj/ShoppingListBean.java index 0d73dc3..6dbe31a 100644 --- a/src/main/java/com/mousetech/gourmetj/ShoppingListBean.java +++ b/src/main/java/com/mousetech/gourmetj/ShoppingListBean.java @@ -1,17 +1,22 @@ package com.mousetech.gourmetj; +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; -import javax.faces.event.AjaxBehaviorEvent; import javax.faces.view.ViewScoped; import javax.inject.Inject; import javax.inject.Named; import org.apache.commons.lang3.StringUtils; +import org.primefaces.model.ByteArrayContent; +import org.primefaces.model.DefaultStreamedContent; +import org.primefaces.model.StreamedContent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,11 +24,57 @@ import com.mousetech.gourmetj.persistence.dao.ShopcatRepository; import com.mousetech.gourmetj.persistence.model.Ingredient; import com.mousetech.gourmetj.persistence.model.Recipe; import com.mousetech.gourmetj.persistence.model.Shopcat; +import com.mousetech.gourmetj.utils.YamlShoppingList; @Named @ViewScoped public class ShoppingListBean implements Serializable { + public class RecipeReference { + + private int count; + private Recipe recipe; + + /** + * Constructor Constructor. + * + * @param r Recipe to reference (from Shopping List) + */ + public RecipeReference(Recipe r) { + count = 1; + recipe = r; + } + + /** + * @return the count + */ + public int getCount() { + return count; + } + + /** + * @param count the count to set + */ + public void setCount(int count) { + this.count = count; + } + + /** + * @return the recipe + */ + public Recipe getRecipe() { + return recipe; + } + + /** + * @param recipe the recipe to set + */ + public void setRecipe(Recipe recipe) { + this.recipe = recipe; + } + + } + /** * Serial version for session save/restore */ @@ -41,7 +92,7 @@ public class ShoppingListBean implements Serializable { private List siList; -// private List ingredientList; + private List recipeList; @PostConstruct public void init() { @@ -50,8 +101,19 @@ public class ShoppingListBean implements Serializable { buildMaps(); } - public List getRecipeList() { - return this.userSession.getShoppingList(); + public List getRecipeList() { + if (this.recipeList == null) { + this.recipeList = loadRecipeList(); + } + return this.recipeList; + } + + private List loadRecipeList() { + List list = + userSession.getShoppingList().stream() + .map(r -> new RecipeReference(r)) + .collect(Collectors.toList()); + return list; } public List getIngredientList() { @@ -59,7 +121,8 @@ public class ShoppingListBean implements Serializable { } private void buildMaps() { - for (Recipe r : this.getRecipeList()) { + this.siList = new ArrayList(30); + for (RecipeReference r : this.getRecipeList()) { buildMapsFor(r); } // Now consolidate amounts and sort by @@ -77,8 +140,13 @@ public class ShoppingListBean implements Serializable { * * @see #buildMaps() */ - private void buildMapsFor(Recipe r) { - for (Ingredient ing : r.getIngredientHash()) { + private void buildMapsFor(RecipeReference r) { + final int multiplier = r.getCount(); + if (multiplier == 0) { + return; + } + for (Ingredient ing : r.getRecipe() + .getIngredientHash()) { String ingkey = ing.getIngkey(); if (StringUtils.isBlank(ingkey)) { continue; @@ -86,10 +154,21 @@ public class ShoppingListBean implements Serializable { String shopCatName = ing.getShopCat() != null ? ing.getShopCat().getShopcategory() : null; - ShopIngredient sing = new ShopIngredient( - ing.getAmount(), ing.getUnit(), - ing.getItem(), ing.getIngkey(), shopCatName); - siList.add(sing); + ShopIngredient sing; + try { + Double amt = ing.getAmount(); + if (multiplier > 1 && (amt != null)) { + amt *= multiplier; + } + sing = new ShopIngredient(amt, ing.getUnit(), + ing.getItem(), ing.getIngkey(), + shopCatName); + siList.add(sing); + } catch (Exception e) { + log.error("Unable to create ShopIngredient for " + + r.getRecipe() + " Ingredient " + ing); + e.printStackTrace(); + } } } @@ -150,6 +229,12 @@ public class ShoppingListBean implements Serializable { } } + public StreamedContent getDlIngredientList() { + return YamlShoppingList + .createDownload(getIngredientList()); + } + + // ============================================= private List shopcatList; public List getShopcatList() { @@ -211,6 +296,15 @@ public class ShoppingListBean implements Serializable { this.shopcatList = null; } + /** + * Primefaces AJAX listener for changes to amount values of + * recipes the recipe list. Forces re-computation of + * ingredient requirements. + */ + public void pfAmountChange() { + buildMaps(); + } + // === private String selectedShopcat; @@ -291,12 +385,12 @@ public class ShoppingListBean implements Serializable { return; // effective NO-OP } newCat = newCat.trim(); - if ( StringUtils.isBlank(newCat)) { + if (StringUtils.isBlank(newCat)) { this.shopcatRepository - .deleteShopcatFor(this.getSelectedIngkey()); + .deleteShopcatFor(this.getSelectedIngkey()); } else { - this.shopcatRepository - .updateShopcatFor(newCat, this.getSelectedIngkey()); + this.shopcatRepository.updateShopcatFor(newCat, + this.getSelectedIngkey()); } } diff --git a/src/main/resources/META-INF/resources/css/style.css b/src/main/resources/META-INF/resources/css/style.css index af4381a..fc7c387 100644 --- a/src/main/resources/META-INF/resources/css/style.css +++ b/src/main/resources/META-INF/resources/css/style.css @@ -23,7 +23,6 @@ textarea { } #footer { - position: absolute; bottom: 90px; width: 100%; } \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/main.xhtml b/src/main/resources/META-INF/resources/main.xhtml index 8ce1080..3106eb5 100644 --- a/src/main/resources/META-INF/resources/main.xhtml +++ b/src/main/resources/META-INF/resources/main.xhtml @@ -33,7 +33,9 @@ - + + + diff --git a/src/main/resources/META-INF/resources/shoppingList.xhtml b/src/main/resources/META-INF/resources/shoppingList.xhtml index 5cdc360..81b4132 100644 --- a/src/main/resources/META-INF/resources/shoppingList.xhtml +++ b/src/main/resources/META-INF/resources/shoppingList.xhtml @@ -23,6 +23,15 @@ border-width: 0; border-style: none; } + +.noRecipe { + text-decoration: line-through; + color: gray; +} + +.plusRecipe { + +} + + + + + - + - + + + + + + @@ -64,11 +93,6 @@ /> - - - @@ -95,11 +119,17 @@ - + + + + +