mirror of
https://github.com/grocy/grocy.git
synced 2026-04-07 05:16:15 +02:00
Recipe templates
Fractions of the total ingredients required can be mentioned in recipes. This can be helpful when, for example, only half of some ingredient is needed at the start of the recipe. The proper values are automatically calculated when the number of servings is adjusted.
This commit is contained in:
parent
4b5b7bcb19
commit
48e300bba6
|
|
@ -28,6 +28,9 @@ $('.save-recipe').on('click', function(e)
|
||||||
{
|
{
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
$(".note-editable span.ingredient").removeClass(["badge", "btn", "btn-secondary"]);
|
||||||
|
$("#description").text($("#description").siblings(".note-editor").find(".note-editable").html());
|
||||||
|
|
||||||
var jsonData = $('#recipe-form').serializeJSON();
|
var jsonData = $('#recipe-form').serializeJSON();
|
||||||
Grocy.FrontendHelpers.BeginUiBusy("recipe-form");
|
Grocy.FrontendHelpers.BeginUiBusy("recipe-form");
|
||||||
|
|
||||||
|
|
@ -230,6 +233,62 @@ $(document).on('click', '.recipe-pos-edit-button', function(e)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.recipe-pos-insert-button', function(e)
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var recipePosId = $(e.currentTarget).attr('data-recipe-pos-id').toString();
|
||||||
|
var recipePosName = $(e.currentTarget).attr('data-recipe-pos-name').toString();
|
||||||
|
var recipePosAmount = parseFloat($(e.currentTarget).attr('data-recipe-pos-amount').toString());
|
||||||
|
var recipePosQu = $(e.currentTarget).attr('data-recipe-pos-qu').toString();
|
||||||
|
var recipePosQuPlural = $(e.currentTarget).attr('data-recipe-pos-qu-plural').toString();
|
||||||
|
var range = $.summernote.range.create();
|
||||||
|
|
||||||
|
bootbox.dialog({
|
||||||
|
message: '<div>Factor?</div><input type="number" class="form-control" value="1" min="0" max="1">',
|
||||||
|
size: 'large',
|
||||||
|
backdrop: true,
|
||||||
|
closeButton: false,
|
||||||
|
buttons: {
|
||||||
|
cancel: {
|
||||||
|
label: __t('Cancel'),
|
||||||
|
className: 'btn-secondary responsive-button',
|
||||||
|
callback: function()
|
||||||
|
{
|
||||||
|
bootbox.hideAll();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ok: {
|
||||||
|
label: __t('Insert'),
|
||||||
|
className: 'btn-success responsive-button',
|
||||||
|
callback: function(e)
|
||||||
|
{
|
||||||
|
var factor = $(e.delegateTarget).find('input').val();
|
||||||
|
var amount = parseFloat(factor) * recipePosAmount;
|
||||||
|
amount = amount.toFixed(2).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1');
|
||||||
|
var html = ' <span class="ingredient" data-ingredient-id="' + recipePosId + '" data-ingredient-factor="' + factor + '">' + [amount, __n(amount, recipePosQu, recipePosQuPlural), recipePosName].join(' ') + '</span> ';
|
||||||
|
if (range.so !== range.eo || range.sc !== range.ec)
|
||||||
|
{
|
||||||
|
range.deleteContents();
|
||||||
|
range = $.summernote.range.create();
|
||||||
|
var check = range.getWordRange(true);
|
||||||
|
if (check.toString().trim().length === 0)
|
||||||
|
check.deleteContents();
|
||||||
|
check = range.getWordRange(false);
|
||||||
|
if (check.toString().trim().length === 0)
|
||||||
|
check.deleteContents();
|
||||||
|
range = $.summernote.range.create();
|
||||||
|
}
|
||||||
|
range.pasteHTML(html);
|
||||||
|
updateIngredientTags();
|
||||||
|
bootbox.hideAll();
|
||||||
|
$("#description").summernote('focus');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on('click', '.recipe-include-edit-button', function(e)
|
$(document).on('click', '.recipe-include-edit-button', function(e)
|
||||||
{
|
{
|
||||||
var id = $(e.currentTarget).attr('data-recipe-include-id');
|
var id = $(e.currentTarget).attr('data-recipe-include-id');
|
||||||
|
|
@ -379,6 +438,19 @@ $(window).on("message", function(e)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function updateIngredientTags()
|
||||||
|
{
|
||||||
|
$("#description").siblings(".note-editable").find("span.ingredient").not(".badge").addClass(["badge", "btn", "btn-secondary"]).on("click", function(evt)
|
||||||
|
{
|
||||||
|
$.summernote.range.createFromNode(evt.target).select();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$(".wysiwyg-editor").on("summernote.init", function()
|
||||||
|
{
|
||||||
|
updateIngredientTags();
|
||||||
|
});
|
||||||
|
updateIngredientTags();
|
||||||
|
|
||||||
// Grocy.Components.RecipePicker.GetPicker().on('change', function (e)
|
// Grocy.Components.RecipePicker.GetPicker().on('change', function (e)
|
||||||
// {
|
// {
|
||||||
// var value = Grocy.Components.RecipePicker.GetValue();
|
// var value = Grocy.Components.RecipePicker.GetValue();
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,35 @@ if (typeof recipe !== "undefined")
|
||||||
// Scroll to recipe card on mobile
|
// Scroll to recipe card on mobile
|
||||||
$("#selectedRecipeCard")[0].scrollIntoView();
|
$("#selectedRecipeCard")[0].scrollIntoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$("#selectedRecipeCard .ingredient").each(function(id, element)
|
||||||
|
{
|
||||||
|
var data = $(element).closest(".tab-pane").data("ingredients");
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
$(element).text('<???>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var ingredient = FindObjectInArrayByPropertyValue(data.recipePositions, 'recipe_pos_id', element.dataset.ingredientId);
|
||||||
|
if (!ingredient)
|
||||||
|
{
|
||||||
|
$(element).text('<???>');
|
||||||
|
}
|
||||||
|
var product = FindObjectInArrayByPropertyValue(data.products, 'id', ingredient.product_id);
|
||||||
|
var amount = ingredient.recipe_amount;
|
||||||
|
if (element.dataset.ingredientFactor && parseFloat(element.dataset.ingredientFactor))
|
||||||
|
{
|
||||||
|
amount *= parseFloat(element.dataset.ingredientFactor);
|
||||||
|
}
|
||||||
|
amount = amount.toFixed(2).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1');
|
||||||
|
var qu = FindObjectInArrayByPropertyValue(data.quantityUnits, 'id', ingredient.qu_id);
|
||||||
|
if (!qu || !product)
|
||||||
|
{
|
||||||
|
$(element).text('<???>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$(element).text([amount, __n(amount, qu.name, qu.name_plural), product.name].join(' '));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetUriParam("search") !== undefined)
|
if (GetUriParam("search") !== undefined)
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,16 @@
|
||||||
@if($mode == "edit")
|
@if($mode == "edit")
|
||||||
@foreach($recipePositions as $recipePosition)
|
@foreach($recipePositions as $recipePosition)
|
||||||
<tr>
|
<tr>
|
||||||
|
@php
|
||||||
|
$product = FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id);
|
||||||
|
$productQuConversions = FindAllObjectsInArrayByPropertyValue($quantityUnitConversionsResolved, 'product_id', $product->id);
|
||||||
|
$productQuConversions = FindAllObjectsInArrayByPropertyValue($productQuConversions, 'from_qu_id', $product->qu_id_stock);
|
||||||
|
$productQuConversion = FindObjectInArrayByPropertyValue($productQuConversions, 'to_qu_id', $recipePosition->qu_id);
|
||||||
|
if ($productQuConversion)
|
||||||
|
{
|
||||||
|
$recipePosition->amount = $recipePosition->amount * $productQuConversion->factor;
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
<td class="fit-content border-right">
|
<td class="fit-content border-right">
|
||||||
<a class="btn btn-sm btn-info recipe-pos-edit-button"
|
<a class="btn btn-sm btn-info recipe-pos-edit-button"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -200,6 +210,15 @@
|
||||||
data-product-id="{{ $recipePosition->product_id }}">
|
data-product-id="{{ $recipePosition->product_id }}">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn btn-sm btn-info recipe-pos-insert-button"
|
||||||
|
href="#"
|
||||||
|
data-recipe-pos-id="{{ $recipePosition->id }}"
|
||||||
|
data-recipe-pos-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}"
|
||||||
|
data-recipe-pos-amount="{{ $recipePosition->amount }}"
|
||||||
|
data-recipe-pos-qu="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name }}"
|
||||||
|
data-recipe-pos-qu-plural="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name_plural }}">
|
||||||
|
<i class="fas fa-map-marker"></i>
|
||||||
|
</a>
|
||||||
<a class="btn btn-sm btn-danger recipe-pos-delete-button"
|
<a class="btn btn-sm btn-danger recipe-pos-delete-button"
|
||||||
href="#"
|
href="#"
|
||||||
data-recipe-pos-id="{{ $recipePosition->id }}"
|
data-recipe-pos-id="{{ $recipePosition->id }}"
|
||||||
|
|
@ -211,16 +230,6 @@
|
||||||
{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}
|
{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@php
|
|
||||||
$product = FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id);
|
|
||||||
$productQuConversions = FindAllObjectsInArrayByPropertyValue($quantityUnitConversionsResolved, 'product_id', $product->id);
|
|
||||||
$productQuConversions = FindAllObjectsInArrayByPropertyValue($productQuConversions, 'from_qu_id', $product->qu_id_stock);
|
|
||||||
$productQuConversion = FindObjectInArrayByPropertyValue($productQuConversions, 'to_qu_id', $recipePosition->qu_id);
|
|
||||||
if ($productQuConversion)
|
|
||||||
{
|
|
||||||
$recipePosition->amount = $recipePosition->amount * $productQuConversion->factor;
|
|
||||||
}
|
|
||||||
@endphp
|
|
||||||
@if(!empty($recipePosition->variable_amount))
|
@if(!empty($recipePosition->variable_amount))
|
||||||
{{ $recipePosition->variable_amount }}
|
{{ $recipePosition->variable_amount }}
|
||||||
@else
|
@else
|
||||||
|
|
|
||||||
|
|
@ -394,6 +394,7 @@
|
||||||
@endif
|
@endif
|
||||||
<div class="tab-pane @if(count($recipePositionsFiltered) == 0) active @endif"
|
<div class="tab-pane @if(count($recipePositionsFiltered) == 0) active @endif"
|
||||||
id="prep-{{ $index }}"
|
id="prep-{{ $index }}"
|
||||||
|
data-ingredients="{{ json_encode(array('recipePositions' => $recipePositionsFiltered, 'products' => $products, 'quantityUnits' => $quantityUnits)) }}"
|
||||||
role="tabpanel">
|
role="tabpanel">
|
||||||
<div class="mb-2 d-none d-print-block">
|
<div class="mb-2 d-none d-print-block">
|
||||||
<h3 class="mb-0">{{ $__t('Preparation') }}</h3>
|
<h3 class="mb-0">{{ $__t('Preparation') }}</h3>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user