Compare commits

..

No commits in common. "master" and "v4.6.0" have entirely different histories.

23 changed files with 176 additions and 296 deletions

View File

@ -15,5 +15,5 @@ if ($adminUserRow == null)
}
$adminUserRow->update([
'password' => password_hash('admin', PASSWORD_ARGON2ID)
'password' => password_hash('admin', PASSWORD_DEFAULT)
]);

8
.editorconfig Normal file
View File

@ -0,0 +1,8 @@
root = true
[*]
indent_style = tab
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View File

@ -14,7 +14,6 @@ Please make sure to:
- Attach screenshots where useful
- Check if the problem was maybe already reported or fixed by searching open and also already closed requests here
- Keep it to one topic per request
- Exclude any AI generated content and only include what you truly understand yourself
Please also try to reproduce the problem on the pre-release demo: => https://demo-prerelease.grocy.info
- Use a private demo instance to make your example persistent

View File

@ -13,5 +13,4 @@ Please make sure to:
- Describe what you would find useful as detailed as possible
- Check if your idea was maybe already requested by searching open and also already closed requests here
- Keep it to one topic per request
- Exclude any AI generated content and only include what you truly understand yourself
-->

View File

@ -117,9 +117,7 @@ else
$authMiddlewareClass = GROCY_AUTH_CLASS;
$app->add(new $authMiddlewareClass($container, $app->getResponseFactory()));
// Add default middleware
$app->addBodyParsingMiddleware();
$app->addRoutingMiddleware();
$errorMiddleware = $app->addErrorMiddleware(true, false, false);
$errorMiddleware->setDefaultErrorHandler(

View File

@ -8,6 +8,6 @@
- Show a calendar on the shopping list page (useful, at least for me)
- Table column ordering and sorting is now remembered
- Sidebar collapse state is now remembered
- Fixed date time picker border
- Fixed datetimepicker border
- Keep the parent sidebar menu item expanded if the active page is a sub menu item
- Custom JS/CSS file names have changed [see README](https://github.com/grocy/grocy#adding-your-own-css-or-js-without-to-have-to-modify-the-application-itself)

View File

@ -2,7 +2,7 @@
- => https://github.com/grocy/grocy-desktop
- Run Grocy without a webserver just like a normal (Windows) desktop application
- New "embedded mode" for Grocy to help running in "desktop application mode" [see README](https://github.com/grocy/grocy#embedded-mode)
- New date time picker shorthands and improvements
- New datepicker shorthands and improvements
- `YYYYMMe` or `YYYYMM+` gets expanded to the end of the given month in the given year in proper notation
- Changed: `MMDD` will be expanded to the given day next year if > today
- [see README](https://github.com/grocy/grocy#input-shorthands-for-date-fields)

View File

@ -1,6 +1,6 @@
- Fixed that price data (last price & chart) was not taken from inventory correction bookings, only purchases
- Fixed weekly chores were scheduled on the same day after execution
- Fixed that undone chores were also included in "Last tracked"
- Fixed the date time picker width was too narrow sometimes
- Fixed the date-time-picker width was too narrow sometimes
- Improved that execution dates of "Track date only" chores will never display the time part
- Improved date display for products that never expire (again, there was a display problem after consuming an item on the stock overview page)

View File

@ -73,7 +73,7 @@
### General & other improvements/fixes
- Added a new `config.php` setting `CALENDAR_SHOW_WEEK_OF_YEAR` to configure if calendars should show week numbers (defaults to `true`)
- Fixed that date time pickers not considered the `config.php` setting `CALENDAR_FIRST_DAY_OF_WEEK`
- Fixed that date/time pickers not considered the `config.php` setting `CALENDAR_FIRST_DAY_OF_WEEK`
- Improved the handling which entry page to use with disabled feature flags (thanks @nielstholenaar)
- Boolean settings provided via environment variables (so the strings `true` and `false`) are now parsed correctly (thanks @mduret)
- All uploaded pictures (currently for products and recipes) are now automatically downscaled to the appropriate size when serving them to improve page load times (this requires the `php-gd` extension, if not installed, images will not be downscaled)

View File

@ -43,7 +43,7 @@ If you run Grocy in a subdirectory, you need to set a new `config.php` setting (
- Added a button to enable the device flash light on the camera barcode scanner popup (thanks @radim-ek)
- Optimized the top navbar height and overall spacing to waste less space
- Replaced the scan-mode-switch-button by a native button because it's less disturbing
- Fixed that the "contextual time ago" of date time pickers was not displayed
- Fixed that the "contextual time ago" of date/time pickers was not displayed
- New translations: (thanks all the translators)
- Czech (demo available at https://cs.demo.grocy.info)
- Portuguese (Portugal) (demo available at https://pt-pt.demo.grocy.info)

View File

@ -44,7 +44,7 @@
- Fixed that CORS was broken (there was no response to preflight OPTIONS requests)
### General & other improvements/fixes
- Optimized that sometimes the corresponding form was not validated when selecting a date from the date time picker
- Optimized that sometimes the corresponding form was not validated when selecting a date from the datetimepicker
- New `config.php` setting `FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_FIELD_NUMBER_PAD` which activates the number pad for best-before-date fields on (supported) mobile browsers (useful because of [shorthands](https://github.com/grocy/grocy#input-shorthands-for-date-fields)) (defaults to `true`) (thanks @Mik-)
- Enhancements for the camera barcode scanner
- Torch / light improvements (thanks @Mik-)

View File

@ -1,59 +0,0 @@
> ⚠️ xxxBREAKING CHANGESxxx
> ❗ xxxImportant upgrade informationXXX
> 💡 xxxMinor upgrade informationXXX
### New Feature: xxxx
- xxx
### Stock
- 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
### Shopping list
- xxx
### Recipes
- xxx
### Meal plan
- xxx
### Chores
- xxx
### Calendar
- xxx
### Tasks
- xxx
### Batteries
- xxx
### Equipment
- xxx
### Userfields
- Fixed that Userfields of type "Select list (a single item can be selected)" changed by keyboard only were not saved
### General
- Fixed that it wasn't possible to log in using passwords containing special escape sequences (e.g. `<<`)
### API
- xxx

View File

@ -22,15 +22,7 @@ class LoginController extends BaseController
public function ProcessLogin(Request $request, Response $response, array $args)
{
$authMiddlewareClass = GROCY_AUTH_CLASS;
$postParams = $request->getParsedBody();
if (isset($postParams['password_base64']))
{
$postParams['password'] = base64_decode($postParams['password_base64']);
}
unset($postParams['password_base64']);
if ($authMiddlewareClass::ProcessLogin($postParams))
if ($authMiddlewareClass::ProcessLogin($request->getParsedBody()))
{
return $response->withRedirect($this->AppContainer->get('UrlManager')->ConstructUrl('/'));
}

View File

@ -43,12 +43,6 @@ class UsersApiController extends BaseApiController
throw new \Exception('Request body could not be parsed (probably invalid JSON format or missing/wrong Content-Type header)');
}
if (isset($requestBody['password_base64']))
{
$requestBody['password'] = base64_decode($requestBody['password_base64']);
}
unset($requestBody['password_base64']);
$this->getUsersService()->CreateUser($requestBody['username'], $requestBody['first_name'], $requestBody['last_name'], $requestBody['password'], $requestBody['picture_file_name']);
return $this->EmptyApiResponse($response);
}
@ -87,12 +81,6 @@ class UsersApiController extends BaseApiController
try
{
if (isset($requestBody['password_base64']))
{
$requestBody['password'] = base64_decode($requestBody['password_base64']);
}
unset($requestBody['password_base64']);
$this->getUsersService()->EditUser($args['userId'], $requestBody['username'], $requestBody['first_name'], $requestBody['last_name'], $requestBody['password'], $requestBody['picture_file_name']);
return $this->EmptyApiResponse($response);
}

View File

@ -40,10 +40,10 @@ class DefaultAuthMiddleware extends AuthMiddleware
$sessionKey = SessionService::getInstance()->CreateSession($user->id, $stayLoggedInPermanently);
self::SetSessionCookie($sessionKey);
if (password_needs_rehash($user->password, PASSWORD_ARGON2ID))
if (password_needs_rehash($user->password, PASSWORD_DEFAULT))
{
$user->update([
'password' => password_hash($inputPassword, PASSWORD_ARGON2ID)
'password' => password_hash($inputPassword, PASSWORD_DEFAULT)
]);
}

View File

@ -9,7 +9,7 @@ if (defined('GROCY_HTTP_USER'))
// Migrate old user defined in config file to database
$newUserRow = $db->users()->createRow([
'username' => GROCY_HTTP_USER,
'password' => password_hash(GROCY_HTTP_PASSWORD, PASSWORD_ARGON2ID)
'password' => password_hash(GROCY_HTTP_PASSWORD, PASSWORD_DEFAULT)
]);
$newUserRow->save();
}
@ -18,7 +18,7 @@ else
// Create default user "admin" with password "admin"
$newUserRow = $db->users()->createRow([
'username' => 'admin',
'password' => password_hash('admin', PASSWORD_ARGON2ID)
'password' => password_hash('admin', PASSWORD_DEFAULT)
]);
$newUserRow->save();
}

View File

@ -1,10 +1,10 @@
Grocy.Api = {};
Grocy.Api.Get = function (apiFunction, success, error)
Grocy.Api.Get = function(apiFunction, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/' + apiFunction);
xhr.onreadystatechange = function ()
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
@ -36,12 +36,12 @@ Grocy.Api.Get = function (apiFunction, success, error)
xhr.send();
};
Grocy.Api.Post = function (apiFunction, jsonData, success, error)
Grocy.Api.Post = function(apiFunction, jsonData, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/' + apiFunction);
xhr.onreadystatechange = function ()
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
@ -74,12 +74,12 @@ Grocy.Api.Post = function (apiFunction, jsonData, success, error)
xhr.send(JSON.stringify(jsonData));
};
Grocy.Api.Put = function (apiFunction, jsonData, success, error)
Grocy.Api.Put = function(apiFunction, jsonData, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/' + apiFunction);
xhr.onreadystatechange = function ()
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
@ -112,12 +112,12 @@ Grocy.Api.Put = function (apiFunction, jsonData, success, error)
xhr.send(JSON.stringify(jsonData));
};
Grocy.Api.Delete = function (apiFunction, jsonData, success, error)
Grocy.Api.Delete = function(apiFunction, jsonData, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/' + apiFunction);
xhr.onreadystatechange = function ()
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
@ -150,12 +150,12 @@ Grocy.Api.Delete = function (apiFunction, jsonData, success, error)
xhr.send(JSON.stringify(jsonData));
};
Grocy.Api.UploadFile = function (file, group, fileName, success, error)
Grocy.Api.UploadFile = function(file, group, fileName, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/files/' + group + '/' + btoa(fileName));
xhr.onreadystatechange = function ()
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
@ -188,12 +188,12 @@ Grocy.Api.UploadFile = function (file, group, fileName, success, error)
xhr.send(file);
};
Grocy.Api.DeleteFile = function (fileName, group, success, error)
Grocy.Api.DeleteFile = function(fileName, group, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/files/' + group + '/' + btoa(fileName));
xhr.onreadystatechange = function ()
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
@ -226,14 +226,14 @@ Grocy.Api.DeleteFile = function (fileName, group, success, error)
xhr.send();
};
U = function (relativePath)
U = function(relativePath)
{
return Grocy.BaseUrl.replace(/\/$/, '') + relativePath;
}
Grocy.Translator = new window.translator.default(Grocy.LocalizationStrings);
Grocy.TranslatorQu = new window.translator.default(Grocy.LocalizationStringsQu);
__t = function (text, ...placeholderValues)
__t = function(text, ...placeholderValues)
{
if (!text)
{
@ -258,7 +258,7 @@ __t = function (text, ...placeholderValues)
return Grocy.Translator.__(text, ...placeholderValues);
}
}
__n = function (number, singularForm, pluralForm, isQu = false)
__n = function(number, singularForm, pluralForm, isQu = false)
{
if (!singularForm)
{
@ -291,9 +291,9 @@ __n = function (number, singularForm, pluralForm, isQu = false)
}
}
RefreshContextualTimeago = function (rootSelector = "#page-content")
RefreshContextualTimeago = function(rootSelector = "#page-content")
{
$(rootSelector + " time.timeago").each(function ()
$(rootSelector + " time.timeago").each(function()
{
var element = $(this);
@ -357,7 +357,7 @@ toastr.options = {
};
Grocy.FrontendHelpers = {};
Grocy.FrontendHelpers.ValidateForm = function (formId, reportValidity = false)
Grocy.FrontendHelpers.ValidateForm = function(formId, reportValidity = false)
{
var form = document.getElementById(formId);
if (form === null || form === undefined)
@ -375,7 +375,7 @@ Grocy.FrontendHelpers.ValidateForm = function (formId, reportValidity = false)
return form.checkValidity();
}
Grocy.FrontendHelpers.BeginUiBusy = function (formId = null)
Grocy.FrontendHelpers.BeginUiBusy = function(formId = null)
{
$("body").addClass("cursor-busy");
@ -385,7 +385,7 @@ Grocy.FrontendHelpers.BeginUiBusy = function (formId = null)
}
}
Grocy.FrontendHelpers.EndUiBusy = function (formId = null)
Grocy.FrontendHelpers.EndUiBusy = function(formId = null)
{
$("body").removeClass("cursor-busy");
@ -395,10 +395,10 @@ Grocy.FrontendHelpers.EndUiBusy = function (formId = null)
}
}
Grocy.FrontendHelpers.ShowGenericError = function (message, exception)
Grocy.FrontendHelpers.ShowGenericError = function(message, exception)
{
toastr.error(__t(message) + '<br><br>' + __t('Click to show technical details'), '', {
onclick: function ()
onclick: function()
{
var errorDetails = JSON.stringify(exception, null, 4);
if (typeof exception === "object" && exception !== null && exception.hasOwnProperty("error_message"))
@ -418,7 +418,7 @@ Grocy.FrontendHelpers.ShowGenericError = function (message, exception)
console.error(exception);
}
Grocy.FrontendHelpers.SaveUserSetting = function (settingsKey, value, force = false)
Grocy.FrontendHelpers.SaveUserSetting = function(settingsKey, value, force = false)
{
if (Grocy.UserSettings[settingsKey] == value && !force)
{
@ -430,30 +430,30 @@ Grocy.FrontendHelpers.SaveUserSetting = function (settingsKey, value, force = fa
jsonData = {};
jsonData.value = value;
Grocy.Api.Put('user/settings/' + settingsKey, jsonData,
function (result)
function(result)
{
// Nothing to do...
},
function (xhr)
function(xhr)
{
console.error(xhr);
}
);
}
Grocy.FrontendHelpers.DeleteUserSetting = function (settingsKey, reloadPageOnSuccess = false)
Grocy.FrontendHelpers.DeleteUserSetting = function(settingsKey, reloadPageOnSuccess = false)
{
delete Grocy.UserSettings[settingsKey];
Grocy.Api.Delete('user/settings/' + settingsKey, {},
function (result)
function(result)
{
if (reloadPageOnSuccess)
{
location.reload();
}
},
function (xhr)
function(xhr)
{
if (xhr.statusText)
{
@ -463,7 +463,7 @@ Grocy.FrontendHelpers.DeleteUserSetting = function (settingsKey, reloadPageOnSuc
);
}
Grocy.FrontendHelpers.RunWebhook = function (webhook, data, repetitions = 1)
Grocy.FrontendHelpers.RunWebhook = function(webhook, data, repetitions = 1)
{
Object.assign(data, webhook.extra_data);
var hasAlreadyFailed = false;
@ -472,7 +472,7 @@ Grocy.FrontendHelpers.RunWebhook = function (webhook, data, repetitions = 1)
{
if (webhook.json)
{
$.ajax(webhook.hook, { "data": JSON.stringify(data), "contentType": "application/json", "type": "POST" }).fail(function (req, status, errorThrown)
$.ajax(webhook.hook, { "data": JSON.stringify(data), "contentType": "application/json", "type": "POST" }).fail(function(req, status, errorThrown)
{
if (!hasAlreadyFailed)
{
@ -483,7 +483,7 @@ Grocy.FrontendHelpers.RunWebhook = function (webhook, data, repetitions = 1)
}
else
{
$.post(webhook.hook, data).fail(function (req, status, errorThrown)
$.post(webhook.hook, data).fail(function(req, status, errorThrown)
{
if (!hasAlreadyFailed)
{
@ -495,13 +495,17 @@ Grocy.FrontendHelpers.RunWebhook = function (webhook, data, repetitions = 1)
}
}
$(document).on("keyup paste change click", "input, select, textarea", function ()
$(document).on("keyup paste change", "input, textarea", function()
{
$(this).addClass("is-dirty").closest("form").addClass("is-dirty");
});
$(document).on("click", "select", function()
{
$(this).addClass("is-dirty").closest("form").addClass("is-dirty");
});
// Auto saving user setting controls
$(document).on("change", ".user-setting-control", function ()
$(document).on("change", ".user-setting-control", function()
{
var element = $(this);
var settingKey = element.attr("data-setting-key");
@ -530,7 +534,7 @@ $(document).on("change", ".user-setting-control", function ()
});
// Show file name Bootstrap custom file input
$('input.custom-file-input').on('change', function ()
$('input.custom-file-input').on('change', function()
{
$(this).next('.custom-file-label').html(GetFileNameFromPath($(this).val()));
});
@ -541,9 +545,9 @@ if ($(".custom-file-label").length > 0)
$("<style>").html('.custom-file-label::after { content: "' + __t("Select file") + '"; }').appendTo("head");
}
ResizeResponsiveEmbeds = function ()
ResizeResponsiveEmbeds = function()
{
$("iframe.embed-responsive").each(function ()
$("iframe.embed-responsive").each(function()
{
var iframeBody = $(this)[0].contentWindow.document.body;
if (iframeBody)
@ -564,25 +568,25 @@ ResizeResponsiveEmbeds = function ()
}
$("embed.embed-responsive:not(.resize-done)").attr("height", maxHeight.toString() + "px").addClass("resize-done");
}
$(window).on("resize", function ()
$(window).on("resize", function()
{
ResizeResponsiveEmbeds();
});
$("iframe").on("load", function ()
$("iframe").on("load", function()
{
ResizeResponsiveEmbeds();
});
$(document).on("shown.bs.modal", function (e)
$(document).on("shown.bs.modal", function(e)
{
ResizeResponsiveEmbeds();
});
$(document).on("hidden.bs.modal", function (e)
$(document).on("hidden.bs.modal", function(e)
{
$("body").removeClass("fullscreen-card");
});
$("body").children().each(function (index, child)
$("body").children().each(function(index, child)
{
new ResizeObserver(function ()
new ResizeObserver(function()
{
window.parent.postMessage(WindowMessageBag("ResizeResponsiveEmbeds"), Grocy.BaseUrl);
}).observe(child);
@ -604,7 +608,7 @@ if (window.location.hash)
function RefreshLocaleNumberDisplay(rootSelector = "#page-content")
{
$(rootSelector + " .locale-number.locale-number-currency:not('.number-parsing-done')").each(function ()
$(rootSelector + " .locale-number.locale-number-currency:not('.number-parsing-done')").each(function()
{
var element = $(this);
var text = element.text();
@ -618,7 +622,7 @@ function RefreshLocaleNumberDisplay(rootSelector = "#page-content")
element.addClass("number-parsing-done");
});
$(rootSelector + " .locale-number.locale-number-quantity-amount:not('.number-parsing-done')").each(function ()
$(rootSelector + " .locale-number.locale-number-quantity-amount:not('.number-parsing-done')").each(function()
{
var element = $(this);
var text = element.text();
@ -632,7 +636,7 @@ function RefreshLocaleNumberDisplay(rootSelector = "#page-content")
element.addClass("number-parsing-done");
});
$(rootSelector + " .locale-number.locale-number-generic:not('.number-parsing-done')").each(function ()
$(rootSelector + " .locale-number.locale-number-generic:not('.number-parsing-done')").each(function()
{
var element = $(this);
var text = element.text();
@ -647,9 +651,9 @@ function RefreshLocaleNumberDisplay(rootSelector = "#page-content")
});
}
RefreshLocaleNumberDisplay();
$(".locale-number").each(function ()
$(".locale-number").each(function()
{
new MutationObserver(function (mutations)
new MutationObserver(function(mutations)
{
mutations.forEach(mutation =>
{
@ -667,7 +671,7 @@ $(".locale-number").each(function ()
function RefreshLocaleNumberInput(rootSelector = "#page-content")
{
$(rootSelector + " .locale-number-input.locale-number-currency").each(function ()
$(rootSelector + " .locale-number-input.locale-number-currency").each(function()
{
var element = $(this);
var value = element.val();
@ -679,7 +683,7 @@ function RefreshLocaleNumberInput(rootSelector = "#page-content")
element.val(Number.parseFloat(value).toLocaleString("en", { minimumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices_input, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices_input, useGrouping: false }));
});
$(rootSelector + " .locale-number-input.locale-number-quantity-amount").each(function ()
$(rootSelector + " .locale-number-input.locale-number-quantity-amount").each(function()
{
var element = $(this);
var value = element.val();
@ -691,7 +695,7 @@ function RefreshLocaleNumberInput(rootSelector = "#page-content")
element.val(Number.parseFloat(value).toLocaleString("en", { minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts, useGrouping: false }));
});
$(rootSelector + " .locale-number-input.locale-number-generic").each(function ()
$(rootSelector + " .locale-number-input.locale-number-generic").each(function()
{
var element = $(this);
var value = element.val();
@ -705,7 +709,7 @@ function RefreshLocaleNumberInput(rootSelector = "#page-content")
}
RefreshLocaleNumberInput();
$(document).on("click", ".easy-link-copy-textbox", function ()
$(document).on("click", ".easy-link-copy-textbox", function()
{
$(this).select();
});
@ -729,12 +733,12 @@ if (GetUriParam("embedded"))
</div>');
}
$(document).on("click", ".close-last-modal-button", function ()
$(document).on("click", ".close-last-modal-button", function()
{
window.parent.postMessage(WindowMessageBag("CloseLastModal"), Grocy.BaseUrl);
});
$("body").on("keydown", function (e)
$("body").on("keydown", function(e)
{
if (e.key == "Escape")
{
@ -743,7 +747,7 @@ $("body").on("keydown", function (e)
});
$(window).on("message", function (e)
$(window).on("message", function(e)
{
var data = e.originalEvent.data;
@ -775,7 +779,7 @@ $(window).on("message", function (e)
window.postMessage(data.Payload, Grocy.BaseUrl);
// => Bubble the broadcast message down to all child iframes
$("iframe.embed-responsive").each(function ()
$("iframe.embed-responsive").each(function()
{
$(this)[0].contentWindow.postMessage(data, Grocy.BaseUrl);
});
@ -783,7 +787,7 @@ $(window).on("message", function (e)
});
window.IsGrocy = true;
Grocy.GetTopmostWindow = function ()
Grocy.GetTopmostWindow = function()
{
if (window.top.IsGrocy)
{
@ -810,7 +814,7 @@ Grocy.GetTopmostWindow = function ()
}
}
$(document).on("click", ".show-as-dialog-link", function (e)
$(document).on("click", ".show-as-dialog-link", function(e)
{
e.preventDefault();
@ -850,7 +854,7 @@ $('[data-toggle="tooltip"]').tooltip();
// serializeJSON defaults
$.serializeJSON.defaultOptions.checkboxUncheckedValue = "0";
$(Grocy.UserPermissions).each(function (index, item)
$(Grocy.UserPermissions).each(function(index, item)
{
if (item.has_permission == 0)
{
@ -858,7 +862,7 @@ $(Grocy.UserPermissions).each(function (index, item)
}
});
$('a.link-return').not(".btn").each(function ()
$('a.link-return').not(".btn").each(function()
{
var base = $(this).data('href');
if (base.contains('?'))
@ -871,7 +875,7 @@ $('a.link-return').not(".btn").each(function ()
}
});
$(document).on("click", "a.btn.link-return", function (e)
$(document).on("click", "a.btn.link-return", function(e)
{
e.preventDefault();
@ -886,7 +890,7 @@ $(document).on("click", "a.btn.link-return", function (e)
}
});
$('.dropdown-item').has('.form-check input[type=checkbox]').on('click', function (e)
$('.dropdown-item').has('.form-check input[type=checkbox]').on('click', function(e)
{
if ($(e.target).is('div.form-check') || $(e.target).is('div.dropdown-item'))
{
@ -894,12 +898,12 @@ $('.dropdown-item').has('.form-check input[type=checkbox]').on('click', function
}
});
$('[data-toggle="tooltip"][data-html="true"]').on("shown.bs.tooltip", function ()
$('[data-toggle="tooltip"][data-html="true"]').on("shown.bs.tooltip", function()
{
RefreshLocaleNumberDisplay(".tooltip");
})
$(document).on("click", '.btn, a, button', function (e)
$(document).on("click", '.btn, a, button', function(e)
{
// Remove focus and hide any tooltips after click
document.activeElement.blur();
@ -908,7 +912,7 @@ $(document).on("click", '.btn, a, button', function (e)
// Delay only initial field focus
Grocy.FormFocusDelay = 500;
setTimeout(function ()
setTimeout(function()
{
Grocy.FormFocusDelay = 0;
}, 1000);

View File

@ -1,4 +1,4 @@
setTimeout(function ()
setTimeout(function()
{
$('#username').focus();
}, Grocy.FormFocusDelay);
@ -8,11 +8,3 @@ if (GetUriParam('invalid') === 'true')
$('#login-error').text(__t('Invalid credentials, please try again'));
$('#login-error').removeClass('d-none');
}
$("#login-button").on("click", function (e)
{
e.preventDefault();
$("#password_base64").val(btoa($("#password_input").val()));
$("#login-form").trigger("submit");
});

View File

@ -1,6 +1,6 @@
var CurrentProductDetails;
$('#save-purchase-button').on('click', function (e)
$('#save-purchase-button').on('click', function(e)
{
e.preventDefault();
@ -24,7 +24,7 @@ $('#save-purchase-button').on('click', function (e)
Grocy.FrontendHelpers.BeginUiBusy("purchase-form");
Grocy.Api.Get('stock/products/' + jsonForm.product_id,
function (productDetails)
function(productDetails)
{
var jsonData = {};
jsonData.amount = jsonForm.amount;
@ -76,14 +76,14 @@ $('#save-purchase-button').on('click', function (e)
}
Grocy.Api.Post('stock/products/' + jsonForm.product_id + '/add', jsonData,
function (result)
function(result)
{
if ($("#purchase-form").hasAttr("data-used-barcode"))
{
Grocy.Api.Put('objects/product_barcodes/' + $("#purchase-form").attr("data-used-barcode"), { last_price: $("#price").val() },
function (result)
function(result)
{ },
function (xhr)
function(xhr)
{ }
);
}
@ -104,14 +104,14 @@ $('#save-purchase-button').on('click', function (e)
jsonDataBarcode.note = jsonForm.note;
Grocy.Api.Post('objects/product_barcodes', jsonDataBarcode,
function (result)
function(result)
{
$("#flow-info-InplaceAddBarcodeToExistingProduct").addClass("d-none");
$('#barcode-lookup-disabled-hint').addClass('d-none');
$('#barcode-lookup-hint').removeClass('d-none');
window.history.replaceState({}, document.title, U("/purchase"));
},
function (xhr)
function(xhr)
{
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
@ -145,7 +145,7 @@ $('#save-purchase-button').on('click', function (e)
else if (jsonForm.stock_label_type == 2) // Label per unit
{
Grocy.Api.Get('stock/transactions/' + result[0].transaction_id,
function (stockEntries)
function(stockEntries)
{
stockEntries.forEach(stockEntry =>
{
@ -160,7 +160,7 @@ $('#save-purchase-button').on('click', function (e)
Grocy.FrontendHelpers.RunWebhook(Grocy.Webhooks.labelprinter, webhookData);
});
},
function (xhr)
function(xhr)
{
console.error(xhr);
}
@ -172,7 +172,7 @@ $('#save-purchase-button').on('click', function (e)
Grocy.EditObjectId = result[0].transaction_id;
if (GetUriParam("embedded") !== undefined)
{
Grocy.Components.UserfieldsForm.Save(function ()
Grocy.Components.UserfieldsForm.Save(function()
{
Grocy.GetTopmostWindow().postMessage(WindowMessageBag("BroadcastMessage", WindowMessageBag("ProductChanged", jsonForm.product_id)), Grocy.BaseUrl);
window.parent.postMessage(WindowMessageBag("AfterItemAdded", GetUriParam("listitemid")), Grocy.BaseUrl);
@ -187,7 +187,7 @@ $('#save-purchase-button').on('click', function (e)
}
else
{
Grocy.Components.UserfieldsForm.Save(function ()
Grocy.Components.UserfieldsForm.Save(function()
{
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
toastr.success(successMessage);
@ -239,14 +239,14 @@ $('#save-purchase-button').on('click', function (e)
});
}
},
function (xhr)
function(xhr)
{
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
console.error(xhr);
}
);
},
function (xhr)
function(xhr)
{
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
console.error(xhr);
@ -256,7 +256,7 @@ $('#save-purchase-button').on('click', function (e)
if (Grocy.Components.ProductPicker !== undefined)
{
Grocy.Components.ProductPicker.GetPicker().on('change', function (e)
Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
{
if (BoolVal(Grocy.UserSettings.scan_mode_purchase_enabled))
{
@ -270,7 +270,7 @@ if (Grocy.Components.ProductPicker !== undefined)
Grocy.Components.ProductCard.Refresh(productId);
Grocy.Api.Get('stock/products/' + productId,
function (productDetails)
function(productDetails)
{
CurrentProductDetails = productDetails;
@ -356,7 +356,7 @@ if (Grocy.Components.ProductPicker !== undefined)
$("#price-type-total-price").click();
}
setTimeout(function ()
setTimeout(function()
{
$('#display_amount').focus();
}, Grocy.FormFocusDelay);
@ -372,7 +372,7 @@ if (Grocy.Components.ProductPicker !== undefined)
if (document.getElementById("product_id").getAttribute("barcode") != "null")
{
Grocy.Api.Get('objects/product_barcodes_view?query[]=barcode=' + document.getElementById("product_id").getAttribute("barcode"),
function (barcodeResult)
function(barcodeResult)
{
if (barcodeResult && barcodeResult.length > 0)
{
@ -416,7 +416,7 @@ if (Grocy.Components.ProductPicker !== undefined)
ScanModeSubmit(false);
},
function (xhr)
function(xhr)
{
console.error(xhr);
}
@ -430,7 +430,7 @@ if (Grocy.Components.ProductPicker !== undefined)
$('#display_amount').trigger("keyup");
},
function (xhr)
function(xhr)
{
console.error(xhr);
}
@ -441,81 +441,52 @@ if (Grocy.Components.ProductPicker !== undefined)
function PrefillBestBeforeDate(product, location)
{
if (!Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
{
return;
}
if (location == null)
{
location = {}
}
var shortcutValue = $("#datetimepicker-shortcut").attr("data-datetimepicker-shortcut-value");
var dueDateCurrent = Grocy.Components.DateTimePicker.GetValue();
var dueDateDefault = null;
var dueDateFreezer = null;
if (product.default_best_before_days != 0)
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
{
dueDateDefault = moment().add(product.default_best_before_days, 'days').format('YYYY-MM-DD');
if (product.default_best_before_days == -1)
var dueDays;
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRODUCT_FREEZING && BoolVal(location.is_freezer))
{
dueDateDefault = shortcutValue;
}
}
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRODUCT_FREEZING && BoolVal(location.is_freezer) && product.default_best_before_days_after_freezing != 0)
{
dueDateFreezer = moment().add(product.default_best_before_days_after_freezing, 'days').format('YYYY-MM-DD');
if (product.default_best_before_days_after_freezing == -1)
{
dueDateFreezer = shortcutValue;
}
}
// Set the default due date when currently no one is set
if (dueDateDefault && !dueDateCurrent)
{
if (!$("#datetimepicker-shortcut").is(":checked") && dueDateDefault == shortcutValue)
{
$("#datetimepicker-shortcut").click();
dueDays = product.default_best_before_days_after_freezing;
}
else
{
Grocy.Components.DateTimePicker.SetValue(dueDateDefault);
dueDays = product.default_best_before_days;
}
}
// Set the default due date after freezing when currently no one is set or when it was previously set to the default due date
// (so essentially don't overwrite a by the user different entered due date)
if (dueDateFreezer && (!dueDateCurrent || dueDateCurrent == dueDateDefault))
{
if (!$("#datetimepicker-shortcut").is(":checked") && dueDateFreezer == shortcutValue)
if (dueDays != 0)
{
$("#datetimepicker-shortcut").click();
}
else
{
Grocy.Components.DateTimePicker.SetValue(dueDateFreezer);
if (dueDays == -1)
{
if (!$("#datetimepicker-shortcut").is(":checked"))
{
$("#datetimepicker-shortcut").click();
}
}
else
{
Grocy.Components.DateTimePicker.SetValue(moment().add(dueDays, 'days').format('YYYY-MM-DD'));
}
}
}
}
if (Grocy.Components.LocationPicker !== undefined)
{
Grocy.Components.LocationPicker.GetPicker().on('change', function (e)
Grocy.Components.LocationPicker.GetPicker().on('change', function(e)
{
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRODUCT_FREEZING)
{
Grocy.Api.Get('objects/locations/' + Grocy.Components.LocationPicker.GetValue(),
function (location)
function(location)
{
PrefillBestBeforeDate(CurrentProductDetails.product, location);
},
function (xhr)
function(xhr)
{ }
);
}
@ -531,7 +502,7 @@ if (Grocy.Components.ProductPicker)
{
if (Grocy.Components.ProductPicker.InAnyFlow() === false && GetUriParam("embedded") === undefined)
{
setTimeout(function ()
setTimeout(function()
{
Grocy.Components.ProductPicker.GetInputElement().focus();
}, Grocy.FormFocusDelay);
@ -542,7 +513,7 @@ if (Grocy.Components.ProductPicker)
if (Grocy.Components.ProductPicker.InProductModifyWorkflow())
{
setTimeout(function ()
setTimeout(function()
{
Grocy.Components.ProductPicker.GetInputElement().focus();
}, Grocy.FormFocusDelay);
@ -550,11 +521,11 @@ if (Grocy.Components.ProductPicker)
}
}
$('#display_amount').on('focus', function (e)
$('#display_amount').on('focus', function(e)
{
if (Grocy.Components.ProductPicker.GetValue().length === 0)
{
setTimeout(function ()
setTimeout(function()
{
Grocy.Components.ProductPicker.GetInputElement().focus();
}, Grocy.FormFocusDelay);
@ -565,17 +536,17 @@ $('#display_amount').on('focus', function (e)
}
});
$('#price').on('focus', function (e)
$('#price').on('focus', function(e)
{
$(this).select();
});
$('#purchase-form input').keyup(function (event)
$('#purchase-form input').keyup(function(event)
{
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});
$('#purchase-form input').keydown(function (event)
$('#purchase-form input').keydown(function(event)
{
if (event.keyCode === 13) // Enter
{
@ -594,12 +565,12 @@ $('#purchase-form input').keydown(function (event)
if (Grocy.Components.DateTimePicker)
{
Grocy.Components.DateTimePicker.GetInputElement().on('change', function (e)
Grocy.Components.DateTimePicker.GetInputElement().on('change', function(e)
{
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});
Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function (e)
Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e)
{
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});
@ -607,12 +578,12 @@ if (Grocy.Components.DateTimePicker)
if (Grocy.Components.DateTimePicker2)
{
Grocy.Components.DateTimePicker2.GetInputElement().on('change', function (e)
Grocy.Components.DateTimePicker2.GetInputElement().on('change', function(e)
{
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});
Grocy.Components.DateTimePicker2.GetInputElement().on('keypress', function (e)
Grocy.Components.DateTimePicker2.GetInputElement().on('keypress', function(e)
{
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});
@ -620,22 +591,22 @@ if (Grocy.Components.DateTimePicker2)
Grocy.Components.DateTimePicker2.GetInputElement().trigger("input");
}
$('#price').on('keyup', function (e)
$('#price').on('keyup', function(e)
{
RefreshPriceHint();
});
$('#price-type-unit-price').on('change', function (e)
$('#price-type-unit-price').on('change', function(e)
{
RefreshPriceHint();
});
$('#price-type-total-price').on('change', function (e)
$('#price-type-total-price').on('change', function(e)
{
RefreshPriceHint();
});
$('#display_amount').on('change', function (e)
$('#display_amount').on('change', function(e)
{
RefreshPriceHint();
Grocy.FrontendHelpers.ValidateForm('purchase-form');
@ -674,22 +645,22 @@ function RefreshPriceHint()
function UndoStockBooking(bookingId)
{
Grocy.Api.Post('stock/bookings/' + bookingId.toString() + '/undo', {},
function (result)
function(result)
{
toastr.success(__t("Booking successfully undone"));
Grocy.Api.Get('stock/bookings/' + bookingId.toString(),
function (result)
function(result)
{
Grocy.GetTopmostWindow().postMessage(WindowMessageBag("BroadcastMessage", WindowMessageBag("ProductChanged", result.product_id)), Grocy.BaseUrl);
},
function (xhr)
function(xhr)
{
console.error(xhr);
}
);
},
function (xhr)
function(xhr)
{
console.error(xhr);
}
@ -699,29 +670,29 @@ function UndoStockBooking(bookingId)
function UndoStockTransaction(transactionId)
{
Grocy.Api.Post('stock/transactions/' + transactionId.toString() + '/undo', {},
function (result)
function(result)
{
toastr.success(__t("Transaction successfully undone"));
Grocy.Api.Get('stock/transactions/' + transactionId.toString(),
function (result)
function(result)
{
Grocy.GetTopmostWindow().postMessage(WindowMessageBag("BroadcastMessage", WindowMessageBag("ProductChanged", result[0].product_id)), Grocy.BaseUrl);
},
function (xhr)
function(xhr)
{
console.error(xhr);
}
);
},
function (xhr)
function(xhr)
{
console.error(xhr);
}
);
};
$("#scan-mode").on("change", function (e)
$("#scan-mode").on("change", function(e)
{
if ($(this).prop("checked"))
{
@ -729,7 +700,7 @@ $("#scan-mode").on("change", function (e)
}
});
$("#scan-mode-button").on("click", function (e)
$("#scan-mode-button").on("click", function(e)
{
$("#scan-mode").click();
$("#scan-mode-button").toggleClass("btn-success").toggleClass("btn-danger");
@ -743,7 +714,7 @@ $("#scan-mode-button").on("click", function (e)
}
});
$('#qu_id').on('change', function (e)
$('#qu_id').on('change', function(e)
{
var priceTypeUnitPrice = $("#price-type-unit-price");
var priceTypeUnitPriceLabel = $("[for=" + priceTypeUnitPrice.attr("id") + "]");
@ -776,7 +747,7 @@ function ScanModeSubmit(singleUnit = true)
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_LABEL_PRINTER)
{
$("#stock_label_type, #amount").on("change", function (e)
$("#stock_label_type, #amount").on("change", function(e)
{
if ($("#stock_label_type").val() == 2)
{

View File

@ -24,7 +24,7 @@
});
}
$('#save-user-button').on('click', function (e)
$('#save-user-button').on('click', function(e)
{
e.preventDefault();
@ -46,16 +46,11 @@ $('#save-user-button').on('click', function (e)
jsonData.picture_file_name = RandomString() + CleanFileName($("#user-picture")[0].files[0].name);
}
jsonData.password_base64 = btoa(jsonData.password);
delete jsonData.password;
delete jsonData.password_confirm;
delete jsonData.change_password;
if (Grocy.EditMode === 'create')
{
Grocy.Api.Post('users', jsonData,
(result) => SaveUserPicture(result, jsonData),
function (xhr)
function(xhr)
{
Grocy.FrontendHelpers.EndUiBusy("user-form");
console.error(xhr);
@ -69,11 +64,11 @@ $('#save-user-button').on('click', function (e)
jsonData.picture_file_name = null;
Grocy.Api.DeleteFile(Grocy.UserPictureFileName, 'userpictures',
function (result)
function(result)
{
// Nothing to do
},
function (xhr)
function(xhr)
{
Grocy.FrontendHelpers.EndUiBusy("user-form");
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response);
@ -83,7 +78,7 @@ $('#save-user-button').on('click', function (e)
Grocy.Api.Put('users/' + Grocy.EditObjectId, jsonData,
(result) => SaveUserPicture(result, jsonData),
function (xhr)
function(xhr)
{
Grocy.FrontendHelpers.EndUiBusy("user-form");
console.error(xhr);
@ -92,7 +87,7 @@ $('#save-user-button').on('click', function (e)
}
});
$('#user-form input').keyup(function (event)
$('#user-form input').keyup(function(event)
{
var element = document.getElementById("password_confirm");
if ($("#password").val() !== $("#password_confirm").val())
@ -107,7 +102,7 @@ $('#user-form input').keyup(function (event)
Grocy.FrontendHelpers.ValidateForm('user-form');
});
$('#user-form input').keydown(function (event)
$('#user-form input').keydown(function(event)
{
if (event.keyCode === 13) // Enter
{
@ -124,7 +119,7 @@ $('#user-form input').keydown(function (event)
}
});
$("#user-picture").on("change", function (e)
$("#user-picture").on("change", function(e)
{
$("#user-picture-label").removeClass("d-none");
$("#user-picture-label-none").addClass("d-none");
@ -134,7 +129,7 @@ $("#user-picture").on("change", function (e)
});
Grocy.DeleteUserPictureOnSave = false;
$("#delete-current-user-picture-button").on("click", function (e)
$("#delete-current-user-picture-button").on("click", function(e)
{
Grocy.DeleteUserPictureOnSave = true;
$("#current-user-picture").addClass("d-none");
@ -143,12 +138,12 @@ $("#delete-current-user-picture-button").on("click", function (e)
$("#user-picture-label-none").removeClass("d-none");
});
$("#change_password").click(function ()
$("#change_password").click(function()
{
$("#password").attr("disabled", !this.checked);
$("#password_confirm").attr("disabled", !this.checked);
setTimeout(function ()
setTimeout(function()
{
$("#password").focus();
}, Grocy.FormFocusDelay);
@ -160,7 +155,7 @@ if (GetUriParam("changepw") === "true")
}
else
{
setTimeout(function ()
setTimeout(function()
{
$('#username').focus();
}, Grocy.FormFocusDelay);

View File

@ -463,8 +463,7 @@ class StockService extends BaseService
'transaction_id' => $transactionId,
'user_id' => GROCY_USER_ID,
'location_id' => $stockEntry->location_id,
'note' => $stockEntry->note,
'shopping_location_id' => $stockEntry->shopping_location_id
'note' => $stockEntry->note
]);
$logRow->save();
@ -499,8 +498,7 @@ class StockService extends BaseService
'transaction_id' => $transactionId,
'user_id' => GROCY_USER_ID,
'location_id' => $stockEntry->location_id,
'note' => $stockEntry->note,
'shopping_location_id' => $stockEntry->shopping_location_id
'note' => $stockEntry->note
]);
$logRow->save();
@ -1534,8 +1532,7 @@ class StockService extends BaseService
'opened_date' => $logRow->opened_date,
'open' => $logRow->opened_date !== null,
'location_id' => $logRow->location_id,
'note' => $logRow->note,
'shopping_location_id' => $logRow->shopping_location_id
'note' => $logRow->note
]);
$stockRow->save();
@ -1586,8 +1583,7 @@ class StockService extends BaseService
'stock_id' => $logRow->stock_id,
'price' => $logRow->price,
'opened_date' => $logRow->opened_date,
'note' => $logRow->note,
'shopping_location_id' => $logRow->shopping_location_id
'note' => $logRow->note
]);
$stockRow->save();
}

View File

@ -12,7 +12,7 @@ class UsersService extends BaseService
'username' => $username,
'first_name' => $firstName,
'last_name' => $lastName,
'password' => password_hash($password, PASSWORD_ARGON2ID),
'password' => password_hash($password, PASSWORD_DEFAULT),
'picture_file_name' => $pictureFileName
]);
$newUserRow = $newUserRow->save();
@ -61,7 +61,7 @@ class UsersService extends BaseService
'username' => $username,
'first_name' => $firstName,
'last_name' => $lastName,
'password' => password_hash($password, PASSWORD_ARGON2ID),
'password' => password_hash($password, PASSWORD_DEFAULT),
'picture_file_name' => $pictureFileName
]);
}

View File

@ -23,16 +23,13 @@
name="username">
</div>
<input type="hidden"
id="password_base64"
name="password_base64">
<div class="form-group">
<label for="password_input">{{ $__t('Password') }}</label>
<label for="password">{{ $__t('Password') }}</label>
<input type="password"
class="form-control"
required
id="password_input">
id="password"
name="password">
<div id="login-error"
class="form-text text-danger d-none"></div>
</div>