Fixed all (or most of) the broken stuff after the dependency upgrade party

This commit is contained in:
Bernd Bestel 2018-07-11 19:43:05 +02:00
parent 71701804ea
commit 778191fd11
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
51 changed files with 553 additions and 498 deletions

137
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "42031c0b205b7ce7efb4b6eb95a0096a",
"content-hash": "131ab83ecb1ea3d1a431cc70b5092448",
"packages": [
{
"name": "container-interop/container-interop",
@ -158,16 +158,16 @@
},
{
"name": "illuminate/container",
"version": "v5.6.17",
"version": "v5.6.27",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
"reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a"
"reference": "1f0757cae8749400aeda730f6438a081fc3c082d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/container/zipball/4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a",
"reference": "4a42d667a05ec6d31f05b532cdac7e8e68e5ea2a",
"url": "https://api.github.com/repos/illuminate/container/zipball/1f0757cae8749400aeda730f6438a081fc3c082d",
"reference": "1f0757cae8749400aeda730f6438a081fc3c082d",
"shasum": ""
},
"require": {
@ -198,20 +198,20 @@
],
"description": "The Illuminate Container package.",
"homepage": "https://laravel.com",
"time": "2018-01-21T02:13:38+00:00"
"time": "2018-05-24T13:16:56+00:00"
},
{
"name": "illuminate/contracts",
"version": "v5.6.17",
"version": "v5.6.27",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "322ec80498b3bf85bc4025d028e130a9b50242b9"
"reference": "3dc639feabe0f302f574157a782ede323881a944"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/322ec80498b3bf85bc4025d028e130a9b50242b9",
"reference": "322ec80498b3bf85bc4025d028e130a9b50242b9",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/3dc639feabe0f302f574157a782ede323881a944",
"reference": "3dc639feabe0f302f574157a782ede323881a944",
"shasum": ""
},
"require": {
@ -242,11 +242,11 @@
],
"description": "The Illuminate Contracts package.",
"homepage": "https://laravel.com",
"time": "2018-04-07T17:05:26+00:00"
"time": "2018-05-11T23:38:58+00:00"
},
{
"name": "illuminate/events",
"version": "v5.6.17",
"version": "v5.6.27",
"source": {
"type": "git",
"url": "https://github.com/illuminate/events.git",
@ -291,16 +291,16 @@
},
{
"name": "illuminate/filesystem",
"version": "v5.6.17",
"version": "v5.6.27",
"source": {
"type": "git",
"url": "https://github.com/illuminate/filesystem.git",
"reference": "c9ab9376076cedd88a374d7281d62b619634d578"
"reference": "2677365f61c66fad13ff12a37cd4fa8aaeb048d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/filesystem/zipball/c9ab9376076cedd88a374d7281d62b619634d578",
"reference": "c9ab9376076cedd88a374d7281d62b619634d578",
"url": "https://api.github.com/repos/illuminate/filesystem/zipball/2677365f61c66fad13ff12a37cd4fa8aaeb048d2",
"reference": "2677365f61c66fad13ff12a37cd4fa8aaeb048d2",
"shasum": ""
},
"require": {
@ -339,20 +339,20 @@
],
"description": "The Illuminate Filesystem package.",
"homepage": "https://laravel.com",
"time": "2018-04-06T13:15:37+00:00"
"time": "2018-07-07T14:54:27+00:00"
},
{
"name": "illuminate/support",
"version": "v5.6.17",
"version": "v5.6.27",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
"reference": "cc8d6f5cef3a901de6bb7d1b362102a6db001085"
"reference": "97ca44c95392ce0a41749fa47b953734d88b94b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/cc8d6f5cef3a901de6bb7d1b362102a6db001085",
"reference": "cc8d6f5cef3a901de6bb7d1b362102a6db001085",
"url": "https://api.github.com/repos/illuminate/support/zipball/97ca44c95392ce0a41749fa47b953734d88b94b1",
"reference": "97ca44c95392ce0a41749fa47b953734d88b94b1",
"shasum": ""
},
"require": {
@ -367,6 +367,7 @@
},
"suggest": {
"illuminate/filesystem": "Required to use the composer class (5.6.*).",
"ramsey/uuid": "Required to use Str::uuid() (^3.7).",
"symfony/process": "Required to use the composer class (~4.0).",
"symfony/var-dumper": "Required to use the dd function (~4.0)."
},
@ -396,20 +397,20 @@
],
"description": "The Illuminate Support package.",
"homepage": "https://laravel.com",
"time": "2018-04-17T12:26:47+00:00"
"time": "2018-07-04T01:23:57+00:00"
},
{
"name": "illuminate/view",
"version": "v5.6.17",
"version": "v5.6.27",
"source": {
"type": "git",
"url": "https://github.com/illuminate/view.git",
"reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d"
"reference": "625c35e8942f0ecd467acb8db8daf8449390d559"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/view/zipball/54eaf45ee7946d8f8cde13d5e89c5ea2e997040d",
"reference": "54eaf45ee7946d8f8cde13d5e89c5ea2e997040d",
"url": "https://api.github.com/repos/illuminate/view/zipball/625c35e8942f0ecd467acb8db8daf8449390d559",
"reference": "625c35e8942f0ecd467acb8db8daf8449390d559",
"shasum": ""
},
"require": {
@ -444,7 +445,7 @@
],
"description": "The Illuminate View package.",
"homepage": "https://laravel.com",
"time": "2018-04-03T12:56:35+00:00"
"time": "2018-07-06T14:55:12+00:00"
},
{
"name": "morris/lessql",
@ -496,16 +497,16 @@
},
{
"name": "neomerx/cors-psr7",
"version": "v1.0.12",
"version": "v1.0.13",
"source": {
"type": "git",
"url": "https://github.com/neomerx/cors-psr7.git",
"reference": "24944f39483d1a89f66ae9d58cca9f82b8815b35"
"reference": "2556e2013f16a55532c95928455257d5b6bbc6e2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/neomerx/cors-psr7/zipball/24944f39483d1a89f66ae9d58cca9f82b8815b35",
"reference": "24944f39483d1a89f66ae9d58cca9f82b8815b35",
"url": "https://api.github.com/repos/neomerx/cors-psr7/zipball/2556e2013f16a55532c95928455257d5b6bbc6e2",
"reference": "2556e2013f16a55532c95928455257d5b6bbc6e2",
"shasum": ""
},
"require": {
@ -514,7 +515,7 @@
"psr/log": "^1.0"
},
"require-dev": {
"mockery/mockery": "^0.9.9",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^5.7",
"scrutinizer/ocular": "^1.1",
"squizlabs/php_codesniffer": "^3.0"
@ -547,20 +548,20 @@
"w3.org",
"www.w3.org"
],
"time": "2017-09-03T22:31:57+00:00"
"time": "2018-05-23T16:10:11+00:00"
},
{
"name": "nesbot/carbon",
"version": "1.26.4",
"version": "1.32.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "e3d9014279133a3cccc01f6a691322a2d5a6a87b"
"reference": "64563e2b9f69e4db1b82a60e81efa327a30ff343"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/e3d9014279133a3cccc01f6a691322a2d5a6a87b",
"reference": "e3d9014279133a3cccc01f6a691322a2d5a6a87b",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/64563e2b9f69e4db1b82a60e81efa327a30ff343",
"reference": "64563e2b9f69e4db1b82a60e81efa327a30ff343",
"shasum": ""
},
"require": {
@ -572,6 +573,13 @@
"phpunit/phpunit": "^4.8.35 || ^5.7"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Carbon\\Laravel\\ServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"": "src/"
@ -595,7 +603,7 @@
"datetime",
"time"
],
"time": "2018-04-17T15:35:42+00:00"
"time": "2018-07-05T06:59:26+00:00"
},
{
"name": "nikic/fast-route",
@ -1206,16 +1214,16 @@
},
{
"name": "symfony/debug",
"version": "v4.0.8",
"version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "5961d02d48828671f5d8a7805e06579d692f6ede"
"reference": "dbe0fad88046a755dcf9379f2964c61a02f5ae3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/5961d02d48828671f5d8a7805e06579d692f6ede",
"reference": "5961d02d48828671f5d8a7805e06579d692f6ede",
"url": "https://api.github.com/repos/symfony/debug/zipball/dbe0fad88046a755dcf9379f2964c61a02f5ae3d",
"reference": "dbe0fad88046a755dcf9379f2964c61a02f5ae3d",
"shasum": ""
},
"require": {
@ -1231,7 +1239,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
"dev-master": "4.1-dev"
}
},
"autoload": {
@ -1258,20 +1266,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2018-04-03T05:24:00+00:00"
"time": "2018-06-08T09:39:36+00:00"
},
{
"name": "symfony/finder",
"version": "v4.0.8",
"version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49"
"reference": "84714b8417d19e4ba02ea78a41a975b3efaafddb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
"reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
"url": "https://api.github.com/repos/symfony/finder/zipball/84714b8417d19e4ba02ea78a41a975b3efaafddb",
"reference": "84714b8417d19e4ba02ea78a41a975b3efaafddb",
"shasum": ""
},
"require": {
@ -1280,7 +1288,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
"dev-master": "4.1-dev"
}
},
"autoload": {
@ -1307,20 +1315,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2018-04-04T05:10:37+00:00"
"time": "2018-06-19T21:38:16+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.7.0",
"version": "v1.8.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b"
"reference": "3296adf6a6454a050679cde90f95350ad604b171"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b",
"reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171",
"reference": "3296adf6a6454a050679cde90f95350ad604b171",
"shasum": ""
},
"require": {
@ -1332,7 +1340,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.7-dev"
"dev-master": "1.8-dev"
}
},
"autoload": {
@ -1366,20 +1374,20 @@
"portable",
"shim"
],
"time": "2018-01-30T19:27:44+00:00"
"time": "2018-04-26T10:06:28+00:00"
},
{
"name": "symfony/translation",
"version": "v4.0.8",
"version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938"
"reference": "b6d8164085ee0b6debcd1b7a131fd6f63bb04854"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/e20a9b7f9f62cb33a11638b345c248e7d510c938",
"reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938",
"url": "https://api.github.com/repos/symfony/translation/zipball/b6d8164085ee0b6debcd1b7a131fd6f63bb04854",
"reference": "b6d8164085ee0b6debcd1b7a131fd6f63bb04854",
"shasum": ""
},
"require": {
@ -1394,20 +1402,21 @@
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~3.4|~4.0",
"symfony/console": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/finder": "~2.8|~3.0|~4.0",
"symfony/intl": "~3.4|~4.0",
"symfony/yaml": "~3.4|~4.0"
},
"suggest": {
"psr/log": "To use logging capability in translator",
"psr/log-implementation": "To use logging capability in translator",
"symfony/config": "",
"symfony/yaml": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
"dev-master": "4.1-dev"
}
},
"autoload": {
@ -1434,7 +1443,7 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
"time": "2018-02-22T10:50:29+00:00"
"time": "2018-06-22T08:59:39+00:00"
},
{
"name": "tuupola/callable-handler",
@ -1604,7 +1613,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.0"
"php": ">=7.2"
},
"platform-dev": []
}

