You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
464 lines
24 KiB
464 lines
24 KiB
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
|
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
|
xmlns:ui="http://java.sun.com/jsf/facelets"
|
|
xmlns:p="http://primefaces.org/ui"
|
|
xmlns:c="http://xmlns.jcp.org/jstl"
|
|
>
|
|
<head></head>
|
|
<body>
|
|
<ui:composition template="/WEB-INF/layout/layout.xhtml">
|
|
<ui:define name="title">Gourmet Recipe Manager</ui:define>
|
|
<ui:define name="content">
|
|
<h:outputScript name="js/scrolltable.js" />
|
|
<style>
|
|
.deDescl {
|
|
width: 15em;
|
|
text-align: left;
|
|
}
|
|
|
|
.deDescr {
|
|
text-align: left;
|
|
}
|
|
|
|
.ingSel {
|
|
width: 3em;
|
|
text-align: center;
|
|
}
|
|
|
|
.ingAmt {
|
|
width: 4em;
|
|
text-align: right;
|
|
}
|
|
|
|
.ingItem {
|
|
width: 20em;
|
|
text-align: left;
|
|
}
|
|
|
|
.groupItem {
|
|
font-weight: bold;
|
|
background-color: green;
|
|
}
|
|
</style>
|
|
<h:messages id="messages" />
|
|
<p:panel id="editorPanel"
|
|
header="#{recipeDetailBean.recipe.title}"
|
|
>
|
|
<h:form id="form1" enctype="multipart/form-data">
|
|
<p:tabView id="tabGroupClient"
|
|
orientation="left"
|
|
activeIndex="#{userSession.detailTab}"
|
|
>
|
|
<p:tab id="overviewTab"
|
|
title="Description"
|
|
>
|
|
<p:panelGrid columns="2"
|
|
columnClasses="deDescl, deDescr"
|
|
>
|
|
<f:facet name="header">Description</f:facet>
|
|
<p:outputLabel for="@next"
|
|
value="Title"
|
|
/>
|
|
<p:inputText id="rtitle"
|
|
size="45" required="true"
|
|
focus="true"
|
|
placeholder="A recipe title is required."
|
|
value="#{recipeDetailBean.recipe.title}"
|
|
>
|
|
<f:ajax execute="rtitle"
|
|
render="editorPanel"
|
|
/>
|
|
</p:inputText>
|
|
<p:outputLabel for="@next"
|
|
value="Category"
|
|
/>
|
|
<p:inputText id="rcategory"
|
|
label="Category"
|
|
value="#{recipeDetailBean.category}"
|
|
tip="One or more categories, separated by commas (ex: Entree, Soup)"
|
|
/>
|
|
<p:commandButton
|
|
value="<- Suggest"
|
|
>
|
|
<f:ajax
|
|
execute="rcategory bxCat"
|
|
listener="#{recipeDetailBean.ajaxSuggestCategory}"
|
|
render="rcategory"
|
|
/>
|
|
</p:commandButton>
|
|
<p:selectOneMenu id="bxCat"
|
|
value="#{recipeDetailBean.catToAdd}"
|
|
tip="Recipe category suggestions, based on previous selections"
|
|
>
|
|
<f:selectItems
|
|
value="#{recipeDetailBean.suggestCategory}"
|
|
/>
|
|
</p:selectOneMenu>
|
|
<p:outputLabel for="@next"
|
|
value="Cuisine"
|
|
/>
|
|
<p:autoComplete id="rcuisine"
|
|
value="#{recipeDetailBean.recipe.cuisine}"
|
|
completeMethod="#{recipeDetailBean.cuisineSuggestions}"
|
|
/>
|
|
<p:outputLabel for="@next"
|
|
value="Prep Time"
|
|
/>
|
|
<p:inputText id="rpreptime"
|
|
max="10"
|
|
value="#{recipeDetailBean.recipe.preptime}"
|
|
>
|
|
<f:converter
|
|
converterId="com.mousetech.gourmetj.utils.TimeConverter"
|
|
/>
|
|
</p:inputText>
|
|
<p:outputLabel for="@next"
|
|
value="Cooking Time"
|
|
/>
|
|
<p:inputText id="rcooktime"
|
|
max="10"
|
|
value="#{recipeDetailBean.recipe.cooktime}"
|
|
>
|
|
<f:converter
|
|
converterId="com.mousetech.gourmetj.utils.TimeConverter"
|
|
/>
|
|
</p:inputText>
|
|
<p:outputLabel for="@next"
|
|
value="Rating"
|
|
/>
|
|
<p:rating id="rrating" max="10"
|
|
value="#{recipeDetailBean.recipe.rating}"
|
|
/>
|
|
<p:outputLabel for="@next"
|
|
value="Source"
|
|
/>
|
|
<p:inputText id="rsource"
|
|
size="45"
|
|
value="#{recipeDetailBean.recipe.source}"
|
|
/>
|
|
<p:outputLabel for="@next"
|
|
value="URL"
|
|
/>
|
|
<p:inputText id="rurl" size="45"
|
|
value="#{recipeDetailBean.recipe.link}"
|
|
/>
|
|
<p:outputLabel for="@next"
|
|
value="Description"
|
|
/>
|
|
<p:inputTextarea id="description"
|
|
rows="10" cols="45"
|
|
value="#{recipeDetailBean.recipe.description}"
|
|
/>
|
|
</p:panelGrid>
|
|
<p:panel id="picPanel">
|
|
<img id="bigPix"
|
|
src="/img/picture/?dt=#{recipeDetailBean.currentTime}"
|
|
/>
|
|
</p:panel>
|
|
<p:panelGrid id="picButtonPanel"
|
|
columns="2"
|
|
>
|
|
<p:fileUpload id="ctlUpload"
|
|
label="Upload Image"
|
|
listener="#{recipeDetailBean.ajaxUploadImage}"
|
|
global="true" mode="advanced"
|
|
multiple="false"
|
|
update=":messages picPanel"
|
|
auto="true"
|
|
sizeLimit="1000000"
|
|
allowTypes="/(\.|\/)(gif|jpe?g|png|webp)$/"
|
|
/>
|
|
<p:commandButton id="ctlDelImg"
|
|
value="Delete Image"
|
|
action="#{recipeDetailBean.ajaxDeleteImage}"
|
|
update="picPanel"
|
|
immediate="true"
|
|
/>
|
|
</p:panelGrid>
|
|
</p:tab>
|
|
<p:tab id="ingredientsTab"
|
|
title="Ingredients"
|
|
>
|
|
<p:panel id="pnlIngredients">
|
|
<f:facet name="header">Ingredients</f:facet>
|
|
<h:panelGroup id="ingButtons">
|
|
<p:commandButton value="Up"
|
|
disabled="#{not recipeDetailBean.moveUpAble}"
|
|
id="ctlUp"
|
|
actionListener="#{recipeDetailBean.ajaxMoveUp}"
|
|
update="@this:@parent:@parent"
|
|
onerror="PF('opError').show()"
|
|
/>
|
|
<p:commandButton value="Down"
|
|
disabled="#{not recipeDetailBean.moveDownAble}"
|
|
id="ctlDown"
|
|
onerror="PF('opError').show()"
|
|
actionListener="#{recipeDetailBean.ajaxMoveDown}"
|
|
update="@this:@parent:@parent"
|
|
/>
|
|
<p:commandButton
|
|
value="Add Group"
|
|
onclick="PF('addGroupDlg').show()"
|
|
/>
|
|
<p:button
|
|
value="Add Recipe As Ingredient"
|
|
disabled="true"
|
|
/>
|
|
<p:button
|
|
value="Import Ingredients"
|
|
disabled="true"
|
|
/>
|
|
<p:button value="Paste" />
|
|
<p:commandButton
|
|
value="Delete"
|
|
id="ctlDelete"
|
|
disabled="#{not recipeDetailBean.selectable}"
|
|
onerror="PF('opError').show()"
|
|
actionListener="#{recipeDetailBean.ajaxDeleteItems}"
|
|
update="@this:@parent:@parent"
|
|
/>
|
|
</h:panelGroup>
|
|
<p:dataTable id="ingredientTable"
|
|
style="width: 100%; height: 430px; margin-top: 8px"
|
|
value="#{recipeDetailBean.ingredients}"
|
|
scrollable="true"
|
|
scrollHeight="380" var="item"
|
|
rowStyleClass="#{item.ingGroup ? 'editIngGroupRow' : null}"
|
|
>
|
|
<p:column label="Sel."
|
|
align="center"
|
|
style="width: 2em"
|
|
>
|
|
<p:selectBooleanCheckbox
|
|
id="selected"
|
|
value="#{item.selected}"
|
|
>
|
|
<p:ajax
|
|
listener="#{recipeDetailBean.ajaxSelectionListener}"
|
|
update=":form1:tabGroupClient:ingButtons"
|
|
onerror="PF('opError').show()"
|
|
/>
|
|
</p:selectBooleanCheckbox>
|
|
</p:column>
|
|
<p:column
|
|
style="width: 3.6em"
|
|
>
|
|
<f:facet name="header">
|
|
Amt.
|
|
</f:facet>
|
|
<p:inputText id="ingAmt"
|
|
size="3"
|
|
value="#{item.displayAmount}"
|
|
style="text-align: right"
|
|
rendered="#{not item.ingGroup}"
|
|
>
|
|
</p:inputText>
|
|
</p:column>
|
|
<p:column style="width: 7em">
|
|
<f:facet name="header">
|
|
Units
|
|
</f:facet>
|
|
<p:inputText id="ingUnit"
|
|
value="#{item.unit}"
|
|
size="10"
|
|
rendered="#{not item.ingGroup}"
|
|
>
|
|
</p:inputText>
|
|
</p:column>
|
|
<p:column style="width: 26em">
|
|
<f:facet name="header">
|
|
Item
|
|
</f:facet>
|
|
<p:inputText id="ingItem"
|
|
size="42"
|
|
value="#{item.item}"
|
|
styleClass="#{item.ingGroup ? 'groupItem' : ''}"
|
|
>
|
|
</p:inputText>
|
|
</p:column>
|
|
<p:column label="Optional"
|
|
align="center"
|
|
styleClass="ingSel"
|
|
>
|
|
<f:facet name="header">
|
|
Opt.
|
|
</f:facet>
|
|
<p:selectBooleanCheckbox
|
|
id="ingOpt"
|
|
value="#{item.optionalCB}"
|
|
rendered="#{not item.ingGroup}"
|
|
title="Optional item"
|
|
/>
|
|
</p:column>
|
|
<p:column style="width: 13em">
|
|
<f:facet name="header">
|
|
Ingredient Key
|
|
</f:facet>
|
|
<p:inputText id="ingKey"
|
|
value="#{item.ingkey}"
|
|
size="20"
|
|
rendered="#{not item.ingGroup}"
|
|
title="Ingredient key selects Shopping Category"
|
|
>
|
|
<f:ajax
|
|
event="change"
|
|
listener="#{recipeDetailBean.ajaxUpdateShopcat(item)}"
|
|
render="eShopcat shopCat"
|
|
/>
|
|
</p:inputText>
|
|
</p:column>
|
|
<p:column
|
|
style="width: 2.6em"
|
|
>
|
|
<f:facet name="header">
|
|
E
|
|
</f:facet>
|
|
<p:commandButton
|
|
id="eShopcat"
|
|
value="E"
|
|
action="#{recipeDetailBean.ajaxEditShopcat(item)}"
|
|
immediate="true"
|
|
update="editShopcatDlg"
|
|
oncomplete="PF('editShopcatDlg').show()"
|
|
title="Edit the shopping category for ing. key"
|
|
disabled="#{empty item.ingkey}"
|
|
rendered="#{not item.ingGroup}"
|
|
/>
|
|
</p:column>
|
|
<p:column>
|
|
<f:facet name="header">
|
|
Shopping Category
|
|
</f:facet>
|
|
<h:outputText
|
|
id="shopCat"
|
|
value="#{item.shopCat}"
|
|
rendered="#{not item.ingGroup}"
|
|
/>
|
|
</p:column>
|
|
</p:dataTable>
|
|
<h:panelGroup id="pnlIng">
|
|
<p:remoteCommand
|
|
name="ingButton"
|
|
action="#{recipeDetailBean.doAddIngredient}"
|
|
process="@this ctlAddIngTxt"
|
|
update="pnlIngredients"
|
|
oncomplete="scrollAndFocus('form1:tabGroupClient' , 'ingredientTable', 'ctlAddIngTxt');"
|
|
/>
|
|
<p:outputLabel for="@next"
|
|
value="Add Ingredient: "
|
|
/>
|
|
<p:inputTextarea
|
|
id="ctlAddIngTxt"
|
|
focus="true" rows="1"
|
|
cols="65"
|
|
value="#{recipeDetailBean.ingredientText}"
|
|
title="You can paste in multiple ingredients here!"
|
|
onkeydown="if (event.keyCode === 13) { ingButton(); this.focus(); return false; }"
|
|
/>
|
|
<p:commandButton
|
|
id="ctlAddIng"
|
|
value="+ Add"
|
|
onclick="ingButton(); return false;"
|
|
>
|
|
</p:commandButton>
|
|
</h:panelGroup>
|
|
</p:panel>
|
|
</p:tab>
|
|
<p:tab id="instructionsTab"
|
|
title="Instructions"
|
|
>
|
|
<p:panel header="Instructions">
|
|
<div id="insection">
|
|
<h:inputTextarea
|
|
id="ctlInstructions"
|
|
rows="30" cols="120"
|
|
escape="false"
|
|
value="#{recipeDetailBean.recipe.instructions}"
|
|
/>
|
|
</div>
|
|
</p:panel>
|
|
</p:tab>
|
|
<p:tab id="notesTab" title="Notes">
|
|
<p:panel header="Notes">
|
|
<h:inputTextarea id="ctlNotes"
|
|
rows="30" cols="120"
|
|
escape="false"
|
|
value="#{recipeDetailBean.recipe.modifications}"
|
|
/>
|
|
</p:panel>
|
|
</p:tab>
|
|
</p:tabView>
|
|
<p:commandButton id="doSave" value="Save"
|
|
icon="ui-icon-pencil" ajax="false"
|
|
disabled="{not recipeDetailBean.dirty}"
|
|
action="#{recipeDetailBean.doSave}"
|
|
/>
|
|
<p:commandButton id="doCancel" value="Cancel"
|
|
ajax="false" immediate="true"
|
|
action="recipeDetails.jsf"
|
|
/>
|
|
<p:commandButton id="doHome" value="Home"
|
|
icon="ui-icon-home" ajax="false"
|
|
immediate="true" action="main.jsf"
|
|
/>
|
|
</h:form>
|
|
</p:panel>
|
|
<!-- Note timeouts must be less than
|
|
session timeout in application properties-->
|
|
<p:growl id="growl" showDetail="true" sticky="true" />
|
|
<h:form id="frmTimeout">
|
|
<p:idleMonitor timeout="1500000">
|
|
<p:ajax id="ajaxIdle" event="idle"
|
|
listener="#{cookieBean.sessionIdleListener}"
|
|
update="growl"
|
|
/>
|
|
</p:idleMonitor>
|
|
<p:idleMonitor timeout="1900000">
|
|
<p:ajax id="ajaxIdle" event="idle"
|
|
listener="#{cookieBean.sessionTimeout}"
|
|
update="growl"
|
|
oncomplete="window.location='#{request.contextPath}/main.jsf'"
|
|
/>
|
|
</p:idleMonitor>
|
|
</h:form>
|
|
<!-- -->
|
|
<p:dialog id="addGroupDlg" widgetVar="addGroupDlg">
|
|
<h:form id="frmAddGroup">
|
|
<p:panelGrid columns="1">
|
|
<p:outputLabel for="@next"
|
|
value="Group Name"
|
|
/>
|
|
<p:inputText id="ctlNewGroupName"
|
|
value="#{recipeDetailBean.newGroupName}"
|
|
/>
|
|
<p:panelGrid columns="2"
|
|
style="width: 100%"
|
|
>
|
|
<p:commandButton id="agDlgOK"
|
|
value="OK" style="width: 6em"
|
|
action="#{recipeDetailBean.doAddGroup}"
|
|
update="form1:tabGroupClient:ingredientTable"
|
|
oncomplete="PF('addGroupDlg').hide(); scrollAndFocus('form1:tabGroupClient' , 'ingredientTable', 'ctlAddIngTxt');"
|
|
/>
|
|
<p:commandButton id="agDlgCan"
|
|
value="Cancel" style="width: 6em"
|
|
onclick="PF('addGroupDlg').hide()"
|
|
/>
|
|
</p:panelGrid>
|
|
</p:panelGrid>
|
|
</h:form>
|
|
</p:dialog>
|
|
<p:dialog id="editShopcatDlg"
|
|
widgetVar="editShopcatDlg"
|
|
>
|
|
<ui:include
|
|
src="/WEB-INF/layout/dialog/editShopcat.xhtml"
|
|
/>
|
|
</p:dialog>
|
|
</ui:define>
|
|
</ui:composition>
|
|
</body>
|
|
</html> |