Tab for editing shopping categories completed.

version2
Tim Holloway 2 years ago
parent 1290c66055
commit 75a8487cfb
  1. 134
      src/main/java/com/mousetech/gourmetj/ShoppingListBean.java
  2. 21
      src/main/java/com/mousetech/gourmetj/persistence/dao/ShopcatRepository.java
  3. 14
      src/main/resources/META-INF/resources/WEB-INF/layout/layout.xhtml
  4. 199
      src/main/resources/META-INF/resources/WEB-INF/layout/misctabs/ingshopkey.xhtml
  5. 6
      src/main/resources/META-INF/resources/css/style.css
  6. 118
      src/main/resources/META-INF/resources/shoppingList.xhtml

@ -12,7 +12,6 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.primefaces.event.ReorderEvent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -151,9 +150,9 @@ public class ShoppingListBean implements Serializable {
} }
} }
private List<Shopcat> shopcatList; private List<String> shopcatList;
public List<Shopcat> getShopcatList() { public List<String> getShopcatList() {
if (shopcatList == null) { if (shopcatList == null) {
shopcatList = loadShopcatList(); shopcatList = loadShopcatList();
} }
@ -163,9 +162,9 @@ public class ShoppingListBean implements Serializable {
@Inject @Inject
ShopcatRepository shopcatRepository; ShopcatRepository shopcatRepository;
private List<Shopcat> loadShopcatList() { private List<String> loadShopcatList() {
return shopcatRepository return shopcatRepository.findDistinctCategoryNative();
.findAllByOrderByShopcategoryAsc(); // .findAllByOrderByShopcategoryAsc();
} }
private Shopcat xeditShopcat = new Shopcat(); private Shopcat xeditShopcat = new Shopcat();
@ -180,19 +179,19 @@ public class ShoppingListBean implements Serializable {
} }
public void doEditShopcat(int scId) { public void doEditShopcat(int scId) {
xeditShopcat = null; // xeditShopcat = null;
final List<Shopcat> scl = getShopcatList(); // final List<Shopcat> scl = getShopcatList();
for (Shopcat sc : scl) { // for (Shopcat sc : scl) {
if (sc.getId() == scId) { // if (sc.getId() == scId) {
xeditShopcat = sc; // xeditShopcat = sc;
this.oldShopcategoryName = sc.getShopcategory(); // this.oldShopcategoryName = sc.getShopcategory();
if (sc.getPosition() == null) { // if (sc.getPosition() == null) {
sc.setPosition(0); // sc.setPosition(0);
} // }
return; // return;
} // }
} // }
log.error("SHOPCAT " + scId + " NOT FOUND"); // log.error("SHOPCAT " + scId + " NOT FOUND");
} }
public void ajaxOnClickShopcatIngkey() { public void ajaxOnClickShopcatIngkey() {
@ -202,12 +201,103 @@ public class ShoppingListBean implements Serializable {
} }
/** /**
* Updates all ingredient keys for shopcat name-change. * Updates all ingredient keys for shopcat name-change. Note
* Note that once done, this cannot be undone! * that once done, this cannot be undone!
*/ */
public void ajaxOnClickShopcat() { public void ajaxOnClickShopcat() {
this.shopcatRepository.UpdateShopcats( this.shopcatRepository.UpdateShopcats(
this.oldShopcategoryName, xeditShopcat.getShopcategory()); this.oldShopcategoryName,
xeditShopcat.getShopcategory());
this.shopcatList = null; this.shopcatList = null;
} }
// ===
private String selectedShopcat;
/**
* @return the selectedShopcat
*/
public String getSelectedShopcat() {
return selectedShopcat;
}
/**
* @param selectedShopcat the selectedShopcat to set
*/
public void setSelectedShopcat(String selectedShopcat) {
this.selectedShopcat = selectedShopcat;
this.ingkeyList = null;
}
private List<String> selectedIngkey;
/**
* @return the selectedIngkey
*/
public List<String> getSelectedIngkey() {
return selectedIngkey;
}
/**
* @param selectedIngkey the selectedIngkey to set
*/
public void setSelectedIngkey(List<String> selectedIngkey) {
this.selectedIngkey = selectedIngkey;
}
private List<String> ingkeyList;
/**
* @return the ingkeyList
*/
public List<String> getIngkeyList() {
if (ingkeyList == null) {
ingkeyList = loadIngkeyListFor(selectedShopcat);
}
return ingkeyList;
}
private List<String> loadIngkeyListFor(
String selectedShopcat2) {
List<String> list = this.shopcatRepository
.findByIngkeySorted(selectedShopcat2);
return list;
}
private String newShopcat;
/**
* @return the newShopcat
*/
public String getNewShopcat() {
return newShopcat;
}
/**
* @param newShopcat the newShopcat to set
*/
public void setNewShopcat(String newShopcat) {
this.newShopcat = newShopcat;
}
public List<String> suggestShopcat(String query) {
return this.shopcatList;
}
public void doChangeShopcat() {
String oldCat = this.getSelectedShopcat();
String newCat = this.getNewShopcat();
if (oldCat.equals(newCat)) {
return; // effective NO-OP
}
newCat = newCat.trim();
if ( StringUtils.isBlank(newCat)) {
this.shopcatRepository
.deleteShopcatFor(this.getSelectedIngkey());
} else {
this.shopcatRepository
.updateShopcatFor(newCat, this.getSelectedIngkey());
}
}
} }

@ -12,8 +12,8 @@ import org.springframework.stereotype.Repository;
import com.mousetech.gourmetj.persistence.model.Shopcat; import com.mousetech.gourmetj.persistence.model.Shopcat;
/** /**
* JpaRepository for Shopping Categories, which relate ManyToOne to Ingredient. * JpaRepository for Shopping Categories, which relate ManyToOne
* Service method is @see RecipeService * to Ingredient. Service method is @see RecipeService
* *
* @author timh * @author timh
* @since Dec 28, 2021 * @since Dec 28, 2021
@ -34,11 +34,24 @@ public interface ShopcatRepository
@Transactional @Transactional
@Query(value = "UPDATE Shopcat set shopcategory = :newCatname WHERE shopcategory = :oldCatname") @Query(value = "UPDATE Shopcat set shopcategory = :newCatname WHERE shopcategory = :oldCatname")
@Modifying @Modifying
public int UpdateShopcats(String oldCatname, String newCatname); public int UpdateShopcats(String oldCatname,
String newCatname);
public Shopcat findShopcatByIngkey(String ingkey); public Shopcat findShopcatByIngkey(String ingkey);
public void deleteByIngkey(String key); public void deleteByIngkey(String key);
public List<Shopcat> findAllByOrderByShopcategoryAsc(); public List<Shopcat> findAllByOrderByShopcategoryAsc();
@Query(value = "SELECT s.ingkey FROM Shopcat s WHERE s.shopcategory = :shopcat ORDER BY s.ingkey")
public List<String> findByIngkeySorted(String shopcat);
@Transactional
@Query(value = "UPDATE Shopcat set shopcategory = :newCat WHERE ingkey IN :selectedIngkey")
@Modifying
public void updateShopcatFor(String newCat, List<String> selectedIngkey);
@Transactional
@Query(value = "DELETE Shopcat WHERE ingkey IN :selectedIngkey")
@Modifying public void deleteShopcatFor(List<String> selectedIngkey);
} }

@ -25,11 +25,15 @@
<ui:insert name="content"> <ui:insert name="content">
<ui:include src="content.xhtml" /> <ui:include src="content.xhtml" />
</ui:insert> </ui:insert>
<!-- -->
(C) 2021 Tim Holloway, Licensed under the <a <div id="footer">
href="http://www.apache.org/licenses/LICENSE-2.0" (C) 2021 Tim Holloway, Licensed under the <a
>Apache License, Version 2.0</a>. href="http://www.apache.org/licenses/LICENSE-2.0"
<p>Based on Gourmet Recipe Manager by T. Hinkle</p> >Apache License, Version 2.0</a>.
<p>Based on Gourmet Recipe Manager by T.
Hinkle</p>
</div>
<!-- -->
<h:form id="frmTimeout"> <h:form id="frmTimeout">
<p:idleMonitor <p:idleMonitor
timeout="#{userSession.sessionTimeoutInterval}" timeout="#{userSession.sessionTimeoutInterval}"

@ -1,121 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" <html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui" xmlns:p="http://primefaces.org/ui"
xmlns:c="http://xmlns.jcp.org/jstl"
> >
<!-- === Edit ingkey/shopcat === --> <!-- === Edit ingkey/shopcat === -->
<h:form id="frmIsk1"> <h:form id="frmIsk">
<p:dataTable id="tblShopcats" <p:panelGrid>
style="width: 300px" <p:row>
value="#{shoppingListBean.shopcatList}"
sortBy="#{item.shopcategory}" var="item"
>
<f:facet name="header">
<h:outputText
value="Ingredient Keys/Shopping Categories" />
</f:facet>
<p:headerRow>
<p:column>
<h:outputText id="ctlCatname"
value="#{item.shopcategory}" />
</p:column>
<p:column style="width: 5em">
<p:commandButton
id="ctlEditCat" value="Rename"
action="#{shoppingListBean.doEditShopcat(item.id)}"
onclick="PF('dlgEditShopcat').show()"
update="frmEscat:pnlData" />
</p:column>
</p:headerRow>
<p:column> <p:column>
<h:outputText value="#{item.ingkey}" <p:outputLabel for="ctlScSel"
onclick="clickIngkeyName()" /> value="Shopping Category"
/>
</p:column> </p:column>
<p:column style="width: 5em"> <p:column>
<p:commandButton <p:outputLabel for="ctlIngkeySel"
id="ctlEditIngkey" value="Move" value="Ingredient Key"
action="#{shoppingListBean.doEditShopcat(item.id)}" />
onclick="PF('dlgEditIngkey').show()" </p:column>
update="frmIngkey:pnlData" /> </p:row>
<p:row style="vertical-align: top">
<p:column>
<p:selectOneListbox id="ctlScSel"
style="width: 240px"
value="#{shoppingListBean.selectedShopcat}"
>
<f:selectItems
value="#{shoppingListBean.shopcatList}"
/>
<p:ajax update="ctlIngkeySel" event="change" />
</p:selectOneListbox>
</p:column>
<p:column>
<h:selectManyListbox id="ctlIngkeySel"
style="width: 240px"
value="#{shoppingListBean.selectedIngkey}"
label="Ingcat"
>
<f:selectItems
value="#{shoppingListBean.ingkeyList}"
/>
<p:ajax event="change" update="ctlChangeCat"/>
</h:selectManyListbox>
</p:column>
</p:row>
<p:row>
<p:column>
<p:outputLabel
value="Change shopping category to:"
/>
</p:column>
<p:column>
<p:autoComplete
value="#{shoppingListBean.newShopcat}"
autoSelection="false" forceSelection="false"
maxResults="12"
completeMethod="#{shoppingListBean.suggestShopcat}"
/>
</p:column>
</p:row>
<p:row>
<p:column>
<p:commandButton id="ctlChangeCat" value="Change..."
disabled="#{empty shoppingListBean.selectedIngkey}"
onclick="PF('dlgOkRecat').show()"
/>
</p:column>
<p:column>
<h:outputText value="" />
</p:column> </p:column>
</p:dataTable> </p:row>
</h:form> </p:panelGrid>
<!-- --> </h:form>
<h:form id="frmEscat"> <!-- -->
<p:dialog id="dlgEditShopcat" <h:form id="frmDelete">
widgetVar="dlgEditShopcat" <p:confirmDialog closable="false" id="dlgOkRecat"
header="Edit/Rename Shopping Category" header="Confirm Change - CANNOT UNDO"
closeOnEscape="true" message="OK to CHANGE Shopping Category for these Ingredient Keys?"
> severity="alert" widgetVar="dlgOkRecat"
<p:panelGrid id="pnlData" columns="2" style="z-index: 25000"
styleClass="ui-panelgrid-blank" >
> <p:commandButton id="dlgOK" value="OK"
<p:outputLabel for="@next" oncomplete="PF('dlgOkRecat').hide()"
value="Shopping Category" /> action="#{shoppingListBean.doChangeShopcat}"
<p:inputText id="ctlDlgShopcatName" update="@form:@parent:frmIsk:ctlScSel @form:@parent:frmIsk:ctlIngkeySel"
label="Position" required="true" immediate="true"
value="#{shoppingListBean.editShopcat.shopcategory}" /> />
<p:outputLabel for="@next" <p:commandButton id="dlgCancel" value="Cancel"
value="Position" /> onclick="PF('dlgOkRecat').hide()"
<p:inputText />
id="ctlDlgShopcatPosition" type="number" </p:confirmDialog>
required="true" size="3" </h:form>
value="#{shoppingListBean.editShopcat.position}" />
</p:panelGrid>
<p:panelGrid columns="2"
style="width: 100%"
styleClass="ui-panelgrid-blank"
>
<p:commandButton id="scDlgOK"
value="OK" style="width: 6em"
action="#{shoppingListBean.ajaxOnClickShopcat}"
update="frmIsk1:tblShopcats"
process="@this pnlData"
oncomplete="PF('dlgEditShopcat').hide()" />
<p:commandButton id="scDlgCan"
value="Cancel" style="width: 6em"
onclick="PF('dlgEditShopcat').hide()" />
</p:panelGrid>
</p:dialog>
</h:form>
<!-- -->
<h:form id="frmIngkey">
<p:dialog id="dlgEditIngkey"
widgetVar="dlgEditIngkey"
header="Edit/Rename Shopping Category for Ingredient Key"
closeOnEscape="true"
>
<p:panelGrid id="pnlData" columns="2"
styleClass="ui-panelgrid-blank"
>
<p:outputLabel for="@next"
value="Ingredient Key" />
<h:outputText
id="ctlDlgIngKeyIngkey"
value="#{shoppingListBean.editShopcat.ingkey}" />
<p:outputLabel for="@next"
value="Shopping Category" />
<p:inputText
id="ctlDlgIngkeyShopcatName" label="Position"
required="true"
value="#{shoppingListBean.editShopcat.shopcategory}" />
</p:panelGrid>
<p:panelGrid columns="2"
style="width: 100%"
styleClass="ui-panelgrid-blank"
>
<p:commandButton id="ingkDlgOK"
value="OK" style="width: 6em"
action="#{shoppingListBean.ajaxOnClickShopcatIngkey}"
update="frmIsk1:tblShopcats"
process="@this pnlData"
oncomplete="PF('dlgEditIngkey').hide()" />
<p:commandButton id="ingkDlgCan"
value="Cancel" style="width: 6em"
onclick="PF('dlgEditIngkey').hide()" />
</p:panelGrid>
</p:dialog>
</h:form>
</html> </html>

@ -21,3 +21,9 @@ textarea {
font-family: 'latoregular', 'Trebuchet MS,Arial,Helvetica,sans-serif'; font-family: 'latoregular', 'Trebuchet MS,Arial,Helvetica,sans-serif';
font-size: 1em font-size: 1em
} }
#footer {
position: absolute;
bottom: 90px;
width: 100%;
}

@ -25,57 +25,87 @@
} }
</style> </style>
<h:messages /> <h:messages />
<h:form id="form1"> <p:tabView id="tabGroupClient" orientation="left"
<p:dataTable id="tblRecipes" style="width: 600px" dynamic="true"
value="#{shoppingListBean.recipeList}" var="item" >
> <p:tab id="overviewTab" title="Shopping List">
<p:column headerText="Recipe"> <h:form id="form1">
<h:outputText value="#{item.title}" /> <p:dataTable id="tblRecipes"
</p:column> style="width: 600px"
</p:dataTable> value="#{shoppingListBean.recipeList}"
<!-- ====== Ingredients ============================ --> var="item"
<p:column id="ingredientsc" >
style="width: 25%; vertical-align: top;" <f:facet name="header">
> <h:outputText value="Recipes" />
<p:dataTable id="tblShopIngredients" </f:facet>
style="width: 600px; margin-top: 10px" <p:column>
value="#{shoppingListBean.ingredientList}" <h:outputText value="#{item.title}" />
sortBy="#{item.shopCat}" var="item"
>
<f:facet name="header">
<h:outputText styleClass="subtitle"
value="Ingredients"
/>
</f:facet>
<p:headerRow>
<p:column colspan="4">
<h:outputText value="#{item.shopCat}" />
</p:column> </p:column>
</p:headerRow> </p:dataTable>
<p:column label="ingKey"> <!-- ====== Ingredients ============================ -->
<h:outputText value="#{item.ingkey}" /> <p:column id="ingredientsc"
</p:column> style="width: 25%; vertical-align: top;"
<p:column label="Amt"
style="width: 3em; text-align: right"
> >
<h:outputText <p:dataTable id="tblShopIngredients"
value="#{item.displayAmount}" style="width: 600px; margin-top: 10px"
/> value="#{shoppingListBean.ingredientList}"
</p:column> sortBy="#{item.shopCat}" var="item"
<p:column label="Units" style="width: 5em"> >
<h:outputText value="#{item.unit}" /> <f:facet name="header">
</p:column> <h:outputText
<p:column label="Item" style="width: 20em"> styleClass="subtitle"
<h:outputText value="#{item.item}" /> value="Ingredients"
/>
</f:facet>
<p:headerRow>
<p:column colspan="4">
<h:outputText
value="#{item.shopCat}"
/>
</p:column>
</p:headerRow>
<p:column label="ingKey">
<h:outputText
value="#{item.ingkey}"
/>
</p:column>
<p:column label="Amt"
style="width: 3em; text-align: right"
>
<h:outputText
value="#{item.displayAmount}"
/>
</p:column>
<p:column label="Units"
style="width: 5em"
>
<h:outputText
value="#{item.unit}"
/>
</p:column>
<p:column label="Item"
style="width: 20em"
>
<h:outputText
value="#{item.item}"
/>
</p:column>
</p:dataTable>
</p:column> </p:column>
</p:dataTable> </h:form>
</p:column> </p:tab>
<!-- -->
<p:tab id="ingshopcatEditTab" title="Edit">
<ui:include
src="/WEB-INF/layout/misctabs/ingshopkey.xhtml"
/>
</p:tab>
</p:tabView>
<h:form id="frmHome">
<p:commandButton id="doHome" value="Home" <p:commandButton id="doHome" value="Home"
icon="ui-icon-home" ajax="false" immediate="true" icon="ui-icon-home" ajax="false" immediate="true"
action="main.jsf" action="main.jsf"
/> />
</h:form> </h:form>
<!-- -->
<ui:include src="/WEB-INF/layout/misctabs/ingshopkey.xhtml"/>
</ui:define> </ui:define>
</ui:composition> </ui:composition>
Loading…
Cancel
Save