View File

@ -17,7 +17,7 @@ class BatteriesApiController extends BaseApiController
public function TrackChargeCycle(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{
$trackedTime = date('Y-m-d H:i:s');
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']))
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']) && IsIsoDateTime($request->getQueryParams()['tracked_time']))
{
$trackedTime = $request->getQueryParams()['tracked_time'];
}

View File

@ -17,7 +17,7 @@ class HabitsApiController extends BaseApiController
public function TrackHabitExecution(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{
$trackedTime = date('Y-m-d H:i:s');
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']))
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']) && IsIsoDateTime($request->getQueryParams()['tracked_time']))
{
$trackedTime = $request->getQueryParams()['tracked_time'];
}

View File

@ -29,7 +29,7 @@ class StockApiController extends BaseApiController
public function AddProduct(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{
$bestBeforeDate = date('Y-m-d');
if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate']))
if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate']) && IsIsoDate($request->getQueryParams()['bestbeforedate']))
{
$bestBeforeDate = $request->getQueryParams()['bestbeforedate'];
}
@ -79,7 +79,7 @@ class StockApiController extends BaseApiController
public function InventoryProduct(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{
$bestBeforeDate = date('Y-m-d');
if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate']))
if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate']) && IsIsoDate($request->getQueryParams()['bestbeforedate']))
{
$bestBeforeDate = $request->getQueryParams()['bestbeforedate'];
}

View File

@ -110,3 +110,15 @@ function IsAssociativeArray(array $array)
$keys = array_keys($array);
return array_keys($keys) !== $keys;
}
function IsIsoDate($dateString)
{
$d = DateTime::createFromFormat('Y-m-d', $dateString);
return $d && $d->format('Y-m-d') === $dateString;
}
function IsIsoDateTime($dateTimeString)
{
$d = DateTime::createFromFormat('Y-m-d H:i:s', $dateTimeString);
return $d && $d->format('Y-m-d H:i:s') === $dateTimeString;
}

View File

@ -132,6 +132,15 @@ return array(
'Filter by location' => 'Nach Standort filtern',
'Search' => 'Suche',
'Not logged in' => 'Nicht angemeldet',
'You have to select a product' => 'Ein Produkt muss ausgewählt werden',
'You have to select a habit' => 'Eine Gewohnheit muss ausgewählt werden',
'You have to select a battery' => 'Eine Batterie muss ausgewählt werden',
'A name is required' => 'Ein Name ist erforderlich',
'A location is required' => 'Ein Standort ist erforderlich',
'The amount cannot be lower than #1' => 'Die Menge darf nicht kleiner als #1 sein',
'This cannot be negative' => 'Dies darf nicht negativ sein',
'A quantity unit is required' => 'Eine Mengeneinheit muss ausgewählt werden',
'A period type is required' => 'Eine Periodentyp muss ausgewählt werden',
//Constants
'manually' => 'Manuell',

View File

@ -2,26 +2,26 @@
"name": "grocy",
"private": true,
"dependencies": {
"bootstrap": "^4.1.1",
"startbootstrap-sb-admin": "^4.0.0",
"jquery": "^3.3.1",
"font-awesome": "^4.7.0",
"bootbox": "https://github.com/makeusabrew/bootbox.git#v5.x",
"jquery-serializejson": "^2.8.1",
"bootstrap-validator": "^0.11.9",
"bootstrap-datepicker": "^1.8.0",
"moment": "^2.18.1",
"@danielfarrell/bootstrap-combobox": "https://github.com/pallidus-fintech/bootstrap-combobox.git#enhance/boostrap_4",
"@fortawesome/fontawesome-free": "^5.1.0",
"TagManager": "https://github.com/max-favilli/tagmanager.git#3.0.2",
"bootbox": "https://github.com/makeusabrew/bootbox.git#v5.x",
"bootstrap": "^4.1.1",
"bootstrap-datepicker": "^1.8.0",
"bootstrap-side-navbar": "https://github.com/samrayner/bootstrap-side-navbar.git#1.0.1",
"datatables.net": "^1.10.19",
"datatables.net-bs4": "^1.10.19",
"datatables.net-responsive": "^2.2.3",
"datatables.net-responsive-bs4": "^2.2.3",
"timeago": "^1.6.1",
"toastr": "^2.1.3",
"jquery": "^3.3.1",
"jquery-serializejson": "^2.8.1",
"jquery-ui-dist": "^1.12.1",
"moment": "^2.22.2",
"startbootstrap-sb-admin": "^4.0.0",
"swagger-ui-dist": "^3.17.3",
"tagmanager": "https://github.com/max-favilli/tagmanager.git#3.0.2",
"tempusdominus-bootstrap-4": "^5.0.1",
"swagger-ui-dist": "^3.13.4",
"jquery-ui-dist": "^1.12.1",
"bootstrap-side-navbar": "https://github.com/samrayner/bootstrap-side-navbar.git#1.0.1"
"timeago": "^1.6.3",
"toastr": "^2.1.4"
}
}

View File

@ -45,6 +45,10 @@ a.discrete-link:focus {
background-color: #e5e5e5;
}
.content-text .invalid-feedback {
font-size: 95%;
}
/* Navigation style customizations */
#mainNav {
background-color: #e5e5e5 !important;
@ -139,3 +143,16 @@ td {
#toast-container > div {
box-shadow: none;
}
/* Third party component customizations - SB Admin 2 */
#mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link:after,
#mainNav .navbar-collapse .navbar-sidenav .nav-link-collapse:after {
font-family: 'Font Awesome 5 Free';
font-weight: 900;
}
@media (max-width:992px) {
#mainNav .navbar-collapse .navbar-sidenav > .nav-item > .nav-link {
padding: 0.8em;
}
}

View File

@ -39,6 +39,10 @@ toastr.options = {
extendedTimeOut: 5000
};
window.FontAwesomeConfig = {
searchPseudoElements: true
}
Grocy.Api = { };
Grocy.Api.Get = function(apiFunction, success, error)
{
@ -100,3 +104,19 @@ Grocy.Api.Post = function(apiFunction, jsonData, success, error)
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(JSON.stringify(jsonData));
};
Grocy.FrontendHelpers = { };
Grocy.FrontendHelpers.ValidateForm = function(formId)
{
var form = document.getElementById(formId);
if (form.checkValidity() === true)
{
$(form).find(':submit').removeClass('disabled');
}
else
{
$(form).find(':submit').addClass('disabled');
}
$(form).addClass('was-validated');
}

View File

@ -30,6 +30,26 @@
}
});
$('#battery-form input').keyup(function(event)
{
Grocy.FrontendHelpers.ValidateForm('battery-form');
});
$('#battery-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if (document.getElementById('battery-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-battery-button').click();
}
}
});
$('#name').focus();
$('#battery-form').validator();
$('#battery-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('battery-form');

View File

@ -7,18 +7,18 @@
Grocy.Api.Get('batteries/get-battery-details/' + jsonForm.battery_id,
function (batteryDetails)
{
Grocy.Api.Get('batteries/track-charge-cycle/' + jsonForm.battery_id + '?tracked_time=' + $('#tracked_time').val(),
Grocy.Api.Get('batteries/track-charge-cycle/' + jsonForm.battery_id + '?tracked_time=' + $('#tracked_time').find('input').val(),
function(result)
{
toastr.success(L('Tracked charge cylce of battery #1 on #2', batteryDetails.battery.name, $('#tracked_time').val()));
toastr.success(L('Tracked charge cylce of battery #1 on #2', batteryDetails.battery.name, $('#tracked_time').find('input').val()));
$('#battery_id').val('');
$('#battery_id_text_input').focus();
$('#battery_id_text_input').val('');
$('#tracked_time').val(moment().format('YYYY-MM-DD HH:mm:ss'));
$('#tracked_time').trigger('change');
$('#tracked_time').find('input').val(moment().format('YYYY-MM-DD HH:mm:ss'));
$('#tracked_time').find('input').trigger('change');
$('#battery_id_text_input').trigger('change');
$('#batterytracking-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('batterytracking-form');
},
function(xhr)
{
@ -40,26 +40,7 @@ $('#battery_id').on('change', function(e)
if (batteryId)
{
Grocy.Components.BatteryCard.Refresh(batteryId);
$('#tracked_time').focus();
}
});
$('.datetimepicker').datetimepicker(
{
format: 'YYYY-MM-DD HH:mm:ss',
showTodayButton: true,
calendarWeeks: true,
maxDate: moment()
});
$('#tracked_time').val(moment().format('YYYY-MM-DD HH:mm:ss'));
$('#tracked_time').trigger('change');
$('#tracked_time').on('focus', function(e)
{
if ($('#battery_id_text_input').val().length === 0)
{
$('#battery_id_text_input').focus();
$('#tracked_time').find('input').focus();
}
});
@ -71,79 +52,31 @@ $('#battery_id').val('');
$('#battery_id_text_input').focus();
$('#battery_id_text_input').val('');
$('#battery_id_text_input').trigger('change');
Grocy.FrontendHelpers.ValidateForm('batterytracking-form');
$('#batterytracking-form').validator();
$('#batterytracking-form').validator('validate');
$('#batterytracking-form input').keyup(function (event)
{
Grocy.FrontendHelpers.ValidateForm('batterytracking-form');
});
$('#batterytracking-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if ($('#batterytracking-form').validator('validate').has('.has-error').length !== 0) //There is at least one validation error
if (document.getElementById('batterytracking-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-batterytracking-button').click();
}
}
});
$('#tracked_time').on('change', function(e)
$('#tracked_time').find('input').on('keypress', function (e)
{
var value = $('#tracked_time').val();
var now = new Date();
var centuryStart = Number.parseInt(now.getFullYear().toString().substring(0, 2) + '00');
var centuryEnd = Number.parseInt(now.getFullYear().toString().substring(0, 2) + '99');
if (value === 'x' || value === 'X') {
value = '29991231';
}
if (value.length === 4 && !(Number.parseInt(value) > centuryStart && Number.parseInt(value) < centuryEnd))
{
value = (new Date()).getFullYear().toString() + value;
}
if (value.length === 8 && $.isNumeric(value))
{
value = value.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
$('#tracked_time').val(value);
$('#batterytracking-form').validator('validate');
}
Grocy.FrontendHelpers.ValidateForm('batterytracking-form');
});
$('#tracked_time').on('keypress', function(e)
{
var element = $(e.target);
var value = element.val();
var dateObj = moment(element.val(), 'YYYY-MM-DD', true);
$('.datepicker').datepicker('hide');
//If input is empty and any arrow key is pressed, set date to today
if (value.length === 0 && (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 37 || e.keyCode === 39))
{
dateObj = moment(new Date(), 'YYYY-MM-DD', true);
}
if (dateObj.isValid())
{
if (e.keyCode === 38) //Up
{
element.val(dateObj.add(-1, 'days').format('YYYY-MM-DD'));
}
else if (e.keyCode === 40) //Down
{
element.val(dateObj.add(1, 'days').format('YYYY-MM-DD'));
}
else if (e.keyCode === 37) //Left
{
element.val(dateObj.add(-1, 'weeks').format('YYYY-MM-DD'));
}
else if (e.keyCode === 39) //Right
{
element.val(dateObj.add(1, 'weeks').format('YYYY-MM-DD'));
}
}
$('#batterytracking-form').validator('validate');
});

View File

@ -3,9 +3,25 @@ $(function()
$('.datetimepicker').datetimepicker(
{
format: 'YYYY-MM-DD HH:mm:ss',
showTodayButton: true,
buttons: {
showToday: true,
showClose: true
},
calendarWeeks: true,
maxDate: moment(),
locale: moment.locale()
locale: moment.locale(),
defaultDate: moment().format('YYYY-MM-DD HH:mm:ss'),
icons: {
time: 'far fa-clock',
date: 'far fa-calendar',
up: 'fas fa-arrow-up',
down: 'fas fa-arrow-down',
previous: 'fas fa-chevron-left',
next: 'fas fa-chevron-right',
today: 'fas fa-calendar-check',
clear: 'far fa-trash-alt',
close: 'far fa-times-circle'
},
sideBySide: true
});
});

View File

@ -23,7 +23,7 @@
$('#product_id_text_input').focus();
$('#product_id_text_input').val('');
$('#product_id_text_input').trigger('change');
$('#consume-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('consume-form');
},
function(xhr)
{
@ -50,26 +50,19 @@ $('#product_id').on('change', function(e)
function (productDetails)
{
$('#amount').attr('max', productDetails.stock_amount);
$('#consume-form').validator('update');
$('#amount_qu_unit').text(productDetails.quantity_unit_stock.name);
if ((productDetails.stock_amount || 0) === 0)
{
$('#product_id').val('');
$('#product_id_text_input').val('');
$('#product_id_text_input').addClass('has-error');
$('#product_id_text_input').parent('.input-group').addClass('has-error');
$('#product_id_text_input').closest('.form-group').addClass('has-error');
Grocy.FrontendHelpers.ValidateForm('consume-form');
$('#product-error').text(L('This product is not in stock'));
$('#product-error').show();
$('#product_id_text_input').focus();
}
else
{
$('#product_id_text_input').removeClass('has-error');
$('#product_id_text_input').parent('.input-group').removeClass('has-error');
$('#product_id_text_input').closest('.form-group').removeClass('has-error');
$('#product-error').hide();
Grocy.FrontendHelpers.ValidateForm('consume-form');
$('#amount').focus();
}
},
@ -104,9 +97,6 @@ $('#product_id_text_input').focus();
$('#product_id_text_input').val('');
$('#product_id_text_input').trigger('change');
$('#consume-form').validator();
$('#consume-form').validator('validate');
$('#amount').on('focus', function(e)
{
if ($('#product_id_text_input').val().length === 0)
@ -119,14 +109,23 @@ $('#amount').on('focus', function(e)
}
});
$('#consume-form input').keyup(function (event)
{
Grocy.FrontendHelpers.ValidateForm('consume-form');
});
$('#consume-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if ($('#consume-form').validator('validate').has('.has-error').length !== 0) //There is at least one validation error
if (document.getElementById('consume-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-consume-button').click();
}
}
});

View File

@ -30,9 +30,29 @@
}
});
$('#habit-form input').keyup(function(event)
{
Grocy.FrontendHelpers.ValidateForm('habit-form');
});
$('#habit-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if (document.getElementById('habit-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-habit-button').click();
}
}
});
$('#name').focus();
$('#habit-form').validator();
$('#habit-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('habit-form');
$('.input-group-habit-period-type').on('change', function(e)
{
@ -42,10 +62,10 @@ $('.input-group-habit-period-type').on('change', function(e)
if (periodType === 'dynamic-regular')
{
$('#habit-period-type-info').text(L('This means it is estimated that a new execution of this habit is tracked #1 days after the last was tracked', periodDays.toString()));
$('#habit-period-type-info').show();
$('#habit-period-type-info').removeClass('d-none');
}
else
{
$('#habit-period-type-info').hide();
$('#habit-period-type-info').addClass('d-none');
}
});

View File

@ -7,18 +7,18 @@
Grocy.Api.Get('habits/get-habit-details/' + jsonForm.habit_id,
function (habitDetails)
{
Grocy.Api.Get('habits/track-habit-execution/' + jsonForm.habit_id + '?tracked_time=' + $('#tracked_time').val(),
Grocy.Api.Get('habits/track-habit-execution/' + jsonForm.habit_id + '?tracked_time=' + $('#tracked_time').find('input').val(),
function(result)
{
toastr.success(L('Tracked execution of habit #1 on #2', habitDetails.habit.name, $('#tracked_time').val()));
toastr.success(L('Tracked execution of habit #1 on #2', habitDetails.habit.name, $('#tracked_time').find('input').val()));
$('#habit_id').val('');
$('#habit_id_text_input').focus();
$('#habit_id_text_input').val('');
$('#tracked_time').val(moment().format('YYYY-MM-DD HH:mm:ss'));
$('#tracked_time').trigger('change');
$('#tracked_time').find('input').val(moment().format('YYYY-MM-DD HH:mm:ss'));
$('#tracked_time').find('input').trigger('change');
$('#habit_id_text_input').trigger('change');
$('#habittracking-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('habittracking-form');
},
function(xhr)
{
@ -40,18 +40,7 @@ $('#habit_id').on('change', function(e)
if (habitId)
{
Grocy.Components.HabitCard.Refresh(habitId);
$('#tracked_time').focus();
}
});
$('#tracked_time').val(moment().format('YYYY-MM-DD HH:mm:ss'));
$('#tracked_time').trigger('change');
$('#tracked_time').on('focus', function(e)
{
if ($('#habit_id_text_input').val().length === 0)
{
$('#habit_id_text_input').focus();
$('#tracked_time').find('input').focus();
}
});
@ -63,23 +52,30 @@ $('#habit_id').val('');
$('#habit_id_text_input').focus();
$('#habit_id_text_input').val('');
$('#habit_id_text_input').trigger('change');
Grocy.FrontendHelpers.ValidateForm('habittracking-form');
$('#habittracking-form').validator();
$('#habittracking-form').validator('validate');
$('#habittracking-form input').keyup(function (event)
{
Grocy.FrontendHelpers.ValidateForm('habittracking-form');
});
$('#habittracking-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if ($('#habittracking-form').validator('validate').has('.has-error').length !== 0) //There is at least one validation error
if (document.getElementById('habittracking-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-habittracking-button').click();
}
}
});
$('#tracked_time').on('keypress', function(e)
$('#tracked_time').find('input').on('keypress', function(e)
{
$('#habittracking-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('habittracking-form');
});

View File

@ -40,14 +40,14 @@
}
else
{
$('#inventory-change-info').hide();
$('#inventory-change-info').addClass('d-none');
$('#new_amount').val('');
$('#best_before_date').val('');
$('#product_id').val('');
$('#product_id_text_input').focus();
$('#product_id_text_input').val('');
$('#product_id_text_input').trigger('change');
$('#inventory-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('inventory-form');
}
},
function(xhr)
@ -170,33 +170,6 @@ $('#product_id_text_input').focus();
$('#product_id_text_input').val('');
$('#product_id_text_input').trigger('change');
$('#inventory-form').validator({
custom: {
'isodate': function($el)
{
if ($el.val().length !== 0 && !moment($el.val(), 'YYYY-MM-DD', true).isValid())
{
return 'Wrong date format, needs to be YYYY-MM-DD';
}
else if (moment($el.val()).isValid())
{
if (moment($el.val()).isBefore(moment(), 'day'))
{
return 'This value cannot be before today.';
}
}
},
'notequal': function($el)
{
if ($el.val().length !== 0 && $el.val().toString() === $el.attr('not-equal').toString())
{
return 'This value cannot be equal to ' + $el.attr('not-equal').toString();
}
}
}
});
$('#inventory-form').validator('validate');
$('#new_amount').on('focus', function(e)
{
if ($('#product_id_text_input').val().length === 0)
@ -209,15 +182,24 @@ $('#new_amount').on('focus', function(e)
}
});
$('#inventory-form input').keyup(function (event)
{
Grocy.FrontendHelpers.ValidateForm('inventory-form');
});
$('#inventory-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if ($('#inventory-form').validator('validate').has('.has-error').length !== 0) //There is at least one validation error
if (document.getElementById('inventory-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-inventory-button').click();
}
}
});
@ -254,12 +236,12 @@ $('#new_amount').on('keypress', function(e)
$('#best_before_date').on('change', function(e)
{
$('#inventory-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('inventory-form');
});
$('#best_before_date').on('keypress', function(e)
{
$('#inventory-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('inventory-form');
});
$('#best_before_date').on('keydown', function(e)
@ -270,11 +252,11 @@ $('#best_before_date').on('keydown', function(e)
}
});
$('#new_amount').on('change', function(e)
$('#new_amount').on('keyup', function(e)
{
if ($('#product_id').parent().hasClass('has-error'))
{
$('#inventory-change-info').hide();
$('#inventory-change-info').addClass('d-none');
return;
}
@ -292,23 +274,22 @@ $('#new_amount').on('change', function(e)
{
var amountToAdd = newAmount - productDetails.stock_amount;
$('#inventory-change-info').text(L('This means #1 will be added to stock', amountToAdd.toString() + ' ' + productDetails.quantity_unit_stock.name));
$('#inventory-change-info').show();
$('#inventory-change-info').removeClass('d-none')
$('#best_before_date').attr('required', 'required');
}
else if (newAmount < productStockAmount)
{
var amountToRemove = productStockAmount - newAmount;
$('#inventory-change-info').text(L('This means #1 will be removed from stock', amountToRemove.toString() + ' ' + productDetails.quantity_unit_stock.name));
$('#inventory-change-info').show();
$('#inventory-change-info').removeClass('d-none')
$('#best_before_date').removeAttr('required');
}
else
{
$('#inventory-change-info').hide();
$('#inventory-change-info').addClass('d-none');
}
$('#inventory-form').validator('update');
$('#inventory-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('inventory-form');
},
function(xhr)
{

View File

@ -30,6 +30,26 @@
}
});
$('#location-form input').keyup(function (event)
{
Grocy.FrontendHelpers.ValidateForm('location-form');
});
$('#location-form input').keydown(function (event)
{
if (event.keyCode === 13) //Enter
{
if (document.getElementById('location-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-location-button').click();
}
}
});
$('#name').focus();
$('#location-form').validator();
$('#location-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('location-form');

View File

@ -1,10 +1,7 @@
$('.logout-button').hide();
$('.logout-button-divider').hide();
$('#username').focus();
$('#username').focus();
if (GetUriParam('invalid') === 'true')
{
$('#login-error').text(L('Invalid credentials, please try again'));
$('#login-error').show();
$('#login-error').removeClass('d-none');
}

View File

@ -82,15 +82,35 @@ $('.input-group-qu').on('change', function(e)
if (factor > 1)
{
$('#qu-conversion-info').text(L('This means 1 #1 purchased will be converted into #2 #3 in stock', $("#qu_id_purchase option:selected").text(), (1 * factor).toString(), $("#qu_id_stock option:selected").text()));
$('#qu-conversion-info').show();
$('#qu-conversion-info').removeClass('d-none');
}
else
{
$('#qu-conversion-info').hide();
$('#qu-conversion-info').addClass('d-none');
}
});
$('#product-form input').keyup(function(event)
{
Grocy.FrontendHelpers.ValidateForm('product-form');
});
$('#product-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if (document.getElementById('product-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-product-button').click();
}
}
});
$('#name').focus();
$('#product-form').validator();
$('#product-form').validator('validate');
$('.input-group-qu').trigger('change');
Grocy.FrontendHelpers.ValidateForm('product-form');

View File

@ -48,7 +48,7 @@
$('#product_id_text_input').focus();
$('#product_id_text_input').val('');
$('#product_id_text_input').trigger('change');
$('#purchase-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('purchase-form');
}
},
function(xhr)
@ -180,26 +180,6 @@ $('#product_id_text_input').focus();
$('#product_id_text_input').val('');
$('#product_id_text_input').trigger('change');
$('#purchase-form').validator({
custom: {
'isodate': function($el)
{
if ($el.val().length !== 0 && !moment($el.val(), 'YYYY-MM-DD', true).isValid())
{
return 'Wrong date format, needs to be YYYY-MM-DD';
}
else if (moment($el.val()).isValid())
{
if (moment($el.val()).isBefore(moment(), 'day'))
{
return 'This value cannot be before today.';
}
}
}
}
});
$('#purchase-form').validator('validate');
$('#best_before_date').on('focus', function(e)
{
if ($('#product_id_text_input').val().length === 0)
@ -220,15 +200,24 @@ $('#amount').on('focus', function(e)
}
});
$('#purchase-form input').keyup(function(event)
{
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});
$('#purchase-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if ($('#purchase-form').validator('validate').has('.has-error').length !== 0) //There is at least one validation error
if (document.getElementById('purchase-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-purchase-button').click();
}
}
});
@ -260,10 +249,15 @@ if (addBarcode !== undefined)
$('#best_before_date').on('change', function(e)
{
$('#purchase-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});
$('#best_before_date').on('keypress', function(e)
{
$('#purchase-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});
$('#amount').on('change', function (e)
{
Grocy.FrontendHelpers.ValidateForm('purchase-form');
});

View File

@ -30,6 +30,26 @@
}
});
$('#quantityunit-form input').keyup(function(event)
{
Grocy.FrontendHelpers.ValidateForm('quantityunit-form');
});
$('#quantityunit-form input').keydown(function(event)
{
if (event.keyCode === 13) //Enter
{
if (document.getElementById('quantityunit-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-quantityunit-button').click();
}
}
});
$('#name').focus();
$('#quantityunit-form').validator();
$('#quantityunit-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('quantityunit-form');

View File

@ -42,43 +42,6 @@ $('#product_id').on('change', function(e)
function (productDetails)
{
$('#amount_qu_unit').text(productDetails.quantity_unit_purchase.name);
if ($('#product_id').hasClass('suppress-next-custom-validate-event'))
{
$('#product_id').removeClass('suppress-next-custom-validate-event');
}
else
{
Grocy.Api.Get('get-objects/shopping_list',
function (currentShoppingListItems)
{
if (currentShoppingListItems.filter(function (e) { return e.product_id === productId; }).length > 0)
{
$('#product_id').val('');
$('#product_id_text_input').val('');
$('#product_id_text_input').addClass('has-error');
$('#product_id_text_input').parent('.input-group').addClass('has-error');
$('#product_id_text_input').closest('.form-group').addClass('has-error');
$('#product-error').text('This product is already on the shopping list.');
$('#product-error').show();
$('#product_id_text_input').focus();
}
else
{
$('#product_id_text_input').removeClass('has-error');
$('#product_id_text_input').parent('.input-group').removeClass('has-error');
$('#product_id_text_input').closest('.form-group').removeClass('has-error');
$('#product-error').hide();
$('#amount').focus();
}
},
function(xhr)
{
console.error(xhr);
}
);
}
},
function(xhr)
{
@ -113,8 +76,7 @@ if (Grocy.EditMode === 'edit')
$('#product_id').trigger('change');
}
$('#shoppinglist-form').validator();
$('#shoppinglist-form').validator('validate');
Grocy.FrontendHelpers.ValidateForm('shoppinglist-form');
$('#amount').on('focus', function(e)
{
@ -124,14 +86,23 @@ $('#amount').on('focus', function(e)
}
});
$('#shoppinglist-form input').keydown(function(event)
$('#shoppinglist-form input').keyup(function (event)
{
Grocy.FrontendHelpers.ValidateForm('shoppinglist-form');
});
$('#shoppinglist-form input').keydown(function (event)
{
if (event.keyCode === 13) //Enter
{
if ($('#shoppinglist-form').validator('validate').has('.has-error').length !== 0) //There is at least one validation error
if (document.getElementById('shoppinglist-form').checkValidity() === false) //There is at least one validation error
{
event.preventDefault();
return false;
}
else
{
$('#save-shoppinglist-button').click();
}
}
});

View File

@ -10,15 +10,15 @@
<h1>
@yield('title')
<a class="btn btn-outline-dark" href="{{ $U('/battery/new') }}">
<i class="fa fa-plus"></i>&nbsp;{{ $L('Add') }}
<i class="fas fa-plus"></i>&nbsp;{{ $L('Add') }}
</a>
</h1>
</div>
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -39,10 +39,10 @@
<tr>
<td class="fit-content">
<a class="btn btn-info btn-sm" href="{{ $U('/battery/') }}{{ $battery->id }}">
<i class="fa fa-pencil"></i>
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-danger btn-sm battery-delete-button" href="#" data-battery-id="{{ $battery->id }}" data-battery-name="{{ $battery->name }}">
<i class="fa fa-trash"></i>
<i class="fas fa-trash"></i>
</a>
</td>
<td>

View File

@ -18,8 +18,8 @@
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -42,7 +42,7 @@
<a class="btn btn-success btn-sm track-charge-cycle-button" href="#" title="{{ $L('Track charge cycle of battery #1', FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name) }}"
data-battery-id="{{ $curentBatteryEntry->battery_id }}"
data-battery-name="{{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}">
<i class="fa fa-fire"></i>
<i class="fas fa-fire"></i>
</a>
</td>
<td>

View File

@ -19,12 +19,12 @@
<script>Grocy.EditObjectId = {{ $battery->id }}</script>
@endif
<form id="battery-form">
<form id="battery-form" novalidate>
<div class="form-group">
<label for="name">{{ $L('Name') }}</label>
<input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $battery->name }}@endif">
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A name is required') }}</div>
</div>
<div class="form-group">

View File

@ -6,10 +6,10 @@
@section('content')
<div class="row">
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
<h1>@yield('title')</h1>
<form id="batterytracking-form">
<form id="batterytracking-form" novalidate>
<div class="form-group">
<label for="battery_id">{{ $L('Battery') }}</label>
@ -19,26 +19,20 @@
<option value="{{ $battery->id }}">{{ $battery->name }}</option>
@endforeach
</select>
<div id="battery-error" class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('You have to select a battery') }}</div>
</div>
<div class="form-group">
<label for="tracked_time">{{ $L('Tracked time') }}</label>
<div class="input-group date datetimepicker">
<input type="text" class="form-control" id="tracked_time" name="tracked_time" required >
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
<div class="invalid-feedback"></div>
</div>
@include('components.datetimepicker', array(
'id' => 'tracked_time',
'label' => 'Tracked time'
))
<button id="save-batterytracking-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>
</form>
</div>
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
@include('components.batterycard')
</div>
</div>

View File

@ -4,9 +4,10 @@
<div class="card">
<div class="card-header">
<i class="fa fa-fw fa-battery-three-quarters"></i> {{ $L('Battery overview') }} <strong><span id="batterycard-battery-name"></span></strong>
<i class="fas fa-battery-three-quarters"></i> {{ $L('Battery overview') }}
</div>
<div class="card-body">
<h3><span id="batterycard-battery-name"></span></h3>
<strong>{{ $L('Used in') }}:</strong> <span id="batterycard-battery-used_in"></span><br>
<strong>{{ $L('Charge cycles count') }}:</strong> <span id="batterycard-battery-charge-cycles-count"></span><br>
<strong>{{ $L('Last charged') }}:</strong> <span id="batterycard-battery-last-charged"></span> <time id="batterycard-battery-last-charged-timeago" class="timeago timeago-contextual"></time><br>

View File

@ -5,9 +5,9 @@
<div class="form-group">
<label for="{{ $id }}">{{ $L($label) }}&nbsp;&nbsp;<span class="small text-muted"><time id="datepicker-timeago" class="timeago timeago-contextual"></time>@if(!empty($hint))<br>{{ $L($hint) }}@endif</span></label>
<div class="input-group date">
<input type="text" data-isodate="isodate" class="form-control datepicker" id="{{ $id }}" name="{{ $id }}" required autocomplete="off">
<input type="text" data-isodate="isodate" class="form-control datepicker" id="{{ $id }}" name="{{ $id }}" required autocomplete="off" min="2018-07-11">
<div id="datepicker-button" class="input-group-append">
<div class="input-group-text"><i class="fa fa-calendar"></i></div>
<div class="input-group-text"><i class="fas fa-calendar"></i></div>
</div>
</div>
<div class="invalid-feedback"></div>

View File

@ -3,11 +3,11 @@
@endpush
<div class="form-group">
<label for="{{ $id }}">{{ $L($label) }}</label>
<label>{{ $L($label) }}</label>
<div class="input-group date datetimepicker" id="{{ $id }}" data-target-input="nearest">
<input type="text" class="form-control datetimepicker-input" data-target="#{{ $id }}"/>
<div class="input-group-append" data-target="#{{ $id }}" data-toggle="datetimepicker">
<div class="input-group-text"><i class="fa fa-calendar"></i></div>
<div class="input-group-text"><i class="fas fa-calendar"></i></div>
</div>
</div>
<div class="invalid-feedback"></div>

View File

@ -4,9 +4,10 @@
<div class="card">
<div class="card-header">
<i class="fa fa-fw fa-refresh"></i> {{ $L('Habit overview') }} <strong><span id="habitcard-habit-name"></span></strong>
<i class="fas fa-refresh"></i> {{ $L('Habit overview') }}
</div>
<div class="card-body">
<h3><span id="habitcard-habit-name"></span></h3>
<strong>{{ $L('Tracked count') }}:</strong> <span id="habitcard-habit-tracked-count"></span><br>
<strong>{{ $L('Last tracked') }}:</strong> <span id="habitcard-habit-last-tracked"></span> <time id="habitcard-habit-last-tracked-timeago" class="timeago timeago-contextual"></time><br>
</div>

View File

@ -4,9 +4,10 @@
<div class="card">
<div class="card-header">
<i class="fa fa-fw fa-product-hunt"></i> {{ $L('Product overview') }} <strong><span id="productcard-product-name"></span></strong>
<i class="fab fa-product-hunt"></i> {{ $L('Product overview') }}
</div>
<div class="card-body">
<h3><span id="productcard-product-name"></span></h3>
<strong>{{ $L('Stock quantity unit') }}:</strong> <span id="productcard-product-stock-qu-name"></span><br>
<strong>{{ $L('Stock amount') }}:</strong> <span id="productcard-product-stock-amount"></span> <span id="productcard-product-stock-qu-name2"></span><br>
<strong>{{ $L('Last purchased') }}:</strong> <span id="productcard-product-last-purchased"></span> <time id="productcard-product-last-purchased-timeago" class="timeago timeago-contextual"></time><br>

View File

@ -6,26 +6,26 @@
@section('content')
<div class="row">
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
<h1>@yield('title')</h1>
<form id="consume-form">
<form id="consume-form" novalidate>
<div class="form-group">
<label for="product_id">{{ $L('Product') }}&nbsp;&nbsp;<i class="fa fa-barcode"></i></label>
<label for="product_id">{{ $L('Product') }}&nbsp;&nbsp;<i class="fas fa-barcode"></i></label>
<select class="form-control combobox" id="product_id" name="product_id" required>
<option value=""></option>
@foreach($products as $product)
<option data-additional-searchdata="{{ $product->barcode }}" value="{{ $product->id }}">{{ $product->name }}</option>
@endforeach
</select>
<div id="product-error" class="invalid-feedback"></div>
<div id="product-error" class="invalid-feedback">{{ $L('You have to select a product') }}</div>
</div>
<div class="form-group">
<label for="amount">{{ $L('Amount') }}&nbsp;&nbsp;<span id="amount_qu_unit" class="small text-muted"></span></label>
<input type="number" class="form-control" id="amount" name="amount" value="1" min="1" required>
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('The amount cannot be lower than #1', '0') }}</div>
</div>
<div class="checkbox">
@ -39,7 +39,7 @@
</form>
</div>
<div class="col-lg-6 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
@include('components.productcard')
</div>
</div>

View File

@ -19,12 +19,12 @@
<script>Grocy.EditObjectId = {{ $habit->id }};</script>
@endif
<form id="habit-form">
<form id="habit-form" novalidate>
<div class="form-group">
<label for="name">{{ $L('Name') }}</label>
<input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $habit->name }}@endif">
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A name is required') }}</div>
</div>
<div class="form-group">
@ -39,16 +39,16 @@
<option @if($mode == 'edit' && $periodType == $habit->period_type) selected="selected" @endif value="{{ $periodType }}">{{ $L($periodType) }}</option>
@endforeach
</select>
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A period type is required') }}</div>
</div>
<div class="form-group">
<label for="period_days">{{ $L('Period days') }}</label>
<input type="number" class="form-control input-group-habit-period-type" id="period_days" name="period_days" value="@if($mode == 'edit'){{ $habit->period_days }}@endif">
<div class="invalid-feedback"></div>
<input type="number" class="form-control input-group-habit-period-type" id="period_days" name="period_days" min="0" value="@if($mode == 'edit'){{ $habit->period_days }}@endif">
<div class="invalid-feedback">{{ $L('This cannot be negative') }}</div>
</div>
<p id="habit-period-type-info" class="help-block text-muted"></p>
<p id="habit-period-type-info" class="form-text text-muted small d-none"></p>
<button id="save-habit-button" type="submit" class="btn btn-success">{{ $L('Save') }}</button>

