Edit shopping category, mods to ingredient table edits
This commit is contained in:
parent
e6817d7c2e
commit
200317d177
|
@ -5,14 +5,12 @@ import java.util.List;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.faces.event.AjaxBehaviorEvent;
|
||||
import javax.faces.event.ValueChangeEvent;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.primefaces.event.SelectEvent;
|
||||
|
||||
import com.mousetech.gourmetj.persistence.dao.ShopcatRepository;
|
||||
import com.mousetech.gourmetj.persistence.model.Shopcat;
|
||||
|
||||
@Named
|
||||
@ViewScoped
|
||||
|
@ -34,6 +32,18 @@ public class EditShopcatBean implements Serializable {
|
|||
@Inject
|
||||
ShopcatRepository shopcatRepository;
|
||||
|
||||
/*
|
||||
* Indicate if the shopcatname has been changed.
|
||||
*/
|
||||
private boolean changed = false;
|
||||
|
||||
/**
|
||||
* @return the changed
|
||||
*/
|
||||
public boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
|
@ -45,15 +55,20 @@ public class EditShopcatBean implements Serializable {
|
|||
public void init() {
|
||||
this.shopcatSuggestionList = this.shopcatRepository
|
||||
.findDistinctCategoryNative();
|
||||
// // Get ingkey from Flash scope
|
||||
// ingkey = (String) JSFUtils.getFlash("ingkey");
|
||||
// Shopcat scat = this.shopcatRepository
|
||||
// .findShopcatByIngkey(ingkey);
|
||||
// if (scat != null) {
|
||||
// this.setShopcatName(scat.getShopcategory());
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare for edit before the dialog is displayed.
|
||||
*
|
||||
* @param ingkey Ingredient key
|
||||
* @param shopCat Previous shopping category for ingKey
|
||||
*/
|
||||
public void beginEdit(String ingkey, String shopCat) {
|
||||
this.setIngkey(ingkey);
|
||||
this.setShopcatName(shopCat);
|
||||
this.changed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the shopcatName
|
||||
*/
|
||||
|
@ -89,6 +104,11 @@ public class EditShopcatBean implements Serializable {
|
|||
return ingkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ingredient key.
|
||||
*
|
||||
* @param ingkey
|
||||
*/
|
||||
public void setIngkey(String ingkey) {
|
||||
this.ingkey = ingkey;
|
||||
}
|
||||
|
@ -99,8 +119,17 @@ public class EditShopcatBean implements Serializable {
|
|||
public List<String> getShopcatSuggestionList() {
|
||||
return shopcatSuggestionList;
|
||||
}
|
||||
|
||||
|
||||
public void ajaxShopcatSuggest(AjaxBehaviorEvent event) {
|
||||
this.shopcatName = this.shopcatSuggestion;
|
||||
}
|
||||
|
||||
/**
|
||||
* ValueChangeListener for shopcat editor.
|
||||
*
|
||||
* @param e Event, with new name in it.
|
||||
*/
|
||||
public void shopcatNameChanged(ValueChangeEvent e) {
|
||||
this.changed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.util.Set;
|
|||
import javax.annotation.PostConstruct;
|
||||
|
||||
import javax.faces.event.AjaxBehaviorEvent;
|
||||
import javax.faces.event.ValueChangeEvent;
|
||||
import javax.faces.model.DataModel;
|
||||
import javax.faces.model.ListDataModel;
|
||||
import javax.faces.view.ViewScoped;
|
||||
|
@ -203,6 +204,7 @@ public class RecipeDetailBean implements Serializable {
|
|||
ingredients
|
||||
.setWrappedData(new ArrayList<IngredientUI>(1));
|
||||
}
|
||||
log.info("Ingredient size="+ingredients.getRowCount());
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
|
@ -224,7 +226,7 @@ public class RecipeDetailBean implements Serializable {
|
|||
*/
|
||||
if (this.recipe == null) {
|
||||
Long rid =
|
||||
//(Long) JSFUtils.getFlash("recipeID");
|
||||
// (Long) JSFUtils.getFlash("recipeID");
|
||||
userSession.getLastEdit();
|
||||
if (rid != null) {
|
||||
this.recipe = loadRecipe(rid);
|
||||
|
@ -357,6 +359,7 @@ public class RecipeDetailBean implements Serializable {
|
|||
public String doAddIngredient() {
|
||||
this.addIngredientList(this.getIngredientText());
|
||||
setIngredientText(""); // clear for next entry
|
||||
updateSelectionStatus();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -376,7 +379,67 @@ public class RecipeDetailBean implements Serializable {
|
|||
doAddIngredient();
|
||||
}
|
||||
|
||||
public void ajaxMoveUp(AjaxBehaviorEvent event) {
|
||||
// ===
|
||||
/**
|
||||
* Listen to the SELECT checkboxes on Ingredients and update
|
||||
* the action button statuses.
|
||||
*
|
||||
* @param event notused
|
||||
*/
|
||||
public void ajaxSelectionListener(AjaxBehaviorEvent event) {
|
||||
updateSelectionStatus();
|
||||
}
|
||||
|
||||
private void updateSelectionStatus() {
|
||||
List<IngredientUI> ingList = getWrappedIngredients();
|
||||
final int ingCount = ingList.size();
|
||||
|
||||
boolean moveUpable = true;
|
||||
boolean moveDownable = true;
|
||||
boolean selectable = false;
|
||||
|
||||
for (int i = 0; i < ingCount; i++) {
|
||||
boolean selected = ingList.get(i).isSelected();
|
||||
if ((i == 0) && selected) {
|
||||
moveUpable = false;
|
||||
}
|
||||
if ((i == (ingCount - 1)) && selected) {
|
||||
moveDownable = false;
|
||||
}
|
||||
selectable |= selected;
|
||||
}
|
||||
this.setMoveUpAble(moveUpable && selectable);
|
||||
this.setMoveDownAble(moveDownable && selectable);
|
||||
this.setSelectable(selectable);
|
||||
}
|
||||
|
||||
// ---
|
||||
public void setMoveUpAble(boolean moveUpable) {
|
||||
this.moveUpable = moveUpable;
|
||||
}
|
||||
|
||||
public void setMoveDownAble(boolean moveDownable) {
|
||||
this.moveDownable = moveDownable;
|
||||
}
|
||||
|
||||
public void setSelectable(boolean selectable) {
|
||||
this.selectable = selectable;
|
||||
}
|
||||
|
||||
public boolean isMoveUpAble() {
|
||||
return this.moveUpable;
|
||||
}
|
||||
|
||||
public boolean isMoveDownAble() {
|
||||
return this.moveDownable;
|
||||
}
|
||||
|
||||
public boolean isSelectable() {
|
||||
return this.selectable;
|
||||
}
|
||||
|
||||
// ---
|
||||
public void ajaxMoveUp() {
|
||||
if (!isMoveUpAble()) {
|
||||
JSFUtils.addErrorMessage("Cannot move up.");
|
||||
return;
|
||||
|
@ -393,6 +456,15 @@ public class RecipeDetailBean implements Serializable {
|
|||
}
|
||||
}
|
||||
this.setDirty();
|
||||
auditRows(rows);
|
||||
}
|
||||
|
||||
private void auditRows(List<IngredientUI> rows) {
|
||||
log.info("=== AUDIT ROWS ===");
|
||||
for ( IngredientUI row : rows ) {
|
||||
log.info((row.isSelected() ? "[X]" : "[ ]" ) +" ROW="+row);
|
||||
}
|
||||
log.info("=== DONE ===");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -400,7 +472,7 @@ public class RecipeDetailBean implements Serializable {
|
|||
*
|
||||
* @param eventUnused
|
||||
*/
|
||||
public void ajaxMoveDown(AjaxBehaviorEvent event) {
|
||||
public void ajaxMoveDown() {
|
||||
if (!isMoveDownAble()) {
|
||||
JSFUtils.addErrorMessage("Cannot move down.");
|
||||
return;
|
||||
|
@ -416,9 +488,10 @@ public class RecipeDetailBean implements Serializable {
|
|||
rows.add(i, r);
|
||||
}
|
||||
}
|
||||
auditRows(rows);
|
||||
}
|
||||
|
||||
public void ajaxDeleteItems(AjaxBehaviorEvent event) {
|
||||
public void ajaxDeleteItems() {
|
||||
final List<IngredientUI> rows = getWrappedIngredients();
|
||||
List<IngredientUI> selectedRows =
|
||||
new ArrayList<IngredientUI>();
|
||||
|
@ -433,61 +506,81 @@ public class RecipeDetailBean implements Serializable {
|
|||
for (IngredientUI row : selectedRows) {
|
||||
rows.remove(row);
|
||||
}
|
||||
auditRows(rows);
|
||||
}
|
||||
|
||||
// =====
|
||||
@Inject
|
||||
EditShopcatBean editShopcatBean;
|
||||
|
||||
private boolean moveUpable;
|
||||
|
||||
private boolean moveDownable;
|
||||
|
||||
private boolean selectable;
|
||||
|
||||
/**
|
||||
* Invoked when the "E"(dit" button for Ingkey shopping
|
||||
* category has been clicked.
|
||||
*
|
||||
* @param item The item whose ingredient key will
|
||||
* have its shopping category edited. Resets the dialog
|
||||
* backing bean internal state.
|
||||
*/
|
||||
public void ajaxEditShopcat(IngredientUI item) {
|
||||
// Map<String, Object> options = new HashMap<>();
|
||||
// options.put("resizable", false);
|
||||
// TODO: Reject if ingkey is empty/null
|
||||
editShopcatBean.setIngkey(item.getIngkey());
|
||||
editShopcatBean.setShopcatName(item.getShopCat());
|
||||
// if ( ! StringUtils.isBlank(key) ) {
|
||||
// PrimeFaces.current().dialog().openDynamic("editShopcat");
|
||||
// }
|
||||
editShopcatBean.beginEdit(item.getIngkey(),
|
||||
item.getShopCat());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* On "OK" for edit shopcat where shopcat has changed,
|
||||
* update the shopcat Entity and the ingredients.
|
||||
*/
|
||||
public void doUpdateShopcat() {
|
||||
|
||||
final String key = editShopcatBean.getIngkey();
|
||||
if ( StringUtils.isBlank(key)) {
|
||||
if (StringUtils.isBlank(key)) {
|
||||
return; // Do not set category if no ingKey
|
||||
}
|
||||
|
||||
|
||||
final String catname = editShopcatBean.getShopcatName();
|
||||
|
||||
Shopcat sc = this.recipeService
|
||||
.findShopcatForIngredientKey(catname);
|
||||
.findShopcatForIngredientKey(key);
|
||||
if (sc == null) {
|
||||
sc = new Shopcat();
|
||||
sc.setIngkey(key);
|
||||
sc.setShopcategory(catname);
|
||||
} else {
|
||||
if (catname.equals(sc.getShopcategory())) {
|
||||
// No change. Do nothing.
|
||||
return;
|
||||
}
|
||||
if ( StringUtils.equals(sc.getShopcategory(), catname) ) {
|
||||
return; // No change
|
||||
}
|
||||
}
|
||||
|
||||
if ( StringUtils.isBlank(catname)) {
|
||||
this.recipeService.deleteShopcat(sc);
|
||||
} else {
|
||||
sc.setShopcategory(catname);
|
||||
|
||||
/*
|
||||
* Because the database does not have a UNIQUE
|
||||
* constraint on ingkeys, we must delete old
|
||||
* shopcat(s) for this key before adding (updating)
|
||||
* the new shopcat.
|
||||
*/
|
||||
this.recipeService.deleteShopcatByIngKey(key);
|
||||
if (! StringUtils.isBlank(catname)) {
|
||||
this.recipeService.saveShopcat(sc);
|
||||
}
|
||||
updateDisplayedShopcats(key, sc);
|
||||
}
|
||||
|
||||
/**
|
||||
* When Shopcat name changes, update the Ingredients.
|
||||
* In detailEdit, an AJAX "render" will then update
|
||||
* the display. In recipeDetails, nothing actually shows.
|
||||
* When Shopcat name changes, update the Ingredients. In
|
||||
* detailEdit, an AJAX "render" will then update the display.
|
||||
* In recipeDetails, nothing actually shows.
|
||||
*/
|
||||
private void updateDisplayedShopcats(String key, Shopcat sc) {
|
||||
List<IngredientUI> ingList = this.getWrappedIngredients();
|
||||
for (IngredientUI ingUI: ingList ) {
|
||||
if ( key.equals(ingUI.getIngkey())) {
|
||||
private void updateDisplayedShopcats(String key,
|
||||
Shopcat sc) {
|
||||
List<IngredientUI> ingList =
|
||||
this.getWrappedIngredients();
|
||||
for (IngredientUI ingUI : ingList) {
|
||||
if (key.equals(ingUI.getIngkey())) {
|
||||
ingUI.setShopCat(sc);
|
||||
}
|
||||
}
|
||||
|
@ -521,6 +614,7 @@ public class RecipeDetailBean implements Serializable {
|
|||
}
|
||||
addIngredient(line);
|
||||
}
|
||||
updateSelectionStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -541,43 +635,6 @@ public class RecipeDetailBean implements Serializable {
|
|||
ingredients.add(new IngredientUI(ing));
|
||||
}
|
||||
|
||||
public boolean isSelectionActive() {
|
||||
List<IngredientUI> rows = getWrappedIngredients();
|
||||
for (IngredientUI row : rows) {
|
||||
if (row.isSelected()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSelectionActive(boolean value) {
|
||||
// This is required by JBoss JSF, but the property is
|
||||
// read-only.
|
||||
}
|
||||
|
||||
public void setMoveUpAble() {
|
||||
|
||||
}
|
||||
|
||||
public void setMoveDownAble() {
|
||||
|
||||
}
|
||||
|
||||
public boolean isMoveUpAble() {
|
||||
return true;
|
||||
// TODO:
|
||||
// if (isSelectionActive()) {
|
||||
// List<IngredientUI> rows = getWrappedIngredients();
|
||||
// return !rows.get(0).isSelected();
|
||||
// }
|
||||
// return false;
|
||||
}
|
||||
|
||||
public boolean isMoveDownAble() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===
|
||||
|
||||
/**
|
||||
|
@ -695,16 +752,15 @@ public class RecipeDetailBean implements Serializable {
|
|||
Shopcat scat = recipeService
|
||||
.findShopcatForIngredientKey(ingKey);
|
||||
if (scat == null) {
|
||||
JSFUtils.addErrorMessage(
|
||||
log.debug(
|
||||
"No Shopping Category is defined for Ingredient Key "
|
||||
+ ingKey);
|
||||
//return false;
|
||||
|
||||
// return false;
|
||||
}
|
||||
ing.setShopCat(scat);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse out the comma-separated category text control and
|
||||
* post the results as children of the recipe
|
||||
|
@ -865,7 +921,6 @@ public class RecipeDetailBean implements Serializable {
|
|||
public void ajaxUpdateShopcat(IngredientUI item) {
|
||||
log.warn("SHOPCAT2 ");
|
||||
updateShopcat(item);
|
||||
;
|
||||
}
|
||||
|
||||
// ***
|
||||
|
@ -1002,9 +1057,9 @@ public class RecipeDetailBean implements Serializable {
|
|||
long now = new java.util.Date().getTime();
|
||||
return String.valueOf(now);
|
||||
}
|
||||
|
||||
//*** Add Group
|
||||
|
||||
|
||||
// *** Add Group
|
||||
|
||||
private String newGroupName;
|
||||
|
||||
/**
|
||||
|
@ -1020,16 +1075,18 @@ public class RecipeDetailBean implements Serializable {
|
|||
public void setNewGroupName(String newGroupName) {
|
||||
this.newGroupName = newGroupName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add new group to bottom of model as AJAX operation.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public void doAddGroup() {
|
||||
IngredientUI iui = new IngredientUI(null);
|
||||
iui.setIngGroup(true);
|
||||
iui.setItem(this.getNewGroupName());
|
||||
List<IngredientUI> ingUIList = this.getWrappedIngredients();
|
||||
List<IngredientUI> ingUIList =
|
||||
this.getWrappedIngredients();
|
||||
ingUIList.add(iui);
|
||||
this.setNewGroupName(""); // Clear for next time!
|
||||
}
|
||||
|
|
|
@ -29,4 +29,6 @@ public interface ShopcatRepository
|
|||
public List<String> findDistinctCategoryNative();
|
||||
|
||||
public Shopcat findShopcatByIngkey(String ingkey);
|
||||
|
||||
public void deleteByIngkey(String key);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ public class Ingredient implements Serializable, IngredientIF {
|
|||
private String item;
|
||||
|
||||
@Column(name = "optional")
|
||||
@NotNull
|
||||
//@NotNull
|
||||
private Integer optional;
|
||||
|
||||
@Column(name = "position")
|
||||
|
@ -81,6 +81,8 @@ public class Ingredient implements Serializable, IngredientIF {
|
|||
private String unit;
|
||||
|
||||
public Ingredient() {
|
||||
// Attempt to remedy lack of constraints in DB
|
||||
this.optional = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -90,6 +90,11 @@ public class RecipeService implements Serializable {
|
|||
}
|
||||
|
||||
|
||||
public void deleteShopcatByIngKey(String key) {
|
||||
shopcatRepository.deleteByIngkey(key);
|
||||
}
|
||||
|
||||
|
||||
public void saveShopcat(Shopcat sc) {
|
||||
shopcatRepository.save(sc);
|
||||
}
|
||||
|
|
|
@ -47,12 +47,26 @@
|
|||
style="z-index: 25000"
|
||||
>
|
||||
<p:commandButton id="cmdExpiredOK"
|
||||
value="OK"
|
||||
action="/main.jsf"
|
||||
value="OK" action="/main.jsf"
|
||||
oncomplete="PF('sessionExpiredConfirmation').hide()"
|
||||
/>
|
||||
</p:confirmDialog>
|
||||
</h:form>
|
||||
<!-- -->
|
||||
<h:form id="frmOpErr">
|
||||
<p:commandButton type="button"
|
||||
onclick="PF('opError').show()"
|
||||
/>
|
||||
<p:confirmDialog
|
||||
message="Session may have expired."
|
||||
header="Error"
|
||||
severity="alert" widgetVar="opError"
|
||||
>
|
||||
<p:commandButton value="OK"
|
||||
oncomplete="PF('cd').hide()"
|
||||
/>
|
||||
</p:confirmDialog>
|
||||
</h:form>
|
||||
</h:body>
|
||||
</f:view>
|
||||
</ui:composition>
|
||||
|
|
|
@ -100,7 +100,6 @@
|
|||
max="10"
|
||||
value="#{recipeDetailBean.recipe.preptime}"
|
||||
>
|
||||
<f:validator validatorId="com.mousetech.gourmetj.utils.TimeValidator"/>
|
||||
<f:converter
|
||||
converterId="com.mousetech.gourmetj.utils.TimeConverter"
|
||||
/>
|
||||
|
@ -110,9 +109,8 @@
|
|||
/>
|
||||
<p:inputText id="rcooktime"
|
||||
max="10"
|
||||
value="#{recipeDetailBean.recipe.cooktime}"
|
||||
value="#{recipeDetailBean.recipe.cooktime}"
|
||||
>
|
||||
<f:validator validatorId="com.mousetech.gourmetj.utils.TimeValidator"/>
|
||||
<f:converter
|
||||
converterId="com.mousetech.gourmetj.utils.TimeConverter"
|
||||
/>
|
||||
|
@ -178,23 +176,17 @@
|
|||
<p:commandButton value="Up"
|
||||
disabled="#{not recipeDetailBean.moveUpAble}"
|
||||
id="ctlUp"
|
||||
>
|
||||
<f:ajax
|
||||
listener="#{recipeDetailBean.ajaxMoveUp}"
|
||||
execute="ingredientTable"
|
||||
render="ingredientTable"
|
||||
/>
|
||||
</p:commandButton>
|
||||
actionListener="#{recipeDetailBean.ajaxMoveUp}"
|
||||
update="ingredientTable"
|
||||
onerror="PF('opError').show()"
|
||||
/>
|
||||
<p:commandButton value="Down"
|
||||
disabled="#{not recipeDetailBean.moveDownAble}"
|
||||
id="ctlDown"
|
||||
>
|
||||
<f:ajax
|
||||
listener="#{recipeDetailBean.ajaxMoveDown}"
|
||||
execute="ingredientTable"
|
||||
render="ingredientTable"
|
||||
/>
|
||||
</p:commandButton>
|
||||
onerror="PF('opError').show()"
|
||||
actionListener="#{recipeDetailBean.ajaxMoveDown}"
|
||||
update="ingredientTable"
|
||||
/>
|
||||
<p:commandButton
|
||||
value="Add Group"
|
||||
onclick="PF('addGroupDlg').show()"
|
||||
|
@ -211,17 +203,14 @@
|
|||
<p:commandButton
|
||||
value="Delete"
|
||||
id="ctlDelete"
|
||||
disabled="not #{recipeDetailBean.selectionActive}"
|
||||
>
|
||||
<f:ajax
|
||||
listener="#{recipeDetailBean.ajaxDeleteItems}"
|
||||
immediate="true"
|
||||
render="ingredientTable"
|
||||
/>
|
||||
</p:commandButton>
|
||||
disabled="#{not recipeDetailBean.selectable}"
|
||||
onerror="PF('opError').show()"
|
||||
actionListener="#{recipeDetailBean.ajaxDeleteItems}"
|
||||
update="ingredientTable"
|
||||
/>
|
||||
</h:panelGroup>
|
||||
<p:dataTable id="ingredientTable"
|
||||
style="width: 100%; height: 420px; margin-top: 8px"
|
||||
style="width: 100%; height: 430px; margin-top: 8px"
|
||||
value="#{recipeDetailBean.ingredients}"
|
||||
scrollable="true"
|
||||
scrollHeight="380" var="item"
|
||||
|
@ -235,8 +224,8 @@
|
|||
value="#{item.selected}"
|
||||
>
|
||||
<f:ajax
|
||||
immediate="true"
|
||||
render="pnlIngredients"
|
||||
listener="#{recipeDetailBean.ajaxSelectionListener}"
|
||||
render=":form1:tabGroupClient:ingButtons"
|
||||
/>
|
||||
</p:selectBooleanCheckbox>
|
||||
</p:column>
|
||||
|
@ -320,6 +309,7 @@
|
|||
update="editShopcatDlg"
|
||||
oncomplete="PF('editShopcatDlg').show()"
|
||||
title="Edit the shopping category for ing. key"
|
||||
disabled="#{empty item.ingkey}"
|
||||
rendered="#{not item.ingGroup}"
|
||||
/>
|
||||
</p:column>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
value="Category Name" />
|
||||
<p:inputText id="ctlShopcat"
|
||||
value="#{editShopcatBean.shopcatName}"
|
||||
valueChangeListener="#{editShopcatBean.shopcatNameChanged}"
|
||||
>
|
||||
</p:inputText>
|
||||
<h:outputText
|
||||
|
|
Loading…
Reference in New Issue
Block a user