diff --git a/js/helpers/frontend.js b/js/helpers/frontend.js
index aea7c43b..f478646c 100644
--- a/js/helpers/frontend.js
+++ b/js/helpers/frontend.js
@@ -230,6 +230,32 @@ class GrocyFrontendHelpers
});
}
+ MakeYesNoBox(message, selector, callback)
+ {
+ var self = this;
+
+ $(document).on('click', selector, function(e)
+ {
+ message = message instanceof Function ? message(e) : message;
+ bootbox.confirm({
+ message: message,
+ closeButton: false,
+ buttons: {
+ confirm: {
+ label: self.Grocy.translate('Yes'),
+ className: 'btn-success'
+ },
+ cancel: {
+ label: self.Grocy.translate('No'),
+ className: 'btn-danger'
+ }
+ },
+ callback: (result) => callback(result, e)
+ });
+ });
+
+ }
+
MakeDeleteConfirmBox(message, selector, attrName, attrId, apiEndpoint, redirectUrl)
{
if (!apiEndpoint.endsWith('/'))
@@ -245,17 +271,9 @@ class GrocyFrontendHelpers
$(document).on('click', selector, function(e)
{
var target = $(e.currentTarget);
- var objectName = target.attr(attrName);
- var objectId = target.attr(attrId);
-
- if (message instanceof Function)
- {
- message = message(objectId, objectName);
- }
- else
- {
- message = self.Grocy.translate(message, objectName)
- }
+ var objectName = attrName instanceof Function ? attrName(target) : target.attr(attrName);
+ var objectId = attrId instanceof Function ? attrId(target) : target.attr(attrId);
+ message = message instanceof Function ? message(objectId, objectName) : self.Grocy.translate(message, objectName);
bootbox.confirm({
message: message,
diff --git a/js/viewjs/batteries.js b/js/viewjs/batteries.js
index c28f7970..dfef8a34 100644
--- a/js/viewjs/batteries.js
+++ b/js/viewjs/batteries.js
@@ -7,62 +7,21 @@
].concat($.fn.dataTable.defaults.columnDefs)
});
$('#batteries-table tbody').removeClass("d-none");
-batteriesTable.columns.adjust().draw();
-
-$("#search").on("keyup", Grocy.FrontendHelpers.Delay(function()
-{
- var value = $(this).val();
- if (value === "all")
- {
- value = "";
- }
-
- batteriesTable.search(value).draw();
-}, 200));
-
-$("#clear-filter-button").on("click", function()
+Grocy.FrontendHelpers.InitDataTable(batteriesTable, null, function()
{
$("#search").val("");
batteriesTable.search("").draw();
$("#show-disabled").prop('checked', false);
});
-$(document).on('click', '.battery-delete-button', function(e)
-{
- var objectName = $(e.currentTarget).attr('data-battery-name');
- var objectId = $(e.currentTarget).attr('data-battery-id');
-
- bootbox.confirm({
- message: __t('Are you sure to delete battery "%s"?', objectName),
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- closeButton: false,
- callback: function(result)
- {
- if (result === true)
- {
- Grocy.Api.Delete('objects/batteries/' + objectId, {},
- function(result)
- {
- window.location.href = U('/batteries');
- },
- function(xhr)
- {
- console.error(xhr);
- }
- );
- }
- }
- });
-});
+Grocy.FrontendHelpers.MakeDeleteConfirmBox(
+ 'Are you sure to delete battery "%s"?',
+ '.battery-delete-button',
+ 'data-battery-name',
+ 'data-battery-id',
+ 'objects/batteries/',
+ '/batteries'
+);
$("#show-disabled").change(function()
{
diff --git a/js/viewjs/batteriesjournal.js b/js/viewjs/batteriesjournal.js
index 10913954..6d5d3e70 100644
--- a/js/viewjs/batteriesjournal.js
+++ b/js/viewjs/batteriesjournal.js
@@ -7,38 +7,8 @@
].concat($.fn.dataTable.defaults.columnDefs)
});
$('#batteries-journal-table tbody').removeClass("d-none");
-batteriesJournalTable.columns.adjust().draw();
-
-$("#battery-filter").on("change", function()
-{
- var value = $(this).val();
- var text = $("#battery-filter option:selected").text();
- if (value === "all")
- {
- text = "";
- }
-
- batteriesJournalTable.column(1).search(text).draw();
-});
-
-$("#search").on("keyup", Grocy.FrontendHelpers.Delay(function()
-{
- var value = $(this).val();
- if (value === "all")
- {
- value = "";
- }
-
- batteriesJournalTable.search(value).draw();
-}, 200));
-
-$("#clear-filter-button").on("click", function()
-{
- $("#search").val("");
- $("#battery-filter").val("all");
- batteriesJournalTable.column(1).search("").draw();
- batteriesJournalTable.search("").draw();
-});
+Grocy.FrontendHelpers.InitDataTable(batteriesJournalTable);
+Grocy.FrontendHelpers.MakeFilterForColumn("#battery-filter", 1, batteriesJournalTable);
if (typeof GetUriParam("battery") !== "undefined")
{
diff --git a/js/viewjs/chores.js b/js/viewjs/chores.js
index fd0d8f2b..8792f9f0 100644
--- a/js/viewjs/chores.js
+++ b/js/viewjs/chores.js
@@ -13,42 +13,14 @@ Grocy.FrontendHelpers.InitDataTable(choresTable, null, function()
$("#show-disabled").prop('checked', false);
});
-$(document).on('click', '.chore-delete-button', function(e)
-{
- var objectName = $(e.currentTarget).attr('data-chore-name');
- var objectId = $(e.currentTarget).attr('data-chore-id');
-
- bootbox.confirm({
- message: __t('Are you sure to delete chore "%s"?', objectName),
- closeButton: false,
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- callback: function(result)
- {
- if (result === true)
- {
- Grocy.Api.Delete('objects/chores/' + objectId, {},
- function(result)
- {
- window.location.href = U('/chores');
- },
- function(xhr)
- {
- console.error(xhr);
- }
- );
- }
- }
- });
-});
+Grocy.FrontendHelpers.MakeDeleteConfirmBox(
+ 'Are you sure to delete chore "%s"?',
+ '.core-delete-button',
+ 'data-chore-name',
+ 'data-chore-id',
+ 'objects/chores/',
+ '/chroes'
+);
$("#show-disabled").change(function()
{
diff --git a/js/viewjs/quantityunitform.js b/js/viewjs/quantityunitform.js
index 7aee3426..583020eb 100644
--- a/js/viewjs/quantityunitform.js
+++ b/js/viewjs/quantityunitform.js
@@ -148,41 +148,14 @@ $("#name").trigger("keyup");
$('#name').focus();
Grocy.FrontendHelpers.ValidateForm('quantityunit-form');
-$(document).on('click', '.qu-conversion-delete-button', function(e)
-{
- var objectId = $(e.currentTarget).attr('data-qu-conversion-id');
-
- bootbox.confirm({
- message: __t('Are you sure to remove this conversion?'),
- closeButton: false,
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- callback: function(result)
- {
- if (result === true)
- {
- Grocy.Api.Delete('objects/quantity_unit_conversions/' + objectId, {},
- function(result)
- {
- window.location.reload();
- },
- function(xhr)
- {
- console.error(xhr);
- }
- );
- }
- }
- });
-});
+Grocy.FrontendHelpers.MakeDeleteConfirmBox(
+ 'Are you sure to remove this conversion?',
+ '.qu-conversion-delete-button',
+ 'data-qu-conversion-id',
+ 'data-qu-conversion-id',
+ 'objects/quantity_unit_conversions/',
+ () => window.location.reload(),
+);
$("#test-quantityunit-plural-forms-button").on("click", function(e)
{
diff --git a/js/viewjs/recipeform.js b/js/viewjs/recipeform.js
index bb2b40da..b38674f9 100644
--- a/js/viewjs/recipeform.js
+++ b/js/viewjs/recipeform.js
@@ -126,79 +126,23 @@ $('#recipe-form input').keydown(function(event)
}
});
-$(document).on('click', '.recipe-pos-delete-button', function(e)
-{
- var objectName = $(e.currentTarget).attr('data-recipe-pos-name');
- var objectId = $(e.currentTarget).attr('data-recipe-pos-id');
+Grocy.FrontendHelpers.MakeDeleteConfirmBox(
+ 'Are you sure to delete recipe ingredient "%s"?',
+ '.recipe-pos-delete-button',
+ 'data-recipe-pos-name',
+ 'data-recipe-pos-id',
+ 'objects/recipes_pos/',
+ () => window.postMessage(WindowMessageBag("IngredientsChanged"), Grocy.BaseUrl)
+);
- bootbox.confirm({
- message: __t('Are you sure to delete recipe ingredient "%s"?', objectName),
- closeButton: false,
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- callback: function(result)
- {
- if (result === true)
- {
- Grocy.Api.Delete('objects/recipes_pos/' + objectId, {},
- function(result)
- {
- window.postMessage(WindowMessageBag("IngredientsChanged"), Grocy.BaseUrl);
- },
- function(xhr)
- {
- console.error(xhr);
- }
- );
- }
- }
- });
-});
-
-$(document).on('click', '.recipe-include-delete-button', function(e)
-{
- var objectName = $(e.currentTarget).attr('data-recipe-include-name');
- var objectId = $(e.currentTarget).attr('data-recipe-include-id');
-
- bootbox.confirm({
- message: __t('Are you sure to remove the included recipe "%s"?', objectName),
- closeButton: false,
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- callback: function(result)
- {
- if (result === true)
- {
- Grocy.Api.Delete('objects/recipes_nestings/' + objectId, {},
- function(result)
- {
- window.postMessage(WindowMessageBag("IngredientsChanged"), Grocy.BaseUrl);
- },
- function(xhr)
- {
- console.error(xhr);
- }
- );
- }
- }
- });
-});
+Grocy.FrontendHelpers.MakeDeleteConfirmBox(
+ 'Are you sure to remove the included recipe "%s"?',
+ '.recipe-include-delete-button',
+ 'data-recipe-include-name',
+ 'data-recipe-include-id',
+ 'objects/recipes_nesting/',
+ () => window.postMessage(WindowMessageBag("IngredientsChanged"), Grocy.BaseUrl)
+);
$(document).on('click', '.recipe-pos-show-note-button', function(e)
{
diff --git a/js/viewjs/recipes.js b/js/viewjs/recipes.js
index 7efbaf4e..5d7a8a22 100644
--- a/js/viewjs/recipes.js
+++ b/js/viewjs/recipes.js
@@ -108,93 +108,77 @@ Grocy.FrontendHelpers.MakeDeleteConfirmBox(
'/recipes'
);
-$(document).on('click', '.recipe-shopping-list', function(e)
-{
- var objectName = $(e.currentTarget).attr('data-recipe-name');
- var objectId = $(e.currentTarget).attr('data-recipe-id');
-
- bootbox.confirm({
- message: __t('Are you sure to put all missing ingredients for recipe "%s" on the shopping list?', objectName) + "
" + __t("Uncheck ingredients to not put them on the shopping list") + ":" + $("#missing-recipe-pos-list")[0].outerHTML.replace("d-none", ""),
- closeButton: false,
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- callback: function(result)
+Grocy.FrontendHelpers.MakeYesNoBox(
+ (e) =>
+ {
+ var objectName = $(e.currentTarget).attr('data-recipe-name');
+ return __t('Are you sure to put all missing ingredients for recipe "%s" on the shopping list?', objectName) +
+ "
" +
+ __t("Uncheck ingredients to not put them on the shopping list") +
+ ":" +
+ $("#missing-recipe-pos-list")[0].outerHTML.replace("d-none", "");
+ },
+ '.recipe-shopping-list',
+ (result, e) =>
+ {
+ var objectId = $(e.currentTarget).attr('data-recipe-id');
+ if (result === true)
{
- if (result === true)
- {
- Grocy.FrontendHelpers.BeginUiBusy();
+ Grocy.FrontendHelpers.BeginUiBusy();
- var excludedProductIds = new Array();
- $(".missing-recipe-pos-product-checkbox:checkbox:not(:checked)").each(function()
+ var excludedProductIds = new Array();
+ $(".missing-recipe-pos-product-checkbox:checkbox:not(:checked)").each(function()
+ {
+ excludedProductIds.push($(this).data("product-id"));
+ });
+
+ Grocy.Api.Post('recipes/' + objectId + '/add-not-fulfilled-products-to-shoppinglist', { "excludedProductIds": excludedProductIds },
+ function(result)
{
- excludedProductIds.push($(this).data("product-id"));
- });
-
- Grocy.Api.Post('recipes/' + objectId + '/add-not-fulfilled-products-to-shoppinglist', { "excludedProductIds": excludedProductIds },
- function(result)
- {
- window.location.href = U('/recipes');
- },
- function(xhr)
- {
- Grocy.FrontendHelpers.EndUiBusy();
- console.error(xhr);
- }
- );
- }
+ window.location.href = U('/recipes');
+ },
+ function(xhr)
+ {
+ Grocy.FrontendHelpers.EndUiBusy();
+ console.error(xhr);
+ }
+ );
}
- });
-});
+ }
+);
-$(".recipe-consume").on('click', function(e)
-{
- var objectName = $(e.currentTarget).attr('data-recipe-name');
- var objectId = $(e.currentTarget).attr('data-recipe-id');
-
- bootbox.confirm({
- message: __t('Are you sure to consume all ingredients needed by recipe "%s" (ingredients marked with "only check if any amount is in stock" will be ignored)?', objectName),
- closeButton: false,
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- callback: function(result)
+Grocy.FrontendHelpers.MakeYesNoBox(
+ (e) =>
+ {
+ var objectName = $(e.currentTarget).attr('data-recipe-name');
+ return __t('Are you sure to consume all ingredients needed by recipe "%s" (ingredients marked with "only check if any amount is in stock" will be ignored)?', objectName);
+ },
+ '.recipe-consume',
+ (result, e) =>
+ {
+ var target = $(e.currentTarget);
+ var objectName = target.attr('data-recipe-name');
+ var objectId = target.attr('data-recipe-id');
+ if (result === true)
{
- if (result === true)
- {
- Grocy.FrontendHelpers.BeginUiBusy();
+ Grocy.FrontendHelpers.BeginUiBusy();
- Grocy.Api.Post('recipes/' + objectId + '/consume', {},
- function(result)
- {
- Grocy.FrontendHelpers.EndUiBusy();
- toastr.success(__t('Removed all ingredients of recipe "%s" from stock', objectName));
- },
- function(xhr)
- {
- Grocy.FrontendHelpers.EndUiBusy();
- toastr.warning(__t('Not all ingredients of recipe "%s" are in stock, nothing removed', objectName));
- console.error(xhr);
- }
- );
- }
+ Grocy.Api.Post('recipes/' + objectId + '/consume', {},
+ function(result)
+ {
+ Grocy.FrontendHelpers.EndUiBusy();
+ toastr.success(__t('Removed all ingredients of recipe "%s" from stock', objectName));
+ },
+ function(xhr)
+ {
+ Grocy.FrontendHelpers.EndUiBusy();
+ toastr.warning(__t('Not all ingredients of recipe "%s" are in stock, nothing removed', objectName));
+ console.error(xhr);
+ }
+ );
}
- });
-});
+ }
+);
recipesTables.on('select', function(e, dt, type, indexes)
{
diff --git a/js/viewjs/shoppinglist.js b/js/viewjs/shoppinglist.js
index 99e12e2d..b24ee4ac 100644
--- a/js/viewjs/shoppinglist.js
+++ b/js/viewjs/shoppinglist.js
@@ -48,42 +48,14 @@ $("#selected-shopping-list").on("change", function()
window.location.href = U('/shoppinglist?list=' + value);
});
-$("#delete-selected-shopping-list").on("click", function()
-{
- var objectName = $("#selected-shopping-list option:selected").text();
- var objectId = $("#selected-shopping-list").val();
-
- bootbox.confirm({
- message: __t('Are you sure to delete shopping list "%s"?', objectName),
- closeButton: false,
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- callback: function(result)
- {
- if (result === true)
- {
- Grocy.Api.Delete('objects/shopping_lists/' + objectId, {},
- function(result)
- {
- window.location.href = U('/shoppinglist');
- },
- function(xhr)
- {
- console.error(xhr);
- }
- );
- }
- }
- });
-});
+Grocy.FrontendHelpers.MakeDeleteConfirmBox(
+ 'Are you sure to delete shopping list "%s"?',
+ '#delete-selected-shopping-list',
+ () => $("#selected-shopping-list option:selected").text(),
+ () => $("#selected-shopping-list").val(),
+ 'objects/shopping_lists/',
+ '/shoppinglist'
+);
$(document).on('click', '.shoppinglist-delete-button', function(e)
{
@@ -160,47 +132,34 @@ $(document).on('click', '#add-overdue-expired-products', function(e)
);
});
-$(document).on('click', '#clear-shopping-list', function(e)
-{
- bootbox.confirm({
- message: __t('Are you sure to empty shopping list "%s"?', $("#selected-shopping-list option:selected").text()),
- closeButton: false,
- buttons: {
- confirm: {
- label: __t('Yes'),
- className: 'btn-success'
- },
- cancel: {
- label: __t('No'),
- className: 'btn-danger'
- }
- },
- callback: function(result)
+Grocy.FrontendHelpers.MakeYesNoBox(
+ () => __t('Are you sure to empty shopping list "%s"?', $("#selected-shopping-list option:selected").text()),
+ '#clear-shopping-list',
+ (result) =>
+ {
+ if (result === true)
{
- if (result === true)
- {
- Grocy.FrontendHelpers.BeginUiBusy();
+ Grocy.FrontendHelpers.BeginUiBusy();
- Grocy.Api.Post('stock/shoppinglist/clear', { "list_id": $("#selected-shopping-list").val() },
- function(result)
- {
- animateCSS("#shoppinglist-table tbody tr", "fadeOut", function()
- {
- Grocy.FrontendHelpers.EndUiBusy();
- $("#shoppinglist-table tbody tr").remove();
- OnListItemRemoved();
- });
- },
- function(xhr)
+ Grocy.Api.Post('stock/shoppinglist/clear', { "list_id": $("#selected-shopping-list").val() },
+ function(result)
+ {
+ animateCSS("#shoppinglist-table tbody tr", "fadeOut", function()
{
Grocy.FrontendHelpers.EndUiBusy();
- console.error(xhr);
- }
- );
- }
+ $("#shoppinglist-table tbody tr").remove();
+ OnListItemRemoved();
+ });
+ },
+ function(xhr)
+ {
+ Grocy.FrontendHelpers.EndUiBusy();
+ console.error(xhr);
+ }
+ );
}
- });
-});
+ }
+);
$(document).on('click', '.shopping-list-stock-add-workflow-list-item-button', function(e)
{
diff --git a/js/viewjs/stockoverview.js b/js/viewjs/stockoverview.js
index be7af93f..5fa17c02 100755
--- a/js/viewjs/stockoverview.js
+++ b/js/viewjs/stockoverview.js
@@ -55,10 +55,12 @@ $(document).on('click', '.product-consume-button', function(e)
Grocy.FrontendHelpers.BeginUiBusy();
- var productId = $(e.currentTarget).attr('data-product-id');
- var consumeAmount = $(e.currentTarget).attr('data-consume-amount');
- var originalTotalStockAmount = $(e.currentTarget).attr('data-original-total-stock-amount');
- var wasSpoiled = $(e.currentTarget).hasClass("product-consume-button-spoiled");
+ var target = $(e.currentTarget);
+
+ var productId = target.attr('data-product-id');
+ var consumeAmount = target.attr('data-consume-amount');
+ var originalTotalStockAmount = target.attr('data-original-total-stock-amount');
+ var wasSpoiled = target.hasClass("product-consume-button-spoiled");
Grocy.Api.Post('stock/products/' + productId + '/consume', { 'amount': consumeAmount, 'spoiled': wasSpoiled, 'allow_subproduct_substitution': true },
function(bookingResponse)
@@ -111,12 +113,13 @@ $(document).on('click', '.product-open-button', function(e)
Grocy.FrontendHelpers.BeginUiBusy();
- var productId = $(e.currentTarget).attr('data-product-id');
- var productName = $(e.currentTarget).attr('data-product-name');
- var productQuName = $(e.currentTarget).attr('data-product-qu-name');
- var amount = $(e.currentTarget).attr('data-open-amount');
var button = $(e.currentTarget);
+ var productId = button.attr('data-product-id');
+ var productName = button.attr('data-product-name');
+ var productQuName = button.attr('data-product-qu-name');
+ var amount = button.attr('data-open-amount');
+
Grocy.Api.Post('stock/products/' + productId + '/open', { 'amount': amount, 'allow_subproduct_substitution': true },
function(bookingResponse)
{
diff --git a/views/consume.blade.php b/views/consume.blade.php
index fa5a3000..a089bbe6 100644
--- a/views/consume.blade.php
+++ b/views/consume.blade.php
@@ -37,7 +37,7 @@
@endif>
@else
@endif
diff --git a/views/purchase.blade.php b/views/purchase.blade.php
index 9c11fc6a..6ee99e11 100644
--- a/views/purchase.blade.php
+++ b/views/purchase.blade.php
@@ -37,7 +37,7 @@
@endif>
@else
@endif
diff --git a/views/recipeposform.blade.php b/views/recipeposform.blade.php
index 55ee1d45..27bdd65f 100644
--- a/views/recipeposform.blade.php
+++ b/views/recipeposform.blade.php
@@ -29,16 +29,16 @@