View File

@ -10,15 +10,15 @@
<h1>
@yield('title')
<a class="btn btn-outline-dark" href="{{ $U('/habit/new') }}">
<i class="fa fa-plus"></i>&nbsp;{{ $L('Add') }}
<i class="fas fa-plus"></i>&nbsp;{{ $L('Add') }}
</a>
</h1>
</div>
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -40,10 +40,10 @@
<tr>
<td class="fit-content">
<a class="btn btn-info btn-sm" href="{{ $U('/habit/') }}{{ $habit->id }}">
<i class="fa fa-pencil"></i>
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-danger btn-sm habit-delete-button" href="#" data-habit-id="{{ $habit->id }}" data-habit-name="{{ $habit->name }}">
<i class="fa fa-trash"></i>
<i class="fas fa-trash"></i>
</a>
</td>
<td>

View File

@ -18,8 +18,8 @@
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -42,7 +42,7 @@
<a class="btn btn-success btn-sm track-habit-button" href="#" title="{{ $L('Track execution of habit #1', FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->name) }}"
data-habit-id="{{ $curentHabitEntry->habit_id }}"
data-habit-name="{{ FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->name }}">
<i class="fa fa-play"></i>
<i class="fas fa-play"></i>
</a>
</td>
<td>

View File

@ -6,10 +6,10 @@
@section('content')
<div class="row">
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
<h1>@yield('title')</h1>
<form id="habittracking-form">
<form id="habittracking-form" novalidate>
<div class="form-group">
<label for="habit_id">{{ $L('Habit') }}</label>
@ -19,7 +19,7 @@
<option value="{{ $habit->id }}">{{ $habit->name }}</option>
@endforeach
</select>
<div id="product-error" class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('You have to select a habit') }}</div>
</div>
@include('components.datetimepicker', array(
@ -32,7 +32,7 @@
</form>
</div>
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
@include('components.habitcard')
</div>
</div>

View File

@ -6,28 +6,28 @@
@section('content')
<div class="row">
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
<h1>@yield('title')</h1>
<form id="inventory-form">
<form id="inventory-form" novalidate>
<div class="form-group">
<label for="product_id">{{ $L('Product') }}&nbsp;&nbsp;<i class="fa fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted d-none">&nbsp;&nbsp;{{ $L('Barcode lookup is disabled') }}</span></label>
<label for="product_id">{{ $L('Product') }}&nbsp;&nbsp;<i class="fas fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted d-none">&nbsp;&nbsp;{{ $L('Barcode lookup is disabled') }}</span></label>
<select class="form-control combobox" id="product_id" name="product_id" required>
<option value=""></option>
@foreach($products as $product)
<option data-additional-searchdata="{{ $product->barcode }}" value="{{ $product->id }}">{{ $product->name }}</option>
@endforeach
</select>
<div class="invalid-feedback"></div>
<div id="flow-info-addbarcodetoselection" class="text-muted small d-none"><strong><span id="addbarcodetoselection"></span></strong> {{ $L('will be added to the list of barcodes for the selected product on submit') }}</div>
<div class="invalid-feedback">{{ $L('You have to select a product') }}</div>
<div id="flow-info-addbarcodetoselection" class="form-text text-muted small d-none"><strong><span id="addbarcodetoselection"></span></strong> {{ $L('will be added to the list of barcodes for the selected product on submit') }}</div>
</div>
<div class="form-group">
<label for="new_amount">{{ $L('New amount') }}&nbsp;&nbsp;<span id="new_amount_qu_unit" class="small text-muted"></span></label>
<input type="number" data-notequal="notequal" class="form-control" id="new_amount" name="new_amount" min="0" not-equal="-1" required>
<div class="invalid-feedback"></div>
<div id="inventory-change-info" class="text-muted"></div>
<div class="invalid-feedback">{{ $L('The amount cannot be lower than #1', '0') }}</div>
<div id="inventory-change-info" class="form-text text-muted small d-none"></div>
</div>
@include('components.datepicker', array(
@ -41,7 +41,7 @@
</form>
</div>
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
@include('components.productcard')
</div>
</div>

View File

@ -15,7 +15,7 @@
<link href="{{ $U('/node_modules/bootstrap/dist/css/bootstrap.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
<link href="{{ $U('/node_modules/startbootstrap-sb-admin/css/sb-admin.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
<link href="{{ $U('/node_modules/font-awesome/css/font-awesome.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
<link href="{{ $U('/node_modules/@fortawesome/fontawesome-free/css/all.css?v=', true) }}{{ $version }}" rel="stylesheet">
<link href="{{ $U('/node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
<link href="{{ $U('/node_modules/@danielfarrell/bootstrap-combobox/css/bootstrap-combobox.css?v=', true) }}{{ $version }}" rel="stylesheet">
<link href="{{ $U('/node_modules/datatables.net-bs4/css/dataTables.bootstrap4.css?v=', true) }}{{ $version }}" rel="stylesheet">
@ -38,104 +38,104 @@
<body class="fixed-nav">
<nav id="mainNav" class="navbar navbar-expand-lg navbar-light fixed-top">
<a class="navbar-brand" href="{{ $U('/') }}"><img src="{{ $U('/img/grocy_logo.svg?v=', true) }}" height="30"></a>
<a class="navbar-brand py-0" href="{{ $U('/') }}"><img src="{{ $U('/img/grocy_logo.svg?v=', true) }}{{ $version }}" height="30"></a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#sidebarResponsive">
<span class="navbar-toggler-icon"></span>
</button>
<div id="sidebarResponsive" class="collapse navbar-collapse">
<ul class="navbar-nav navbar-sidenav">
<ul class="navbar-nav navbar-sidenav pt-2">
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="{{ $L('Stock overview') }}" data-nav-for-page="stockoverview">
<a class="nav-link discrete-link" href="{{ $U('/stockoverview') }}">
<i class="fa fa-fw fa-dashboard"></i>
<i class="fas fa-tachometer-alt"></i>
<span class="nav-link-text">{{ $L('Stock overview') }}</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="{{ $L('Habits overview') }}" data-nav-for-page="habitsoverview">
<a class="nav-link discrete-link" href="{{ $U('/habitsoverview') }}">
<i class="fa fa-fw fa-dashboard"></i>
<i class="fas fa-tachometer-alt"></i>
<span class="nav-link-text">{{ $L('Habits overview') }}</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="{{ $L('Batteries overview') }}" data-nav-for-page="batteriesoverview">
<a class="nav-link discrete-link" href="{{ $U('/batteriesoverview') }}">
<i class="fa fa-fw fa-dashboard"></i>
<i class="fas fa-tachometer-alt"></i>
<span class="nav-link-text">{{ $L('Batteries overview') }}</span>
</a>
</li>
<li class="nav-item mt-4" data-toggle="tooltip" data-placement="right" title="{{ $L('Purchase') }}" data-nav-for-page="purchase">
<a class="nav-link discrete-link" href="{{ $U('/purchase') }}">
<i class="fa fa-fw fa-shopping-cart"></i>
<i class="fas fa-shopping-cart"></i>
<span class="nav-link-text">{{ $L('Purchase') }}</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="{{ $L('Consume') }}" data-nav-for-page="consume">
<a class="nav-link discrete-link" href="{{ $U('/consume') }}">
<i class="fa fa-fw fa-cutlery"></i>
<i class="fas fa-utensils"></i>
<span class="nav-link-text">{{ $L('Consume') }}</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="{{ $L('Shopping list') }}" data-nav-for-page="shoppinglist">
<a class="nav-link discrete-link" href="{{ $U('/shoppinglist') }}">
<i class="fa fa-fw fa-shopping-bag"></i>
<i class="fas fa-shopping-bag"></i>
<span class="nav-link-text">{{ $L('Shopping list') }}</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="{{ $L('Inventory') }}" data-nav-for-page="inventory">
<a class="nav-link discrete-link" href="{{ $U('/inventory') }}">
<i class="fa fa-fw fa-list"></i>
<i class="fas fa-list"></i>
<span class="nav-link-text">{{ $L('Inventory') }}</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="{{ $L('Habit tracking') }}" data-nav-for-page="habittracking">
<a class="nav-link discrete-link" href="{{ $U('/habittracking') }}">
<i class="fa fa-fw fa-play"></i>
<i class="fas fa-play"></i>
<span class="nav-link-text">{{ $L('Habit tracking') }}</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="{{ $L('Battery tracking') }}" data-nav-for-page="batterytracking">
<a class="nav-link discrete-link" href="{{ $U('/batterytracking') }}">
<i class="fa fa-fw fa-fire"></i>
<i class="fas fa-fire"></i>
<span class="nav-link-text">{{ $L('Battery tracking') }}</span>
</a>
</li>
<li class="nav-item mt-4" data-toggle="tooltip" data-placement="right" title="{{ $L('Manage master data') }}">
<a class="nav-link nav-link-collapse collapsed discrete-link" data-toggle="collapse" href="#top-nav-manager-master-data">
<i class="fa fa-fw fa-wrench"></i>
<i class="fas fa-table"></i>
<span class="nav-link-text">{{ $L('Manage master data') }}</span>
</a>
<ul id="top-nav-manager-master-data" class="sidenav-second-level collapse">
<li data-nav-for-page="products">
<a class="nav-link discrete-link" href="{{ $U('/products') }}">
<i class="fa fa-fw fa-product-hunt"></i>
<i class="fab fa-product-hunt"></i>
<span class="nav-link-text">{{ $L('Products') }}</span>
</a>
</li>
<li data-nav-for-page="locations">
<a class="nav-link discrete-link" href="{{ $U('/locations') }}">
<i class="fa fa-fw fa-map-marker"></i>
<i class="fas fa-map-marker-alt"></i>
<span class="nav-link-text">{{ $L('Locations') }}</span>
</a>
</li>
<li data-nav-for-page="quantityunits">
<a class="nav-link discrete-link" href="{{ $U('/quantityunits') }}">
<i class="fa fa-fw fa-balance-scale"></i>
<i class="fas fa-balance-scale"></i>
<span class="nav-link-text">{{ $L('Quantity units') }}</span>
</a>
</li>
<li data-nav-for-page="habits">
<a class="nav-link discrete-link" href="{{ $U('/habits') }}">
<i class="fa fa-fw fa-refresh"></i>
<i class="fas fa-sync-alt"></i>
<span class="nav-link-text">{{ $L('Habits') }}</span>
</a>
</li>
<li data-nav-for-page="batteries">
<a class="nav-link discrete-link" href="{{ $U('/batteries') }}">
<i class="fa fa-fw fa-battery-three-quarters"></i>
<i class="fas fa-battery-three-quarters"></i>
<span class="nav-link-text">{{ $L('Batteries') }}</span>
</a>
</li>
@ -146,26 +146,32 @@
<ul class="navbar-nav sidenav-toggler">
<li class="nav-item">
<a id="sidenavToggler" class="nav-link text-center">
<i class="fa fa-fw fa-angle-left"></i>
<i class="fas fa-angle-left"></i>
</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
@if(AUTHENTICATED === true)
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle mr-lg-2" href="#" data-toggle="dropdown">@if(AUTHENTICATED === true){{ HTTP_USER }}@else{{ $L('Not logged in') }}@endif</a>
<a class="nav-link dropdown-toggle discrete-link" href="#" data-toggle="dropdown"><i class="fas fa-user"></i> {{ HTTP_USER }}</a>
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item logout-button discrete-link" href="{{ $U('/logout') }}"><i class="fa fa-sign-out fa-fw"></i>&nbsp;{{ $L('Logout') }}</a>
<div class="dropdown-divider logout-button-divider"></div>
<a class="dropdown-item logout-button discrete-link" href="{{ $U('/logout') }}"><i class="fas fa-sign-out-alt"></i>&nbsp;{{ $L('Logout') }}</a>
</div>
</li>
@endif
<a class="dropdown-item discrete-link" href="{{ $U('/manageapikeys') }}"><i class="fa fa-handshake-o fa-fw"></i>&nbsp;{{ $L('Manage API keys') }}</a>
<a class="dropdown-item discrete-link" target="_blank" href="{{ $U('/api') }}"><i class="fa fa-book"></i>&nbsp;{{ $L('REST API & data model documentation') }}</a>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle discrete-link" href="#" data-toggle="dropdown"><i class="fas fa-wrench"></i></a>
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item discrete-link" href="{{ $U('/manageapikeys') }}"><i class="fas fa-handshake"></i>&nbsp;{{ $L('Manage API keys') }}</a>
<a class="dropdown-item discrete-link" target="_blank" href="{{ $U('/api') }}"><i class="fas fa-book"></i>&nbsp;{{ $L('REST API & data model documentation') }}</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item discrete-link" href="#" data-toggle="modal" data-target="#about-modal"><i class="fa fa-info fa-fw"></i>&nbsp;{{ $L('About grocy') }} (Version {{ $version }})</a>
<a class="dropdown-item discrete-link" href="#" data-toggle="modal" data-target="#about-modal"><i class="fas fa-info fa-fw"></i>&nbsp;{{ $L('About grocy') }} (Version {{ $version }})</a>
</div>
</li>
</ul>
@ -199,7 +205,7 @@
<br>
Life runs on code<br>
<a href="https://github.com/berrnd/grocy" class="discrete-link" target="_blank">
<i class="fa fa-github"></i>
<i class="fas fa-github"></i>
</a>
</div>
</div>
@ -212,10 +218,9 @@
<script src="{{ $U('/node_modules/bootbox/dist/bootbox.min.js?v=', true) }}{{ $version }}"></script>
<script src="{{ $U('/node_modules/jquery-serializeJSON/jquery.serializejson.min.js?v=', true) }}{{ $version }}"></script>
<script src="{{ $U('/node_modules/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js?v=', true) }}{{ $version }}"></script>
@if(!empty($L('bootstrap_datepicker_locale')))<script src="{{ $U('/bower_components', true) }}/bootstrap-datepicker/dist/locales/bootstrap-datepicker.{{ $L('bootstrap_datepicker_locale') }}.min.js?v={{ $version }}"></script>@endif
@if(!empty($L('bootstrap_datepicker_locale')))<script src="{{ $U('/node_modules', true) }}/bootstrap-datepicker/dist/locales/bootstrap-datepicker.{{ $L('bootstrap_datepicker_locale') }}.min.js?v={{ $version }}"></script>@endif
<script src="{{ $U('/node_modules/moment/min/moment.min.js?v=', true) }}{{ $version }}"></script>
@if(!empty($L('moment_locale')))<script src="{{ $U('/bower_components', true) }}/moment/locale/{{ $L('moment_locale') }}.js?v={{ $version }}"></script>@endif
<script src="{{ $U('/node_modules/bootstrap-validator/dist/validator.min.js?v=', true) }}{{ $version }}"></script>
@if(!empty($L('moment_locale')))<script src="{{ $U('/node_modules', true) }}/moment/locale/{{ $L('moment_locale') }}.js?v={{ $version }}"></script>@endif
<script src="{{ $U('/node_modules/@danielfarrell/bootstrap-combobox/js/bootstrap-combobox.js?v=', true) }}{{ $version }}"></script>
<script src="{{ $U('/node_modules/datatables.net/js/jquery.dataTables.min.js?v=', true) }}{{ $version }}"></script>
<script src="{{ $U('/node_modules/datatables.net-bs4/js/dataTables.bootstrap4.js?v=', true) }}{{ $version }}"></script>

View File

@ -19,12 +19,12 @@
<script>Grocy.EditObjectId = {{ $location->id }};</script>
@endif
<form id="location-form">
<form id="location-form" novalidate>
<div class="form-group">
<label for="name">{{ $L('Name') }}</label>
<input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $location->name }}@endif">
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A name is required') }}</div>
</div>
<div class="form-group">

View File

@ -10,15 +10,15 @@
<h1>
@yield('title')
<a class="btn btn-outline-dark" href="{{ $U('/location/new') }}">
<i class="fa fa-plus"></i>&nbsp;{{ $L('Add') }}
<i class="fas fa-plus"></i>&nbsp;{{ $L('Add') }}
</a>
</h1>
</div>
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -38,10 +38,10 @@
<tr>
<td class="fit-content">
<a class="btn btn-info btn-sm" href="{{ $U('/location/') }}{{ $location->id }}">
<i class="fa fa-pencil"></i>
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-danger btn-sm location-delete-button" href="#" data-location-id="{{ $location->id }}" data-location-name="{{ $location->name }}">
<i class="fa fa-trash"></i>
<i class="fas fa-trash"></i>
</a>
</td>
<td>

View File

@ -8,7 +8,7 @@
<div class="col-lg-6 offset-lg-3 col-xs-12">
<h1 class="text-center">@yield('title')</h1>
<form method="post" action="{{ $U('/login') }}" id="login-form">
<form method="post" action="{{ $U('/login') }}" id="login-form" novalidate>
<div class="form-group">
<label for="name">{{ $L('Username') }}</label>
@ -19,7 +19,7 @@
<div class="form-group">
<label for="name">{{ $L('Password') }}</label>
<input type="password" class="form-control" required id="password" name="password">
<div id="login-error" class="invalid-feedback"></div>
<div id="login-error" class="form-text text-danger d-none"></div>
</div>
<button id="login-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>

View File

@ -14,15 +14,15 @@
<h1>
@yield('title')
<a class="btn btn-outline-dark" href="{{ $U('/manageapikeys/new') }}">
<i class="fa fa-plus"></i>&nbsp;{{ $L('Add') }}
<i class="fas fa-plus"></i>&nbsp;{{ $L('Add') }}
</a>
</h1>
</div>
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -44,7 +44,7 @@
<tr id="apiKeyRow_{{ $apiKey->id }}">
<td class="fit-content">
<a class="btn btn-danger btn-sm apikey-delete-button" href="#" data-apikey-id="{{ $apiKey->id }}" data-apikey-apikey="{{ $apiKey->api_key }}">
<i class="fa fa-trash"></i>
<i class="fas fa-trash"></i>
</a>
</td>
<td>

View File

@ -19,12 +19,12 @@
<script>Grocy.EditObjectId = {{ $product->id }};</script>
@endif
<form id="product-form">
<form id="product-form" novalidate>
<div class="form-group">
<label for="name">{{ $L('Name') }}</label>
<input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $product->name}}@endif">
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A name is required') }}</div>
</div>
<div class="form-group">
@ -33,7 +33,7 @@
</div>
<div class="form-group tm-group">
<label for="barcode-taginput">{{ $L('Barcode(s)') }}&nbsp;&nbsp;<i class="fa fa-barcode"></i></label>
<label for="barcode-taginput">{{ $L('Barcode(s)') }}&nbsp;&nbsp;<i class="fas fa-barcode"></i></label>
<input type="text" class="form-control tm-input" id="barcode-taginput">
<div id="barcode-taginput-container"></div>
</div>
@ -45,19 +45,19 @@
<option @if($mode == 'edit' && $location->id == $product->location_id) selected="selected" @endif value="{{ $location->id }}">{{ $location->name }}</option>
@endforeach
</select>
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A location is required') }}</div>
</div>
<div class="form-group">
<label for="min_stock_amount">{{ $L('Minimum stock amount') }}</label>
<input required min="0" type="number" class="form-control" id="min_stock_amount" name="min_stock_amount" value="@if($mode == 'edit'){{ $product->min_stock_amount }}@else{{0}}@endif">
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('The amount cannot be lower than #1', '0') }}</div>
</div>
<div class="form-group">
<label for="default_best_before_days">{{ $L('Default best before days') }}<br><span class="small text-muted">{{ $L('For purchases this amount of days will be added to today for the best before date suggestion') }}</span></label>
<input required min="0" type="number" class="form-control" id="default_best_before_days" name="default_best_before_days" value="@if($mode == 'edit'){{ $product->default_best_before_days }}@else{{0}}@endif">
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('This cannot be negative') }}</div>
</div>
<div class="form-group">
@ -67,7 +67,7 @@
<option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_purchase) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
@endforeach
</select>
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A quantity unit is required') }}</div>
</div>
<div class="form-group">
@ -77,16 +77,16 @@
<option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_stock) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
@endforeach
</select>
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A quantity unit is required') }}</div>
</div>
<div class="form-group">
<label for="qu_factor_purchase_to_stock">{{ $L('Factor purchase to stock quantity unit') }}</label>
<input required min="1" type="number" class="form-control input-group-qu" id="qu_factor_purchase_to_stock" name="qu_factor_purchase_to_stock" value="@if ($mode == 'edit'){{ $product->qu_factor_purchase_to_stock }}@else{{1}}@endif">
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('The amount cannot be lower than #1', '1') }}</div>
</div>
<p id="qu-conversion-info" class="text-muted"></p>
<p id="qu-conversion-info" class="form-text text-muted small d-none"></p>
<button id="save-product-button" type="submit" class="btn btn-success">{{ $L('Save') }}</button>
</form>

