diff --git a/changelog/58_2.7.0_2020-04-16.md b/changelog/58_2.7.0_2020-04-16.md index 5e920dfd..abf1b045 100644 --- a/changelog/58_2.7.0_2020-04-16.md +++ b/changelog/58_2.7.0_2020-04-16.md @@ -56,7 +56,7 @@ - Various display/CSS improvements (thanks @Mik-) - Prerequisites (PHP extensions, critical files/folders) will now be checked and properly reported if there are problems (thanks @Forceu) - Improved the the overview pages on mobile devices (main column was hidden) (thanks @Mik-) -- The general search field now searches accent insensitive (and table sorting is also accent insensitive) +- The general table search field now searches accent insensitive (and table sorting is also accent insensitive) - Fixed that all number inputs are always prefilled in the browser locale number format - Optimized the handling of settings provided by `data/settingoverrides` files (thanks @dacto) - Optimized the update script (`update.sh`) to create the backup tar archive before writing to it (was a problem on Btrfs file systems) (thanks @shane-kerr) diff --git a/changelog/82_UNRELEASED_xxxx-xx-xx.md b/changelog/82_UNRELEASED_xxxx-xx-xx.md index 74abf29f..ff3bf3be 100644 --- a/changelog/82_UNRELEASED_xxxx-xx-xx.md +++ b/changelog/82_UNRELEASED_xxxx-xx-xx.md @@ -13,6 +13,7 @@ - Fixed that changing the location on the purchase page re-initialized the due date based on product defaults (if any) - Fixed that when undoing a product consume or transfer transaction, the store of the corresponding stock entry wasn't restored - This will only apply to new consume / transfer transactions, not when undoing transactions made before using this release +- The product picker now searches product names accent insensitive ### Shopping list @@ -52,6 +53,7 @@ ### General +- Fixed accent insensitive searching using the general table search field was broken - Fixed that it wasn't possible to log in using passwords containing special escape sequences (e.g. `<<`) ### API diff --git a/package.json b/package.json index a40ae83c..ac7966f4 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "datatables.net-bs4": "^1.10.22", "datatables.net-colreorder": "^1.5.2", "datatables.net-colreorder-bs4": "^1.5.2", - "datatables.net-plugins": "^1.10.20", "datatables.net-rowgroup": "<1.6.0", "datatables.net-rowgroup-bs4": "^1.1.2", "datatables.net-select": "^1.3.1", diff --git a/public/js/extensions.js b/public/js/extensions.js index a0e81fb9..14c7f2cf 100644 --- a/public/js/extensions.js +++ b/public/js/extensions.js @@ -1,4 +1,4 @@ -EmptyElementWhenMatches = function(selector, text) +EmptyElementWhenMatches = function (selector, text) { if ($(selector).text() === text) { @@ -6,22 +6,34 @@ EmptyElementWhenMatches = function(selector, text) } }; -String.prototype.contains = function(search) +String.prototype.contains = function (search) { return this.toLowerCase().indexOf(search.toLowerCase()) !== -1; }; -String.prototype.replaceAll = function(search, replacement) +String.prototype.replaceAll = function (search, replacement) { return this.replace(new RegExp(search, "g"), replacement); }; -String.prototype.escapeHTML = function() +String.prototype.escapeHTML = function () { return this.replace(/[&<>"'`=\/]/g, s => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=' })[s]);; }; -GetUriParam = function(key) +// E.g. "Crème fraîche" becomes "Creme fraiche" +String.prototype.accentNeutralise = function () +{ + return this.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); +}; + +// E.g. "
test
" becomes "test" +String.prototype.stripHtml = function () +{ + return this.replace(/<.*?>/g, ''); +}; + +GetUriParam = function (key) { var currentUri = window.location.search.substring(1); var vars = currentUri.split('&'); @@ -37,21 +49,21 @@ GetUriParam = function(key) } }; -UpdateUriParam = function(key, value) +UpdateUriParam = function (key, value) { var queryParameters = new URLSearchParams(location.search); queryParameters.set(key, value); window.history.replaceState({}, "", decodeURIComponent(`${location.pathname}?${queryParameters}`)); }; -RemoveUriParam = function(key) +RemoveUriParam = function (key) { var queryParameters = new URLSearchParams(location.search); queryParameters.delete(key); window.history.replaceState({}, "", decodeURIComponent(`${location.pathname}?${queryParameters}`)); }; -BoolVal = function(test) +BoolVal = function (test) { if (!test) { @@ -69,25 +81,25 @@ BoolVal = function(test) } } -GetFileNameFromPath = function(path) +GetFileNameFromPath = function (path) { return path.split("/").pop().split("\\").pop(); } -GetFileExtension = function(pathOrFileName) +GetFileExtension = function (pathOrFileName) { return pathOrFileName.split(".").pop(); } $.extend($.expr[":"], { - "contains_case_insensitive": function(elem, i, match, array) + "contains_case_insensitive": function (elem, i, match, array) { return (elem.textContent || elem.innerText || "").toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0; } }); -FindObjectInArrayByPropertyValue = function(array, propertyName, propertyValue) +FindObjectInArrayByPropertyValue = function (array, propertyName, propertyValue) { for (var i = 0; i < array.length; i++) { @@ -100,7 +112,7 @@ FindObjectInArrayByPropertyValue = function(array, propertyName, propertyValue) return null; } -FindAllObjectsInArrayByPropertyValue = function(array, propertyName, propertyValue) +FindAllObjectsInArrayByPropertyValue = function (array, propertyName, propertyValue) { var returnArray = []; @@ -115,7 +127,7 @@ FindAllObjectsInArrayByPropertyValue = function(array, propertyName, propertyVal return returnArray; } -$.fn.hasAttr = function(name) +$.fn.hasAttr = function (name) { return this.attr(name) !== undefined; }; @@ -135,20 +147,20 @@ function IsJsonString(text) function Delay(callable, delayMilliseconds) { var timer = 0; - return function() + return function () { var context = this; var args = arguments; clearTimeout(timer); - timer = setTimeout(function() + timer = setTimeout(function () { callable.apply(context, args); }, delayMilliseconds || 0); }; } -$.fn.isVisibleInViewport = function(extraHeightPadding = 0) +$.fn.isVisibleInViewport = function (extraHeightPadding = 0) { var elementTop = $(this).offset().top; var viewportTop = $(window).scrollTop() - extraHeightPadding; diff --git a/public/js/grocy.js b/public/js/grocy.js index 3865df38..f79993ca 100644 --- a/public/js/grocy.js +++ b/public/js/grocy.js @@ -850,6 +850,16 @@ $('[data-toggle="tooltip"]').tooltip(); // serializeJSON defaults $.serializeJSON.defaultOptions.checkboxUncheckedValue = "0"; +// bootstrap-combobox defaults +BootstrapComboboxDefaults = { + appendId: "_text_input", + bsVersion: "4", + "matcher": function (item) + { + return ~item.accentNeutralise().toLowerCase().indexOf(this.query.accentNeutralise().toLowerCase()); + } +}; + $(Grocy.UserPermissions).each(function (index, item) { if (item.has_permission == 0) diff --git a/public/js/grocy_datatables.js b/public/js/grocy_datatables.js index 7891eeb0..8e580611 100644 --- a/public/js/grocy_datatables.js +++ b/public/js/grocy_datatables.js @@ -9,7 +9,7 @@ $.extend(true, $.fn.dataTable.defaults, { 'colReorder': true, 'stateSave': true, 'stateDuration': 0, - 'stateSaveParams': function(settings, data) + 'stateSaveParams': function (settings, data) { data.search.search = ""; @@ -18,7 +18,7 @@ $.extend(true, $.fn.dataTable.defaults, { column.search.search = ""; }); }, - 'stateSaveCallback': function(settings, data) + 'stateSaveCallback': function (settings, data) { var settingKey = 'datatables_state_' + settings.sTableId; @@ -49,7 +49,7 @@ $.extend(true, $.fn.dataTable.defaults, { Grocy.FrontendHelpers.SaveUserSetting(settingKey, JSON.stringify(data)); } }, - 'stateLoadCallback': function(settings, data) + 'stateLoadCallback': function (settings, data) { var settingKey = 'datatables_state_' + settings.sTableId; @@ -62,7 +62,7 @@ $.extend(true, $.fn.dataTable.defaults, { return JSON.parse(Grocy.UserSettings[settingKey]); } }, - 'preDrawCallback': function(settings) + 'preDrawCallback': function (settings) { // Currently it is not possible to save the state of rowGroup via saveState events var api = new $.fn.dataTable.Api(settings); @@ -99,16 +99,16 @@ $.extend(true, $.fn.dataTable.defaults, { } }, 'columnDefs': [ - { type: 'chinese-string', targets: '_all' } + { type: 'string', targets: '_all' } ], 'rowGroup': { enable: false, - startRender: function(rows, group) + startRender: function (rows, group) { var collapsed = !!collapsedGroups[group]; var toggleClass = collapsed ? "fa-caret-right" : "fa-caret-down"; - rows.nodes().each(function(row) + rows.nodes().each(function (row) { row.style.display = collapsed ? "none" : ""; }); @@ -120,13 +120,13 @@ $.extend(true, $.fn.dataTable.defaults, { } } }); -$(document).on("click", "tr.dtrg-group", function() +$(document).on("click", "tr.dtrg-group", function () { var name = $(this).data('name'); collapsedGroups[name] = !collapsedGroups[name]; $("table").DataTable().draw(); }); -$.fn.dataTable.ext.type.order["custom-sort-pre"] = function(data) +$.fn.dataTable.ext.type.order["custom-sort-pre"] = function (data) { // Workaround for https://github.com/DataTables/ColReorder/issues/85 // @@ -139,7 +139,24 @@ $.fn.dataTable.ext.type.order["custom-sort-pre"] = function(data) return (Number.parseFloat($(data).get(0).innerText)); }; -$('.table').on('column-sizing.dt', function(e, settings) +$.fn.dataTable.ext.type.search.string = function (s) +{ + return s.accentNeutralise(); +}; +$.fn.dataTable.ext.type.search.html = function (s) +{ + return s.stripHtml().accentNeutralise(); +}; +$.fn.dataTable.ext.type.order["string-pre"] = function (s) +{ + return s.accentNeutralise(); +}; +$.fn.dataTable.ext.type.order["html-pre"] = function (s) +{ + return s.stripHtml().accentNeutralise(); +}; + +$('.table').on('column-sizing.dt', function (e, settings) { var dtScrollWidth = $('.dataTables_scroll').width(); var tableWidth = $('.table').width() + 100; // Some extra padding, otherwise the scrollbar maybe only appears after a column is already completely out of the viewport @@ -155,14 +172,14 @@ $('.table').on('column-sizing.dt', function(e, settings) $('.dataTables_scrollBody').addClass("force-overflow-visible"); } }); -$(document).on("show.bs.dropdown", "td .dropdown", function(e) +$(document).on("show.bs.dropdown", "td .dropdown", function (e) { if ($('.dataTables_scrollBody').hasClass("no-force-overflow-visible")) { $('.dataTables_scrollBody').addClass("force-overflow-visible"); } }); -$(document).on("hide.bs.dropdown", "td .dropdown", function(e) +$(document).on("hide.bs.dropdown", "td .dropdown", function (e) { if ($('.dataTables_scrollBody').hasClass("no-force-overflow-visible")) { @@ -170,7 +187,7 @@ $(document).on("hide.bs.dropdown", "td .dropdown", function(e) } }); -$(".change-table-columns-visibility-button").on("click", function(e) +$(".change-table-columns-visibility-button").on("click", function (e) { e.preventDefault(); @@ -200,7 +217,7 @@ $(".change-table-columns-visibility-button").on("click", function(e) '; } - dataTable.columns().every(function() + dataTable.columns().every(function () { var index = this.index(); var indexForGrouping = index; @@ -292,7 +309,7 @@ $(".change-table-columns-visibility-button").on("click", function(e) reset: { label: __t('Reset'), className: 'btn-outline-danger float-left responsive-button', - callback: function() + callback: function () { bootbox.confirm({ message: __t("Are you sure you want to reset the table options?"), @@ -307,7 +324,7 @@ $(".change-table-columns-visibility-button").on("click", function(e) className: 'btn-success' } }, - callback: function(result) + callback: function (result) { if (result) { @@ -328,7 +345,7 @@ $(".change-table-columns-visibility-button").on("click", function(e) ok: { label: __t('OK'), className: 'btn-primary responsive-button', - callback: function() + callback: function () { $(".modal").last().modal("hide"); } @@ -337,7 +354,7 @@ $(".change-table-columns-visibility-button").on("click", function(e) }); }); -$(document).on("click", ".change-table-columns-visibility-toggle", function() +$(document).on("click", ".change-table-columns-visibility-toggle", function () { var dataTableSelector = $(this).attr("data-table-selector"); var columnIndex = $(this).attr("data-column-index"); @@ -347,7 +364,7 @@ $(document).on("click", ".change-table-columns-visibility-toggle", function() }); -$(document).on("click", ".change-table-columns-rowgroup-toggle", function() +$(document).on("click", ".change-table-columns-rowgroup-toggle", function () { var dataTableSelector = $(this).attr("data-table-selector"); var columnIndex = $(this).attr("data-column-index"); diff --git a/public/viewjs/batterytracking.js b/public/viewjs/batterytracking.js index 435f52bb..6ea8cbf8 100644 --- a/public/viewjs/batterytracking.js +++ b/public/viewjs/batterytracking.js @@ -1,4 +1,4 @@ -$('#save-batterytracking-button').on('click', function(e) +$('#save-batterytracking-button').on('click', function (e) { e.preventDefault(); @@ -16,13 +16,13 @@ Grocy.FrontendHelpers.BeginUiBusy("batterytracking-form"); Grocy.Api.Get('batteries/' + jsonForm.battery_id, - function(batteryDetails) + function (batteryDetails) { Grocy.Api.Post('batteries/' + jsonForm.battery_id + '/charge', { 'tracked_time': $('#tracked_time').find('input').val() }, - function(result) + function (result) { Grocy.EditObjectId = result.id; - Grocy.Components.UserfieldsForm.Save(function() + Grocy.Components.UserfieldsForm.Save(function () { Grocy.FrontendHelpers.EndUiBusy("batterytracking-form"); toastr.success(__t('Tracked charge cycle of battery %1$s on %2$s', batteryDetails.battery.name, $('#tracked_time').find('input').val()) + '
' + __t("Undo") + ''); @@ -36,14 +36,14 @@ Grocy.FrontendHelpers.ValidateForm('batterytracking-form'); }); }, - function(xhr) + function (xhr) { Grocy.FrontendHelpers.EndUiBusy("batterytracking-form"); console.error(xhr); } ); }, - function(xhr) + function (xhr) { Grocy.FrontendHelpers.EndUiBusy("batterytracking-form"); console.error(xhr); @@ -51,7 +51,7 @@ ); }); -$('#battery_id').on('change', function(e) +$('#battery_id').on('change', function (e) { var input = $('#battery_id_text_input').val().toString(); $('#battery_id_text_input').val(input); @@ -62,7 +62,7 @@ $('#battery_id').on('change', function(e) { Grocy.Components.BatteryCard.Refresh(batteryId); - setTimeout(function() + setTimeout(function () { $('#tracked_time').find('input').focus(); }, Grocy.FormFocusDelay); @@ -71,28 +71,24 @@ $('#battery_id').on('change', function(e) } }); -$('.combobox').combobox({ - appendId: '_text_input', - bsVersion: '4', - clearIfNoMatch: false -}); +$(".combobox").combobox(Object.assign(BootstrapComboboxDefaults, { "clearIfNoMatch": false })); $('#battery_id').val(''); $('#battery_id_text_input').val(''); $('#battery_id_text_input').trigger('change'); Grocy.Components.DateTimePicker.GetInputElement().trigger('input'); Grocy.FrontendHelpers.ValidateForm('batterytracking-form'); -setTimeout(function() +setTimeout(function () { $('#battery_id_text_input').focus(); }, Grocy.FormFocusDelay); -$('#batterytracking-form input').keyup(function(event) +$('#batterytracking-form input').keyup(function (event) { Grocy.FrontendHelpers.ValidateForm('batterytracking-form'); }); -$('#batterytracking-form input').keydown(function(event) +$('#batterytracking-form input').keydown(function (event) { if (event.keyCode === 13) // Enter { @@ -109,12 +105,12 @@ $('#batterytracking-form input').keydown(function(event) } }); -$('#tracked_time').find('input').on('keypress', function(e) +$('#tracked_time').find('input').on('keypress', function (e) { Grocy.FrontendHelpers.ValidateForm('batterytracking-form'); }); -$(document).on("Grocy.BarcodeScanned", function(e, barcode, target) +$(document).on("Grocy.BarcodeScanned", function (e, barcode, target) { if (!(target == "@batterypicker" || target == "undefined" || target == undefined)) // Default target { @@ -128,7 +124,7 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target) $("#battery_id_text_input").val(barcode); - setTimeout(function() + setTimeout(function () { $("#battery_id_text_input").focusout(); $("#battery_id_text_input").focus(); @@ -140,18 +136,18 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target) function UndoChargeCycle(chargeCycleId) { Grocy.Api.Post('batteries/charge-cycles/' + chargeCycleId.toString() + '/undo', {}, - function(result) + function (result) { toastr.success(__t("Charge cycle successfully undone")); }, - function(xhr) + function (xhr) { console.error(xhr); } ); }; -$('#battery_id_text_input').on('blur', function(e) +$('#battery_id_text_input').on('blur', function (e) { if ($('#battery_id').hasClass("combobox-menu-visible")) { @@ -187,7 +183,7 @@ $('#battery_id_text_input').on('blur', function(e) } }); -$("#tracked_time").find("input").on("focus", function(e) +$("#tracked_time").find("input").on("focus", function (e) { $(this).select(); }); diff --git a/public/viewjs/choretracking.js b/public/viewjs/choretracking.js index 3760e0cc..81f6f155 100644 --- a/public/viewjs/choretracking.js +++ b/public/viewjs/choretracking.js @@ -1,4 +1,4 @@ -$('.save-choretracking-button').on('click', function(e) +$('.save-choretracking-button').on('click', function (e) { e.preventDefault(); @@ -18,13 +18,13 @@ Grocy.FrontendHelpers.BeginUiBusy("choretracking-form"); Grocy.Api.Get('chores/' + jsonForm.chore_id, - function(choreDetails) + function (choreDetails) { Grocy.Api.Post('chores/' + jsonForm.chore_id + '/execute', { 'tracked_time': Grocy.Components.DateTimePicker.GetValue(), 'done_by': $("#user_id").val(), 'skipped': skipped }, - function(result) + function (result) { Grocy.EditObjectId = result.id; - Grocy.Components.UserfieldsForm.Save(function() + Grocy.Components.UserfieldsForm.Save(function () { Grocy.FrontendHelpers.EndUiBusy("choretracking-form"); toastr.success(__t('Tracked execution of chore %1$s on %2$s', choreDetails.chore.name, Grocy.Components.DateTimePicker.GetValue()) + '
' + __t("Undo") + ''); @@ -38,14 +38,14 @@ Grocy.FrontendHelpers.ValidateForm('choretracking-form'); }); }, - function(xhr) + function (xhr) { Grocy.FrontendHelpers.EndUiBusy("choretracking-form"); console.error(xhr); } ); }, - function(xhr) + function (xhr) { Grocy.FrontendHelpers.EndUiBusy("choretracking-form"); console.error(xhr); @@ -53,7 +53,7 @@ ); }); -$('#chore_id').on('change', function(e) +$('#chore_id').on('change', function (e) { var input = $('#chore_id_text_input').val().toString(); $('#chore_id_text_input').val(input); @@ -63,7 +63,7 @@ $('#chore_id').on('change', function(e) if (choreId) { Grocy.Api.Get('objects/chores/' + choreId, - function(chore) + function (chore) { if (chore.track_date_only == 1) @@ -88,7 +88,7 @@ $('#chore_id').on('change', function(e) Grocy.FrontendHelpers.ValidateForm('choretracking-form'); }, - function(xhr) + function (xhr) { console.error(xhr); } @@ -96,7 +96,7 @@ $('#chore_id').on('change', function(e) Grocy.Components.ChoreCard.Refresh(choreId); - setTimeout(function() + setTimeout(function () { Grocy.Components.DateTimePicker.GetInputElement().focus(); }, Grocy.FormFocusDelay); @@ -105,26 +105,22 @@ $('#chore_id').on('change', function(e) } }); -$('.combobox').combobox({ - appendId: '_text_input', - bsVersion: '4', - clearIfNoMatch: false -}); +$(".combobox").combobox(Object.assign(BootstrapComboboxDefaults, { "clearIfNoMatch": false })); $('#chore_id_text_input').trigger('change'); Grocy.Components.DateTimePicker.GetInputElement().trigger('input'); Grocy.FrontendHelpers.ValidateForm('choretracking-form'); -setTimeout(function() +setTimeout(function () { $('#chore_id_text_input').focus(); }, Grocy.FormFocusDelay); -$('#choretracking-form input').keyup(function(event) +$('#choretracking-form input').keyup(function (event) { Grocy.FrontendHelpers.ValidateForm('choretracking-form'); }); -$('#choretracking-form input').keydown(function(event) +$('#choretracking-form input').keydown(function (event) { if (event.keyCode === 13) // Enter { @@ -141,7 +137,7 @@ $('#choretracking-form input').keydown(function(event) } }); -$(document).on("Grocy.BarcodeScanned", function(e, barcode, target) +$(document).on("Grocy.BarcodeScanned", function (e, barcode, target) { if (!(target == "@chorepicker" || target == "undefined" || target == undefined)) // Default target { @@ -155,7 +151,7 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target) $("#chore_id_text_input").val(barcode); - setTimeout(function() + setTimeout(function () { $("#chore_id_text_input").focusout(); $("#chore_id_text_input").focus(); @@ -164,7 +160,7 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target) }, Grocy.FormFocusDelay); }); -Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e) +Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function (e) { Grocy.FrontendHelpers.ValidateForm('choretracking-form'); }); @@ -172,18 +168,18 @@ Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e) function UndoChoreExecution(executionId) { Grocy.Api.Post('chores/executions/' + executionId.toString() + '/undo', {}, - function(result) + function (result) { toastr.success(__t("Chore execution successfully undone")); }, - function(xhr) + function (xhr) { console.error(xhr); } ); }; -$('#chore_id_text_input').on('blur', function(e) +$('#chore_id_text_input').on('blur', function (e) { if ($('#chore_id').hasClass("combobox-menu-visible")) { @@ -218,7 +214,7 @@ $('#chore_id_text_input').on('blur', function(e) } }); -$("#tracked_time").find("input").on("focus", function(e) +$("#tracked_time").find("input").on("focus", function (e) { $(this).select(); }); diff --git a/public/viewjs/components/locationpicker.js b/public/viewjs/components/locationpicker.js index c6dae8c5..27c0a6f4 100644 --- a/public/viewjs/components/locationpicker.js +++ b/public/viewjs/components/locationpicker.js @@ -1,44 +1,40 @@ Grocy.Components.LocationPicker = {}; -Grocy.Components.LocationPicker.GetPicker = function() +Grocy.Components.LocationPicker.GetPicker = function () { return $('#location_id'); } -Grocy.Components.LocationPicker.GetInputElement = function() +Grocy.Components.LocationPicker.GetInputElement = function () { return $('#location_id_text_input'); } -Grocy.Components.LocationPicker.GetValue = function() +Grocy.Components.LocationPicker.GetValue = function () { return $('#location_id').val(); } -Grocy.Components.LocationPicker.SetValue = function(value) +Grocy.Components.LocationPicker.SetValue = function (value) { Grocy.Components.LocationPicker.GetInputElement().val(value); Grocy.Components.LocationPicker.GetInputElement().trigger('change'); } -Grocy.Components.LocationPicker.SetId = function(value) +Grocy.Components.LocationPicker.SetId = function (value) { Grocy.Components.LocationPicker.GetPicker().val(value); Grocy.Components.LocationPicker.GetPicker().data('combobox').refresh(); Grocy.Components.LocationPicker.GetInputElement().trigger('change'); } -Grocy.Components.LocationPicker.Clear = function() +Grocy.Components.LocationPicker.Clear = function () { Grocy.Components.LocationPicker.SetValue(''); Grocy.Components.LocationPicker.SetId(null); } -$('.location-combobox').combobox({ - appendId: '_text_input', - bsVersion: '4', - clearIfNoMatch: true -}); +$(".location-combobox").combobox(BootstrapComboboxDefaults); var prefillByName = Grocy.Components.LocationPicker.GetPicker().parent().data('prefill-by-name').toString(); if (typeof prefillByName !== "undefined") diff --git a/public/viewjs/components/productpicker.js b/public/viewjs/components/productpicker.js index 0141fed1..efba2167 100644 --- a/public/viewjs/components/productpicker.js +++ b/public/viewjs/components/productpicker.js @@ -1,56 +1,56 @@ Grocy.Components.ProductPicker = {}; -Grocy.Components.ProductPicker.GetPicker = function() +Grocy.Components.ProductPicker.GetPicker = function () { return $('#product_id'); } -Grocy.Components.ProductPicker.GetInputElement = function() +Grocy.Components.ProductPicker.GetInputElement = function () { return $('#product_id_text_input'); } -Grocy.Components.ProductPicker.GetValue = function() +Grocy.Components.ProductPicker.GetValue = function () { return $('#product_id').val(); } -Grocy.Components.ProductPicker.SetValue = function(value) +Grocy.Components.ProductPicker.SetValue = function (value) { Grocy.Components.ProductPicker.GetInputElement().val(value); Grocy.Components.ProductPicker.GetInputElement().trigger('change'); } -Grocy.Components.ProductPicker.SetId = function(value) +Grocy.Components.ProductPicker.SetId = function (value) { Grocy.Components.ProductPicker.GetPicker().val(value); Grocy.Components.ProductPicker.GetPicker().data('combobox').refresh(); Grocy.Components.ProductPicker.GetInputElement().trigger('change'); } -Grocy.Components.ProductPicker.Clear = function() +Grocy.Components.ProductPicker.Clear = function () { Grocy.Components.ProductPicker.SetValue(''); Grocy.Components.ProductPicker.SetId(null); $('#product_id').attr("barcode", "null"); } -Grocy.Components.ProductPicker.InProductAddWorkflow = function() +Grocy.Components.ProductPicker.InProductAddWorkflow = function () { return GetUriParam('flow') == "InplaceNewProductWithName"; } -Grocy.Components.ProductPicker.InProductModifyWorkflow = function() +Grocy.Components.ProductPicker.InProductModifyWorkflow = function () { return GetUriParam('flow') == "InplaceAddBarcodeToExistingProduct"; } -Grocy.Components.ProductPicker.InAnyFlow = function() +Grocy.Components.ProductPicker.InAnyFlow = function () { return Grocy.Components.ProductPicker.InProductAddWorkflow() || Grocy.Components.ProductPicker.InProductModifyWorkflow(); } -Grocy.Components.ProductPicker.FinishFlow = function() +Grocy.Components.ProductPicker.FinishFlow = function () { if (GetUriParam("flow") == "InplaceAddBarcodeToExistingProduct") { @@ -62,37 +62,33 @@ Grocy.Components.ProductPicker.FinishFlow = function() RemoveUriParam("product-name"); } -Grocy.Components.ProductPicker.ShowCustomError = function(text) +Grocy.Components.ProductPicker.ShowCustomError = function (text) { var element = $("#custom-productpicker-error"); element.text(text); element.removeClass("d-none"); } -Grocy.Components.ProductPicker.HideCustomError = function() +Grocy.Components.ProductPicker.HideCustomError = function () { $("#custom-productpicker-error").addClass("d-none"); } -Grocy.Components.ProductPicker.Disable = function() +Grocy.Components.ProductPicker.Disable = function () { Grocy.Components.ProductPicker.GetInputElement().attr("disabled", ""); $("#camerabarcodescanner-start-button").attr("disabled", ""); $("#camerabarcodescanner-start-button").addClass("disabled"); } -Grocy.Components.ProductPicker.Enable = function() +Grocy.Components.ProductPicker.Enable = function () { Grocy.Components.ProductPicker.GetInputElement().removeAttr("disabled"); $("#camerabarcodescanner-start-button").removeAttr("disabled"); $("#camerabarcodescanner-start-button").removeClass("disabled"); } -$('.product-combobox').combobox({ - appendId: '_text_input', - bsVersion: '4', - clearIfNoMatch: false -}); +$(".product-combobox").combobox(Object.assign(BootstrapComboboxDefaults, { "clearIfNoMatch": false })); var prefillProduct = GetUriParam('product-name'); var prefillProduct2 = Grocy.Components.ProductPicker.GetPicker().parent().data('prefill-by-name').toString(); @@ -152,7 +148,7 @@ if (GetUriParam("flow") === "InplaceAddBarcodeToExistingProduct") } Grocy.Components.ProductPicker.PopupOpen = false; -$('#product_id_text_input').on('blur', function(e) +$('#product_id_text_input').on('blur', function (e) { if (Grocy.Components.ProductPicker.GetPicker().hasClass("combobox-menu-visible")) { @@ -212,10 +208,10 @@ $('#product_id_text_input').on('blur', function(e) cancel: { label: __t('Cancel'), className: 'btn-secondary responsive-button productpicker-workflow-cancel-button', - callback: function() + callback: function () { Grocy.Components.ProductPicker.PopupOpen = false; - setTimeout(function() + setTimeout(function () { Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductPicker.GetInputElement().select(); @@ -225,7 +221,7 @@ $('#product_id_text_input').on('blur', function(e) addnewproduct: { label: 'P ' + __t('Add as new product'), className: 'btn-success add-new-product-dialog-button responsive-button ' + addProductWorkflowsAdditionalCssClasses, - callback: function() + callback: function () { // Not the best place here - this is only relevant when this flow is started from the shopping list item form // (to select the correct shopping list on return) @@ -241,7 +237,7 @@ $('#product_id_text_input').on('blur', function(e) addbarcode: { label: 'B ' + __t('Add as barcode to existing product'), className: 'btn-info add-new-barcode-dialog-button responsive-button', - callback: function() + callback: function () { Grocy.Components.ProductPicker.PopupOpen = false; window.location.href = U(Grocy.CurrentUrlRelative + '?flow=InplaceAddBarcodeToExistingProduct&barcode=' + encodeURIComponent(input) + "&" + embedded); @@ -250,7 +246,7 @@ $('#product_id_text_input').on('blur', function(e) addnewproductwithbarcode: { label: 'A ' + __t('Add as new product and prefill barcode'), className: 'btn-warning add-new-product-with-barcode-dialog-button responsive-button ' + addProductWorkflowsAdditionalCssClasses, - callback: function() + callback: function () { Grocy.Components.ProductPicker.PopupOpen = false; window.location.href = U('/product/new?flow=InplaceNewProductWithBarcode&barcode=' + encodeURIComponent(input) + '&returnto=' + encodeURIComponent(Grocy.CurrentUrlRelative + "?flow=InplaceAddBarcodeToExistingProduct&barcode=" + input + "&" + embedded) + "&" + embedded); @@ -263,19 +259,19 @@ $('#product_id_text_input').on('blur', function(e) buttons.barcodepluginlookup = { label: 'E ' + __t('External barcode lookup') + ' ' + Grocy.ExternalBarcodeLookupPluginName + '', className: 'btn-dark add-new-product-plugin-dialog-button responsive-button ' + addProductWorkflowsAdditionalCssClasses, - callback: function() + callback: function () { Grocy.Components.ProductPicker.PopupOpen = false; Grocy.FrontendHelpers.BeginUiBusy($("form").first().attr("id")); Grocy.Api.Get("stock/barcodes/external-lookup/" + encodeURIComponent(input) + "?add=true", - function(pluginResponse) + function (pluginResponse) { if (pluginResponse == null) { toastr.warning(__t("Nothing was found for the given barcode")); Grocy.FrontendHelpers.EndUiBusy($("form").first().attr("id")); - setTimeout(function() + setTimeout(function () { Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductPicker.GetInputElement().select(); @@ -286,7 +282,7 @@ $('#product_id_text_input').on('blur', function(e) window.location.href = U("/product/" + pluginResponse.id + "?flow=InplaceNewProductByExternalBarcodeLookupPlugin&returnto=" + encodeURIComponent(Grocy.CurrentUrlRelative + "?flow=InplaceNewProductWithName&" + embedded) + "&" + embedded); } }, - function(xhr) + function (xhr) { Grocy.FrontendHelpers.ShowGenericError("Error while executing the barcode lookup plugin", xhr.response); Grocy.FrontendHelpers.EndUiBusy($("form").first().attr("id")); @@ -301,7 +297,7 @@ $('#product_id_text_input').on('blur', function(e) buttons.retrycamerascanning = { label: 'C ', className: 'btn-primary responsive-button retry-camera-scanning-button', - callback: function() + callback: function () { Grocy.Components.ProductPicker.PopupOpen = false; Grocy.Components.ProductPicker.SetValue(''); @@ -317,7 +313,7 @@ $('#product_id_text_input').on('blur', function(e) var existsAsProduct = false; var existsAsBarcode = false; Grocy.Api.Get('objects/product_barcodes_view?query[]=barcode=' + input, - function(barcodeResult) + function (barcodeResult) { if (barcodeResult.length > 0) { @@ -325,7 +321,7 @@ $('#product_id_text_input').on('blur', function(e) } Grocy.Api.Get('objects/products?query[]=name=' + input, - function(productResult) + function (productResult) { if (productResult.length > 0) { @@ -338,7 +334,7 @@ $('#product_id_text_input').on('blur', function(e) bootbox.dialog({ message: __t('"%s" could not be resolved to a product, how do you want to proceed?', input), title: __t('Create or assign product'), - onEscape: function() + onEscape: function () { $(".productpicker-workflow-cancel-button").click(); }, @@ -347,7 +343,7 @@ $('#product_id_text_input').on('blur', function(e) closeButton: false, buttons: buttons, className: "wider custom-escape-key-handling", - }).on('keypress', function(e) + }).on('keypress', function (e) { if (e.key === 'B' || e.key === 'b') { @@ -377,19 +373,19 @@ $('#product_id_text_input').on('blur', function(e) Grocy.Components.ProductPicker.Clear(); Grocy.FrontendHelpers.ValidateForm('consume-form'); Grocy.Components.ProductPicker.ShowCustomError(__t('This product is not in stock')); - setTimeout(function() + setTimeout(function () { Grocy.Components.ProductPicker.GetInputElement().focus(); }, Grocy.FormFocusDelay); } }, - function(xhr) + function (xhr) { console.error(xhr); } ); }, - function(xhr) + function (xhr) { console.error(xhr); } @@ -398,7 +394,7 @@ $('#product_id_text_input').on('blur', function(e) } }); -$(document).on("Grocy.BarcodeScanned", function(e, barcode, target) +$(document).on("Grocy.BarcodeScanned", function (e, barcode, target) { if (!(target == "@productpicker" || target == "undefined" || target == undefined)) // Default target { @@ -412,7 +408,7 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target) Grocy.Components.ProductPicker.GetInputElement().val(barcode); - setTimeout(function() + setTimeout(function () { Grocy.Components.ProductPicker.GetInputElement().focusout(); Grocy.Components.ProductPicker.GetInputElement().focus(); @@ -420,14 +416,14 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target) }, Grocy.FormFocusDelay); }); -$(document).on("shown.bs.modal", function(e) +$(document).on("shown.bs.modal", function (e) { $(".modal-footer").addClass("d-block").addClass("d-sm-flex"); $(".modal-footer").find("button").addClass("mt-2").addClass("mt-sm-0"); }) // Make that ENTER behaves the same like TAB (trigger blur to start workflows, but only when the dropdown is not opened) -$('#product_id_text_input').keydown(function(event) +$('#product_id_text_input').keydown(function (event) { if (event.keyCode === 13) // Enter { diff --git a/public/viewjs/components/recipepicker.js b/public/viewjs/components/recipepicker.js index aada2328..5be42c17 100644 --- a/public/viewjs/components/recipepicker.js +++ b/public/viewjs/components/recipepicker.js @@ -1,44 +1,40 @@ Grocy.Components.RecipePicker = {}; -Grocy.Components.RecipePicker.GetPicker = function() +Grocy.Components.RecipePicker.GetPicker = function () { return $('#recipe_id'); } -Grocy.Components.RecipePicker.GetInputElement = function() +Grocy.Components.RecipePicker.GetInputElement = function () { return $('#recipe_id_text_input'); } -Grocy.Components.RecipePicker.GetValue = function() +Grocy.Components.RecipePicker.GetValue = function () { return $('#recipe_id').val(); } -Grocy.Components.RecipePicker.SetValue = function(value) +Grocy.Components.RecipePicker.SetValue = function (value) { Grocy.Components.RecipePicker.GetInputElement().val(value); Grocy.Components.RecipePicker.GetInputElement().trigger('change'); } -Grocy.Components.RecipePicker.SetId = function(value) +Grocy.Components.RecipePicker.SetId = function (value) { Grocy.Components.RecipePicker.GetPicker().val(value); Grocy.Components.RecipePicker.GetPicker().data('combobox').refresh(); Grocy.Components.RecipePicker.GetInputElement().trigger('change'); } -Grocy.Components.RecipePicker.Clear = function() +Grocy.Components.RecipePicker.Clear = function () { Grocy.Components.RecipePicker.SetValue(''); Grocy.Components.RecipePicker.SetId(null); } -$('.recipe-combobox').combobox({ - appendId: '_text_input', - bsVersion: '4', - clearIfNoMatch: false -}); +$(".recipe-combobox").combobox(Object.assign(BootstrapComboboxDefaults, { "clearIfNoMatch": false })); var prefillByName = Grocy.Components.RecipePicker.GetPicker().parent().data('prefill-by-name').toString(); if (typeof prefillByName !== "undefined") @@ -67,7 +63,7 @@ if (typeof prefillById !== "undefined") nextInputElement.focus(); } -$('#recipe_id_text_input').on('blur', function(e) +$('#recipe_id_text_input').on('blur', function (e) { if ($('#recipe_id').hasClass("combobox-menu-visible")) { @@ -102,7 +98,7 @@ $('#recipe_id_text_input').on('blur', function(e) } }); -$(document).on("Grocy.BarcodeScanned", function(e, barcode, target) +$(document).on("Grocy.BarcodeScanned", function (e, barcode, target) { if (!(target == "@recipepicker" || target == "undefined" || target == undefined)) // Default target { @@ -116,7 +112,7 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target) Grocy.Components.RecipePicker.GetInputElement().val(barcode); - setTimeout(function() + setTimeout(function () { Grocy.Components.RecipePicker.GetInputElement().focusout(); Grocy.Components.RecipePicker.GetInputElement().focus(); diff --git a/public/viewjs/components/shoppinglocationpicker.js b/public/viewjs/components/shoppinglocationpicker.js index 2c141dde..a51ec092 100644 --- a/public/viewjs/components/shoppinglocationpicker.js +++ b/public/viewjs/components/shoppinglocationpicker.js @@ -1,44 +1,40 @@ Grocy.Components.ShoppingLocationPicker = {}; -Grocy.Components.ShoppingLocationPicker.GetPicker = function() +Grocy.Components.ShoppingLocationPicker.GetPicker = function () { return $('#shopping_location_id'); } -Grocy.Components.ShoppingLocationPicker.GetInputElement = function() +Grocy.Components.ShoppingLocationPicker.GetInputElement = function () { return $('#shopping_location_id_text_input'); } -Grocy.Components.ShoppingLocationPicker.GetValue = function() +Grocy.Components.ShoppingLocationPicker.GetValue = function () { return $('#shopping_location_id').val(); } -Grocy.Components.ShoppingLocationPicker.SetValue = function(value) +Grocy.Components.ShoppingLocationPicker.SetValue = function (value) { Grocy.Components.ShoppingLocationPicker.GetInputElement().val(value); Grocy.Components.ShoppingLocationPicker.GetInputElement().trigger('change'); } -Grocy.Components.ShoppingLocationPicker.SetId = function(value) +Grocy.Components.ShoppingLocationPicker.SetId = function (value) { Grocy.Components.ShoppingLocationPicker.GetPicker().val(value); Grocy.Components.ShoppingLocationPicker.GetPicker().data('combobox').refresh(); Grocy.Components.ShoppingLocationPicker.GetInputElement().trigger('change'); } -Grocy.Components.ShoppingLocationPicker.Clear = function() +Grocy.Components.ShoppingLocationPicker.Clear = function () { Grocy.Components.ShoppingLocationPicker.SetValue(''); Grocy.Components.ShoppingLocationPicker.SetId(null); } -$('.shopping-location-combobox').combobox({ - appendId: '_text_input', - bsVersion: '4', - clearIfNoMatch: true -}); +$(".shopping-location-combobox").combobox(BootstrapComboboxDefaults); var prefillByName = Grocy.Components.ShoppingLocationPicker.GetPicker().parent().data('prefill-by-name').toString(); if (typeof prefillByName !== "undefined") diff --git a/public/viewjs/components/userpicker.js b/public/viewjs/components/userpicker.js index f36a83fb..ce9d8b9e 100644 --- a/public/viewjs/components/userpicker.js +++ b/public/viewjs/components/userpicker.js @@ -1,43 +1,40 @@ Grocy.Components.UserPicker = {}; -Grocy.Components.UserPicker.GetPicker = function() +Grocy.Components.UserPicker.GetPicker = function () { return $('#user_id'); } -Grocy.Components.UserPicker.GetInputElement = function() +Grocy.Components.UserPicker.GetInputElement = function () { return $('#user_id_text_input'); } -Grocy.Components.UserPicker.GetValue = function() +Grocy.Components.UserPicker.GetValue = function () { return $('#user_id').val(); } -Grocy.Components.UserPicker.SetValue = function(value) +Grocy.Components.UserPicker.SetValue = function (value) { Grocy.Components.UserPicker.GetInputElement().val(value); Grocy.Components.UserPicker.GetInputElement().trigger('change'); } -Grocy.Components.UserPicker.SetId = function(value) +Grocy.Components.UserPicker.SetId = function (value) { Grocy.Components.UserPicker.GetPicker().val(value); Grocy.Components.UserPicker.GetPicker().data('combobox').refresh(); Grocy.Components.UserPicker.GetInputElement().trigger('change'); } -Grocy.Components.UserPicker.Clear = function() +Grocy.Components.UserPicker.Clear = function () { Grocy.Components.UserPicker.SetValue(''); Grocy.Components.UserPicker.SetId(null); } -$('.user-combobox').combobox({ - appendId: '_text_input', - bsVersion: '4' -}); +$(".user-combobox").combobox(BootstrapComboboxDefaults); var prefillUser = Grocy.Components.UserPicker.GetPicker().parent().data('prefill-by-username').toString(); if (typeof prefillUser !== "undefined") diff --git a/views/components/productpicker.blade.php b/views/components/productpicker.blade.php index 72d1ccdd..c9e18a5c 100644 --- a/views/components/productpicker.blade.php +++ b/views/components/productpicker.blade.php @@ -5,9 +5,11 @@ @endpush @push('componentScripts') +@if(isset($ExternalBarcodeLookupPluginName)) +@endif @endpush @endonce diff --git a/views/layout/default.blade.php b/views/layout/default.blade.php index 7c28f713..5556f56d 100644 --- a/views/layout/default.blade.php +++ b/views/layout/default.blade.php @@ -715,8 +715,6 @@ - - diff --git a/views/mealplan.blade.php b/views/mealplan.blade.php index 192ac3be..a9dc616c 100644 --- a/views/mealplan.blade.php +++ b/views/mealplan.blade.php @@ -281,7 +281,8 @@ @include('components.productpicker', array( 'products' => $products, - 'nextInputSelector' => '#amount' + 'nextInputSelector' => '#amount', + 'disallowAddProductWorkflows' => true )) @include('components.productamountpicker', array( diff --git a/yarn.lock b/yarn.lock index 723bf5a6..b7e60059 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21,18 +21,6 @@ resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.4.0.tgz#3bbb984085dbd6d982494538b523be1ce6562972" integrity sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ== -"@types/jquery@^3.5.16": - version "3.5.34" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.34.tgz#c1993eaac0db03cf9db974976dd8f07bbf7c5708" - integrity sha512-3m3939S3erqmTLJANS/uy0B6V7BorKx7RorcGZVjZ62dF5PAGbKEDZK1CuLtKombJkFA2T1jl8LAIIs7IV6gBQ== - dependencies: - "@types/sizzle" "*" - -"@types/sizzle@*": - version "2.3.10" - resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.10.tgz#277a542aff6776d8a9b15f2ac682a663e3e94bbd" - integrity sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww== - "@zxing/library@^0.21.3": version "0.21.3" resolved "https://registry.yarnpkg.com/@zxing/library/-/library-0.21.3.tgz#0a4cb777701884131832b05922d7e88ef1b87ab4" @@ -165,14 +153,6 @@ datatables.net-colreorder@1.7.2, datatables.net-colreorder@^1.5.2: datatables.net "^1.13.0" jquery ">=1.7" -datatables.net-plugins@^1.10.20: - version "1.13.6" - resolved "https://registry.yarnpkg.com/datatables.net-plugins/-/datatables.net-plugins-1.13.6.tgz#7b0af0675083e2c669ccd09ef7c86878d6c9638d" - integrity sha512-CPLH+09OiEAP3PKbZH7u2qcLajgHhy4fBHCdLzjGWJwKbIkhaPu7tby4jZHQXqoolUznbm3TEpJj4eMI1eqcGw== - dependencies: - "@types/jquery" "^3.5.16" - datatables.net "^1.13.2" - datatables.net-rowgroup-bs4@^1.1.2: version "1.6.0" resolved "https://registry.yarnpkg.com/datatables.net-rowgroup-bs4/-/datatables.net-rowgroup-bs4-1.6.0.tgz#452cd6ebb576c76d0341cf4fece21cdbd194a617" @@ -215,7 +195,7 @@ datatables.net-select@1.7.1, datatables.net-select@^1.3.1: datatables.net "^1.13.0" jquery ">=1.7" -datatables.net@1.13.11, datatables.net@^1.10.22, datatables.net@^1.13.0, datatables.net@^1.13.2: +datatables.net@1.13.11, datatables.net@^1.10.22, datatables.net@^1.13.0: version "1.13.11" resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.13.11.tgz#e2a4c8b50553512f241ebfcbc078d74d551183b2" integrity sha512-AE6RkMXziRaqzPcu/pl3SJXeRa6fmXQG/fVjuRESujvkzqDCYEeKTTpPMuVJSGYJpPi32WGSphVNNY1G4nSN/g==