diff --git a/changelog/55_UNRELEASED_2019-xx-xx.md b/changelog/55_UNRELEASED_2019-xx-xx.md index 7c759c30..28574d5f 100644 --- a/changelog/55_UNRELEASED_2019-xx-xx.md +++ b/changelog/55_UNRELEASED_2019-xx-xx.md @@ -4,6 +4,14 @@ - From there you can also edit the stock entries - A huge THANK YOU goes to @kriddles for the work on this feature +### New feature: Scan mode +- New switch-button on the purchase and consume page +- When enabled + - The amount will always be filled with `1` after changing/scanning a product + - If all fields could be automatically populated (means for purchase the product has a default best before date set), the transaction is automatically submitted + - If not, a warning is displayed and you can fill in the missing information + - Audio feedback is provided after scanning and on success/error of the transaction + ### New feature: Self produced products - To a recipe a product can be attached - This products needs a "Default best before date" diff --git a/config-dist.php b/config-dist.php index 4884ff7c..35f6d83f 100644 --- a/config-dist.php +++ b/config-dist.php @@ -91,6 +91,8 @@ DefaultUserSetting('product_presets_qu_id', -1); // Default quantity unit id for DefaultUserSetting('stock_expring_soon_days', 5); DefaultUserSetting('stock_default_purchase_amount', 0); DefaultUserSetting('stock_default_consume_amount', 1); +DefaultUserSetting('scan_mode_consume_enabled', false); +DefaultUserSetting('scan_mode_purchase_enabled', false); # Chores settings DefaultUserSetting('chores_due_soon_days', 5); diff --git a/localization/strings.pot b/localization/strings.pot index 8a3768e6..96ed6add 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -1669,3 +1669,15 @@ msgstr "" msgid "Meal plan product" msgstr "" + +msgid "Scan mode" +msgstr "" + +msgid "on" +msgstr "" + +msgid "off" +msgstr "" + +msgid "Scan mode is on but not all required fields could be populated automatically" +msgstr "" diff --git a/package.json b/package.json index eaadff35..7709a79b 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "bootbox": "^5.3.2", "bootstrap": "^4.3.1", "bootstrap-select": "^1.13.10", + "bootstrap-switch-button": "https://github.com/walidbagh/bootstrap-switch-button#Fix-module-export", "chart.js": "^2.8.0", "datatables.net": "^1.10.19", "datatables.net-bs4": "^1.10.19", diff --git a/public/js/grocy.js b/public/js/grocy.js index cb080592..08fbeab9 100644 --- a/public/js/grocy.js +++ b/public/js/grocy.js @@ -425,7 +425,7 @@ $(document).on("click", "select", function() }); // Auto saving user setting controls -$(".user-setting-control").on("change", function() +$(document).on("change", ".user-setting-control", function() { var element = $(this); var settingKey = element.attr("data-setting-key"); diff --git a/public/js/grocy_uisound.js b/public/js/grocy_uisound.js new file mode 100644 index 00000000..b7150084 --- /dev/null +++ b/public/js/grocy_uisound.js @@ -0,0 +1,26 @@ +Grocy.UISound = { }; + +Grocy.UISound.Play = function(url) +{ + new Audio(url).play(); +} + +Grocy.UISound.AskForPermission = function() +{ + Grocy.UISound.Play(U("/uisounds/silence.mp3")); +} + +Grocy.UISound.Success = function() +{ + Grocy.UISound.Play(U("/uisounds/success.mp3")); +} + +Grocy.UISound.Error = function() +{ + Grocy.UISound.Play(U("/uisounds/error.mp3")); +} + +Grocy.UISound.BarcodeScannerBeep = function() +{ + Grocy.UISound.Play(U("/uisounds/barcodescannerbeep.mp3")); +} diff --git a/public/uisounds/barcodescannerbeep.mp3 b/public/uisounds/barcodescannerbeep.mp3 new file mode 100644 index 00000000..e488a47e Binary files /dev/null and b/public/uisounds/barcodescannerbeep.mp3 differ diff --git a/public/uisounds/error.mp3 b/public/uisounds/error.mp3 new file mode 100644 index 00000000..f68bc892 Binary files /dev/null and b/public/uisounds/error.mp3 differ diff --git a/public/uisounds/silence.mp3 b/public/uisounds/silence.mp3 new file mode 100644 index 00000000..057d3ffc Binary files /dev/null and b/public/uisounds/silence.mp3 differ diff --git a/public/uisounds/success.mp3 b/public/uisounds/success.mp3 new file mode 100644 index 00000000..6c752d65 Binary files /dev/null and b/public/uisounds/success.mp3 differ diff --git a/public/viewjs/consume.js b/public/viewjs/consume.js index 9faf4cca..601b2f00 100644 --- a/public/viewjs/consume.js +++ b/public/viewjs/consume.js @@ -38,6 +38,11 @@ Grocy.Api.Post(apiUrl, jsonData, function(result) { + if (BoolVal(Grocy.UserSettings.scan_mode_consume_enabled)) + { + Grocy.UISound.Success(); + } + bookingResponse = result; var addBarcode = GetUriParam('addbarcodetoselection'); @@ -246,6 +251,11 @@ $("#location_id").on('change', function(e) Grocy.Components.ProductPicker.GetPicker().on('change', function(e) { + if (BoolVal(Grocy.UserSettings.scan_mode_consume_enabled)) + { + Grocy.UISound.BarcodeScannerBeep(); + } + $("#specific_stock_entry").find("option").remove().end().append(""); if ($("#use_specific_stock_entry").is(":checked")) { @@ -265,13 +275,14 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e) $('#amount_qu_unit').text(productDetails.quantity_unit_stock.name); $("#location_id").find("option").remove().end().append(""); - Grocy.Api.Get("stock/products/" + productId + '/locations', + Grocy.Api.Get("stock/products/" + productId + '/locations', function(stockLocations) { var setDefault = 0; stockLocations.forEach(stockLocation => { - if (productDetails.location.id == stockLocation.location_id) { + if (productDetails.location.id == stockLocation.location_id) + { $("#location_id").append($("