View File

@ -10,15 +10,15 @@
<h1>
@yield('title')
<a class="btn btn-outline-dark" href="{{ $U('/product/new') }}">
<i class="fa fa-plus"></i>&nbsp;{{ $L('Add') }}
<i class="fas fa-plus"></i>&nbsp;{{ $L('Add') }}
</a>
</h1>
</div>
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -43,10 +43,10 @@
<tr>
<td class="fit-content">
<a class="btn btn-info btn-sm" href="{{ $U('/product/') }}{{ $product->id }}">
<i class="fa fa-pencil"></i>
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-danger btn-sm product-delete-button" href="#" data-product-id="{{ $product->id }}" data-product-name="{{ $product->name }}">
<i class="fa fa-trash"></i>
<i class="fas fa-trash"></i>
</a>
</td>
<td>

View File

@ -6,21 +6,21 @@
@section('content')
<div class="row">
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
<h1>@yield('title')</h1>
<form id="purchase-form">
<form id="purchase-form" novalidate>
<div class="form-group">
<label for="product_id">{{ $L('Product') }}&nbsp;&nbsp;<i class="fa fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted d-none">&nbsp;&nbsp;Barcode lookup is disabled</span></label>
<label for="product_id">{{ $L('Product') }}&nbsp;&nbsp;<i class="fas fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted d-none">&nbsp;&nbsp;Barcode lookup is disabled</span></label>
<select class="form-control combobox" id="product_id" name="product_id" required>
<option value=""></option>
@foreach($products as $product)
<option data-additional-searchdata="{{ $product->barcode }}" value="{{ $product->id }}">{{ $product->name }}</option>
@endforeach
</select>
<div class="invalid-feedback"></div>
<div id="flow-info-addbarcodetoselection" class="text-muted small d-none"><strong><span id="addbarcodetoselection"></span></strong> {{ $L('will be added to the list of barcodes for the selected product on submit') }}</div>
<div class="invalid-feedback">{{ $L('You have to select a product') }}</div>
<div id="flow-info-addbarcodetoselection" class="form-text text-muted small d-none"><strong><span id="addbarcodetoselection"></span></strong> {{ $L('will be added to the list of barcodes for the selected product on submit') }}</div>
</div>
@include('components.datepicker', array(
@ -31,7 +31,7 @@
<div class="form-group">
<label for="amount">{{ $L('Amount') }}&nbsp;&nbsp;<span id="amount_qu_unit" class="small text-muted"></span></label>
<input type="number" class="form-control" id="amount" name="amount" value="1" min="1" required>
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('The amount cannot be lower than #1', '1') }}</div>
</div>
<button id="save-purchase-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>
@ -39,7 +39,7 @@
</form>
</div>
<div class="col-lg-6 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
@include('components.productcard')
</div>
</div>

View File

@ -19,12 +19,12 @@
<script>Grocy.EditObjectId = {{ $quantityunit->id }};</script>
@endif
<form id="quantityunit-form">
<form id="quantityunit-form" novalidate>
<div class="form-group">
<label for="name">{{ $L('Name') }}</label>
<input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $quantityunit->name }}@endif">
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('A name is required') }}</div>
</div>
<div class="form-group">

View File

@ -10,15 +10,15 @@
<h1>
@yield('title')
<a class="btn btn-outline-dark" href="{{ $U('/quantityunit/new') }}">
<i class="fa fa-plus"></i>&nbsp;{{ $L('Add') }}
<i class="fas fa-plus"></i>&nbsp;{{ $L('Add') }}
</a>
</h1>
</div>
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -38,10 +38,10 @@
<tr>
<td class="fit-content">
<a class="btn btn-info btn-sm" href="{{ $U('/quantityunit/') }}{{ $quantityunit->id }}">
<i class="fa fa-pencil"></i>
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-danger btn-sm quantityunit-delete-button" href="#" data-quantityunit-id="{{ $quantityunit->id }}" data-quantityunit-name="{{ $quantityunit->name }}">
<i class="fa fa-trash"></i>
<i class="fas fa-trash"></i>
</a>
</td>
<td>

View File

@ -10,18 +10,18 @@
<h1>
@yield('title')
<a class="btn btn-outline-dark" href="{{ $U('/shoppinglistitem/new') }}">
<i class="fa fa-plus"></i>&nbsp;{{ $L('Add') }}
<i class="fas fa-plus"></i>&nbsp;{{ $L('Add') }}
</a>
<a id="add-products-below-min-stock-amount" class="btn btn-info" href="#">
<i class="fa fa-plus"></i>&nbsp;{{ $L('Add products that are below defined min. stock amount') }}
<i class="fas fa-plus"></i>&nbsp;{{ $L('Add products that are below defined min. stock amount') }}
</a>
</h1>
</div>
</div>
<div class="row mt-3">
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -40,11 +40,11 @@
@foreach($listItems as $listItem)
<tr class="@if($listItem->amount_autoadded > 0) table-info @endif">
<td class="fit-content">
<a class="btn btn-info" href="{{ $U('/shoppinglistitem/') }}{{ $listItem->id }}">
<i class="fa fa-pencil"></i>
<a class="btn btn-sm btn-info" href="{{ $U('/shoppinglistitem/') }}{{ $listItem->id }}">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-danger shoppinglist-delete-button" href="#" data-shoppinglist-id="{{ $listItem->id }}">
<i class="fa fa-trash"></i>
<a class="btn btn-sm btn-danger shoppinglist-delete-button" href="#" data-shoppinglist-id="{{ $listItem->id }}">
<i class="fas fa-trash"></i>
</a>
</td>
<td>

View File

@ -10,7 +10,7 @@
@section('content')
<div class="row">
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
<h1>@yield('title')</h1>
<script>Grocy.EditMode = '{{ $mode }}';</script>
@ -19,23 +19,22 @@
<script>Grocy.EditObjectId = {{ $listItem->id }};</script>
@endif
<form id="shoppinglist-form">
<form id="shoppinglist-form" novalidate>
<div class="form-group">
<label for="product_id">{{ $L('Product') }}&nbsp;&nbsp;<i class="fa fa-barcode"></i></label>
<label for="product_id">{{ $L('Product') }}&nbsp;&nbsp;<i class="fas fa-barcode"></i></label>
<select class="form-control combobox" id="product_id" name="product_id" value="@if($mode == 'edit') {{ $listItem->product_id }} @endif">
<option value=""></option>
@foreach($products as $product)
<option @if($mode == 'edit' && $product->id == $listItem->product_id) selected="selected" @endif data-additional-searchdata="{{ $product->barcode }}" value="{{ $product->id }}">{{ $product->name }}</option>
@endforeach
</select>
<div id="product-error" class="invalid-feedback"></div>
</div>
<div class="form-group">
<label for="amount">{{ $L('Amount') }}&nbsp;&nbsp;<span id="amount_qu_unit" class="small text-muted"></span><br><span class="small text-warning">@if($mode == 'edit' && $listItem->amount_autoadded > 0){{ $L('#1 units were automatically added and will apply in addition to the amount entered here', $listItem->amount_autoadded) }}@endif</span></label>
<input type="number" class="form-control" id="amount" name="amount" value="@if($mode == 'edit'){{ $listItem->amount }}@else{{1}}@endif" min="0" required>
<div class="invalid-feedback"></div>
<div class="invalid-feedback">{{ $L('This cannot be negative') }}</div>
</div>
<div class="form-group">
@ -48,7 +47,7 @@
</form>
</div>
<div class="col-lg-4 col-xs-12">
<div class="col-xs-12 col-md-6 col-xl-4">
@include('components.productcard')
</div>
</div>

View File

@ -19,8 +19,8 @@
</div>
<div class="row mt-3">
<div class="col-3">
<label for="location-filter">{{ $L('Filter by location') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="location-filter"><i class="fas fa-filter"></i> {{ $L('Filter by location') }}</label>
<select class="form-control" id="location-filter">
<option value="all">{{ $L('All') }}</option>
@foreach($locations as $location)
@ -28,8 +28,8 @@
@endforeach
</select>
</div>
<div class="col-3">
<label for="search">{{ $L('Search') }}</label>
<div class="col-xs-12 col-md-6 col-xl-3">
<label for="search"><i class="fas fa-search"></i> {{ $L('Search') }}</label>
<input type="text" class="form-control" id="search">
</div>
</div>
@ -55,14 +55,14 @@
data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}"
data-product-qu-name="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}"
data-consume-amount="1">
<i class="fa fa-cutlery"></i> 1
<i class="fas fa-utensils"></i> 1
</a>
<a id="product-{{ $currentStockEntry->product_id }}-consume-all-button" class="btn btn-danger btn-sm product-consume-button" href="#" title="{{ $L('Consume all #1 which are currently in stock', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name) }}"
data-product-id="{{ $currentStockEntry->product_id }}"
data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}"
data-product-qu-name="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}"
data-consume-amount="{{ $currentStockEntry->amount }}">
<i class="fa fa-cutlery"></i> {{ $L('All') }}
<i class="fas fa-utensils"></i> {{ $L('All') }}
</a>
</td>
<td>

View File

@ -6,6 +6,16 @@
version "1.1.8"
resolved "https://github.com/pallidus-fintech/bootstrap-combobox.git#0bd1da781b99d390f1c75315b6025e7d8658b263"
"@fortawesome/fontawesome-free@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.1.0.tgz#f35f5ba91366b7a58b0b6a4f22ff0907fe002219"
"TagManager@https://github.com/max-favilli/tagmanager.git#3.0.2", "tagmanager@https://github.com/max-favilli/tagmanager.git#3.0.2":
version "3.0.1"
resolved "https://github.com/max-favilli/tagmanager.git#df9eb9935c8585a392dfc00602f890caf233fa94"
dependencies:
jquery "1"
"bootbox@https://github.com/makeusabrew/bootbox.git#v5.x":
version "5.0.0"
resolved "https://github.com/makeusabrew/bootbox.git#8d843602d6ba7a2367829e01feee399d5f0a3a07"
@ -20,10 +30,6 @@ bootstrap-datepicker@^1.8.0:
version "0.0.0"
resolved "https://github.com/samrayner/bootstrap-side-navbar.git#bda4883fd2b278df3a48db4add7dc4d994477734"
bootstrap-validator@^0.11.9:
version "0.11.9"
resolved "https://registry.yarnpkg.com/bootstrap-validator/-/bootstrap-validator-0.11.9.tgz#fb7058eef53623e78f5aa7967026f98f875a9404"
bootstrap@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.0.0.tgz#ceb03842c145fcc1b9b4e15da2a05656ba68469a"
@ -101,7 +107,7 @@ datatables.net@1.10.19, datatables.net@^1.10.15, datatables.net@^1.10.19:
dependencies:
jquery ">=1.7"
font-awesome@4.7.0, font-awesome@^4.7.0:
font-awesome@4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133"
@ -131,7 +137,7 @@ moment-timezone@^0.5.11:
dependencies:
moment ">= 2.9.0"
"moment@>= 2.9.0", moment@^2.18.1, moment@^2.22.2:
"moment@>= 2.9.0", moment@^2.22.2:
version "2.22.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
@ -154,16 +160,10 @@ startbootstrap-sb-admin@^4.0.0:
jquery "3.3.1"
jquery.easing "^1.4.1"
swagger-ui-dist@^3.13.4:
swagger-ui-dist@^3.17.3:
version "3.17.3"
resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.17.3.tgz#dfb96408ccc46775155f7369190c5d4b2016fe5c"
"tagmanager@https://github.com/max-favilli/tagmanager.git#3.0.2":
version "3.0.1"
resolved "https://github.com/max-favilli/tagmanager.git#df9eb9935c8585a392dfc00602f890caf233fa94"
dependencies:
jquery "1"
tempusdominus-bootstrap-4@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/tempusdominus-bootstrap-4/-/tempusdominus-bootstrap-4-5.0.1.tgz#713d5d1547caf7784e510e480e32997ccbe7e511"
@ -174,13 +174,13 @@ tempusdominus-bootstrap-4@^5.0.1:
moment-timezone "^0.5.11"
popper.js "^1.12.9"
timeago@^1.6.1:
timeago@^1.6.3:
version "1.6.3"
resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.3.tgz#162a1adae99356297df59339837d09f1b0f36465"
dependencies:
jquery ">=1.2.3"
toastr@^2.1.3:
toastr@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181"
dependencies: