mirror of
https://github.com/grocy/grocy.git
synced 2025-09-16 17:56:51 +00:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
789e475207 | ||
|
eec5105e5b | ||
|
82f7b2109c | ||
|
840dd58c03 | ||
|
37d1377f99 | ||
|
882a3545e5 | ||
|
778191fd11 | ||
|
71701804ea | ||
|
306c404362 | ||
|
4fab4f87d3 | ||
|
54717a81b1 | ||
|
eca299454b | ||
|
c58083f84a | ||
|
ecf96252b9 | ||
|
92e648490a | ||
|
6dd3c26ddd | ||
|
02ea26b090 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,3 @@
|
||||
/public/bower_components
|
||||
/public/node_modules
|
||||
/vendor
|
||||
/.release
|
||||
|
4
.yarnrc
Normal file
4
.yarnrc
Normal file
@@ -0,0 +1,4 @@
|
||||
--modules-folder public/node_modules
|
||||
--install.production true
|
||||
--install.ignore-scripts true
|
||||
--install.ignore-optional true
|
16
README.md
16
README.md
@@ -11,16 +11,16 @@ A household needs to be managed. I did this so far (almost 10 years) with my fir
|
||||
For now my main focus is on stock management, ERP your fridge!
|
||||
|
||||
## How to install
|
||||
Just unpack the [latest release](https://github.com/berrnd/grocy/releases/latest) on your PHP (currently only tested with PHP 7.2) enabled webserver (webservers root should point to the `/public` directory), copy `config-dist.php` to `data/config.php`, edit it to your needs, ensure that the `data` directory is writable and you're ready to go.
|
||||
Just unpack the [latest release](https://github.com/berrnd/grocy/releases/latest) on your PHP (SQLite extension required, currently only tested with PHP 7.2) enabled webserver (webservers root should point to the `/public` directory), copy `config-dist.php` to `data/config.php`, edit it to your needs, ensure that the `data` directory is writable and you're ready to go.
|
||||
|
||||
Default login is user `admin` with password `admin` - see the `data/config.php` file. Alternatively clone this repository and install Composer and Bower dependencies manually.
|
||||
Default login is user `admin` with password `admin` - see the `data/config.php` file. Alternatively clone this repository and install Composer and Yarn dependencies manually.
|
||||
|
||||
If you use nginx as your webserver, please include `try_files $uri /index.php;` in your location block.
|
||||
|
||||
If, however, your webserver does not support URL rewriting, set `DISABLE_URL_REWRITING` in `data/config.php`.
|
||||
If, however, your webserver does not support URL rewriting, set `DISABLE_URL_REWRITING` in `data/config.php` (`Setting('DISABLE_URL_REWRITING', true);`).
|
||||
|
||||
## How to update
|
||||
Just overwrite everything with the latest release while keeping the `/data` directory, check `config-dist.php` for new configuration options and add them to your `data/config.php` (it will show up as an error if something is missing there).
|
||||
Just overwrite everything with the latest release while keeping the `/data` directory, check `config-dist.php` for new configuration options and add them to your `data/config.php` (the default from values `config-dist.php` will be used for not in `data/config.php` defined settings).
|
||||
|
||||
## Things worth to know
|
||||
|
||||
@@ -50,14 +50,18 @@ Products can be directly added to the database via looking them up against exter
|
||||
This is currently only possible through the REST API.
|
||||
There is no plugin included for any service, see the reference implementation in `data/plugins/DemoBarcodeLookupPlugin.php`.
|
||||
|
||||
### Localization
|
||||
grocy is fully localizable - the default language is English (integrated into code), a German localization is always maintained by me. There is one file per language in the `localization` directory, if you want to create a translation, it's best to copy `localization/de.php` to a new one (e. g. `localization/it.php`) and translating all strings there. (Language can be changed in `data/config.php`, e. g. `Setting('CULTURE', 'it');`)
|
||||
|
||||
### Database migrations
|
||||
Database schema migration is automatically done when visiting the root (`/`) route (click on the logo in the left upper edge).
|
||||
|
||||
### Demo mode
|
||||
When the file `data/demo.txt` exists, the application will work in a demo mode which means authentication is disabled and some demo data will be generated during the database schema migration.
|
||||
|
||||
### Other things
|
||||
When the file `data/add_before_end_body.html` exists, the contents of the file be added just before `</body>` on every page, useful for your own JS/CSS without to have to modify the application itself.
|
||||
### Adding your own CSS or JS without to have to modify the application itself
|
||||
- When the file `data/custom.js` exists, the contents of the file be added just before `</body>` on every page
|
||||
- When the file `data/custom.css` exists, the contents of the file be added just before `</head>` on every page
|
||||
|
||||
## Screenshots
|
||||
#### Dashboard
|
||||
|
1
app.php
1
app.php
@@ -8,6 +8,7 @@ use \Grocy\Controllers\LoginController;
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
require_once __DIR__ . '/data/config.php';
|
||||
require_once __DIR__ . '/config-dist.php'; //For not in own config defined values we use the default ones
|
||||
|
||||
// Setup base application
|
||||
$appContainer = new \Slim\Container([
|
||||
|
25
bower.json
25
bower.json
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "grocy",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"bootstrap": "^3.3.7",
|
||||
"font-awesome": "^4.7.0",
|
||||
"bootbox": "^4.4.0",
|
||||
"jquery.serializeJSON": "^2.8.1",
|
||||
"bootstrap-validator": "^0.11.9",
|
||||
"bootstrap-datepicker": "^1.7.1",
|
||||
"moment": "^2.18.1",
|
||||
"bootstrap-combobox": "^1.1.8",
|
||||
"datatables.net": "^1.10.15",
|
||||
"datatables.net-bs": "^2.1.1",
|
||||
"datatables.net-responsive": "^2.1.1",
|
||||
"datatables.net-responsive-bs": "^2.1.1",
|
||||
"jquery-timeago": "^1.6.1",
|
||||
"toastr": "^2.1.3",
|
||||
"tagmanager": "^3.0.2",
|
||||
"eonasdan-bootstrap-datetimepicker": "^4.17.47",
|
||||
"swagger-ui": "^3.13.4",
|
||||
"jquery-ui": "^1.12.1",
|
||||
"bootstrap-side-navbar": "^1.0.1"
|
||||
}
|
||||
}
|
@@ -4,10 +4,10 @@ if %projectPath:~-1%==\ set projectPath=%projectPath:~0,-1%
|
||||
set releasePath=%projectPath%\.release
|
||||
mkdir "%releasePath%"
|
||||
|
||||
for /f "tokens=*" %%a in ('type version.txt') do set version=%%a
|
||||
for /f "tokens=*" %%a in ('build_tools\jq.exe .Version version.json --raw-output') do set version=%%a
|
||||
|
||||
del "%releasePath%\grocy_%version%.zip"
|
||||
"build_tools\7za.exe" a -r "%releasePath%\grocy_%version%.zip" "%projectPath%\*" -xr!.* -xr!build_tools -xr!build.bat -xr!composer.json -xr!composer.lock -xr!bower.json -xr!publication_assets
|
||||
"build_tools\7za.exe" a -r "%releasePath%\grocy_%version%.zip" "%projectPath%\*" -xr!.* -xr!build_tools -xr!build.bat -xr!composer.json -xr!composer.lock -xr!package.json -xr!yarn.lock -xr!publication_assets
|
||||
"build_tools\7za.exe" a "%releasePath%\grocy_%version%.zip" "%projectPath%\public\.htaccess"
|
||||
"build_tools\7za.exe" rn "%releasePath%\grocy_%version%.zip" .htaccess public\.htaccess
|
||||
"build_tools\7za.exe" d "%releasePath%\grocy_%version%.zip" data\*.* data\sessions data\viewcache\*
|
||||
|
BIN
build_tools/jq.exe
Normal file
BIN
build_tools/jq.exe
Normal file
Binary file not shown.
137
composer.lock
generated
137
composer.lock
generated
@@ -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": []
|
||||
}
|
||||
|
@@ -1,26 +1,26 @@
|
||||
<?php
|
||||
|
||||
# Login credentials
|
||||
define('HTTP_USER', 'admin');
|
||||
define('HTTP_PASSWORD', 'admin');
|
||||
Setting('HTTP_USER', 'admin');
|
||||
Setting('HTTP_PASSWORD', 'admin');
|
||||
|
||||
# Either "production" or "dev"
|
||||
define('MODE', 'production');
|
||||
Setting('MODE', 'production');
|
||||
|
||||
# Either "en" or "de" or the filename (without extension) of
|
||||
# one of the other available localization files in the "/localization" directory
|
||||
define('CULTURE', 'en');
|
||||
Setting('CULTURE', 'en');
|
||||
|
||||
# The base url of your installation,
|
||||
# should be just "/" when running directly under the root of a (sub)domain
|
||||
# or for example "https:/example.com/grocy" when using a subdirectory
|
||||
define('BASE_URL', '/');
|
||||
Setting('BASE_URL', '/');
|
||||
|
||||
# The plugin to use for external barcode lookups,
|
||||
# must be the filename without .php extension and must be located in /data/plugins,
|
||||
# see /data/plugins/DemoBarcodeLookupPlugin.php for an example implementation
|
||||
define('STOCK_BARCODE_LOOKUP_PLUGIN', 'DemoBarcodeLookupPlugin');
|
||||
Setting('STOCK_BARCODE_LOOKUP_PLUGIN', 'DemoBarcodeLookupPlugin');
|
||||
|
||||
# If, however, your webserver does not support URL rewriting,
|
||||
# set this to true
|
||||
define('DISABLE_URL_REWRITING', false);
|
||||
Setting('DISABLE_URL_REWRITING', false);
|
||||
|
@@ -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'];
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ class BatteriesController extends BaseController
|
||||
$countDueNextXDays = count(FindAllItemsInArrayByValue($nextChargeTimes, date('Y-m-d', strtotime("+$nextXDays days")), '<'));
|
||||
$countOverdue = count(FindAllItemsInArrayByValue($nextChargeTimes, date('Y-m-d', strtotime('-1 days')), '<'));
|
||||
return $this->AppContainer->view->render($response, 'batteriesoverview', [
|
||||
'batteries' => $this->Database->batteries(),
|
||||
'batteries' => $this->Database->batteries()->orderBy('name'),
|
||||
'current' => $this->BatteriesService->GetCurrent(),
|
||||
'nextChargeTimes' => $nextChargeTimes,
|
||||
'nextXDays' => $nextXDays,
|
||||
@@ -38,14 +38,14 @@ class BatteriesController extends BaseController
|
||||
public function TrackChargeCycle(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batterytracking', [
|
||||
'batteries' => $this->Database->batteries()
|
||||
'batteries' => $this->Database->batteries()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
public function BatteriesList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteries', [
|
||||
'batteries' => $this->Database->batteries()
|
||||
'batteries' => $this->Database->batteries()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -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'];
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ class HabitsController extends BaseController
|
||||
$countDueNextXDays = count(FindAllItemsInArrayByValue($nextHabitTimes, date('Y-m-d', strtotime("+$nextXDays days")), '<'));
|
||||
$countOverdue = count(FindAllItemsInArrayByValue($nextHabitTimes, date('Y-m-d', strtotime('-1 days')), '<'));
|
||||
return $this->AppContainer->view->render($response, 'habitsoverview', [
|
||||
'habits' => $this->Database->habits(),
|
||||
'habits' => $this->Database->habits()->orderBy('name'),
|
||||
'currentHabits' => $this->HabitsService->GetCurrentHabits(),
|
||||
'nextHabitTimes' => $nextHabitTimes,
|
||||
'nextXDays' => $nextXDays,
|
||||
@@ -38,14 +38,14 @@ class HabitsController extends BaseController
|
||||
public function TrackHabitExecution(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'habittracking', [
|
||||
'habits' => $this->Database->habits()
|
||||
'habits' => $this->Database->habits()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
public function HabitsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'habits', [
|
||||
'habits' => $this->Database->habits()
|
||||
'habits' => $this->Database->habits()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -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'];
|
||||
}
|
||||
|
@@ -22,8 +22,9 @@ class StockController extends BaseController
|
||||
$countExpiringNextXDays = count(FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d', strtotime('+5 days')), '<'));
|
||||
$countAlreadyExpired = count(FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d', strtotime('-1 days')), '<'));
|
||||
return $this->AppContainer->view->render($response, 'stockoverview', [
|
||||
'products' => $this->Database->products(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'products' => $this->Database->products()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'currentStock' => $currentStock,
|
||||
'missingProducts' => $this->StockService->GetMissingProducts(),
|
||||
'nextXDays' => $nextXDays,
|
||||
@@ -35,21 +36,21 @@ class StockController extends BaseController
|
||||
public function Purchase(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'purchase', [
|
||||
'products' => $this->Database->products()
|
||||
'products' => $this->Database->products()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
public function Consume(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'consume', [
|
||||
'products' => $this->Database->products()
|
||||
'products' => $this->Database->products()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
public function Inventory(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'inventory', [
|
||||
'products' => $this->Database->products()
|
||||
'products' => $this->Database->products()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -57,8 +58,8 @@ class StockController extends BaseController
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'shoppinglist', [
|
||||
'listItems' => $this->Database->shopping_list(),
|
||||
'products' => $this->Database->products(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'products' => $this->Database->products()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'missingProducts' => $this->StockService->GetMissingProducts()
|
||||
]);
|
||||
}
|
||||
@@ -66,23 +67,23 @@ class StockController extends BaseController
|
||||
public function ProductsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'products', [
|
||||
'products' => $this->Database->products(),
|
||||
'locations' => $this->Database->locations(),
|
||||
'quantityunits' => $this->Database->quantity_units()
|
||||
'products' => $this->Database->products()->orderBy('name'),
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
public function LocationsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'locations', [
|
||||
'locations' => $this->Database->locations()
|
||||
'locations' => $this->Database->locations()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
public function QuantityUnitsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'quantityunits', [
|
||||
'quantityunits' => $this->Database->quantity_units()
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -91,8 +92,8 @@ class StockController extends BaseController
|
||||
if ($args['productId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'productform', [
|
||||
'locations' => $this->Database->locations(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
@@ -100,8 +101,8 @@ class StockController extends BaseController
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'productform', [
|
||||
'product' => $this->Database->products($args['productId']),
|
||||
'locations' => $this->Database->locations(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
@@ -146,7 +147,7 @@ class StockController extends BaseController
|
||||
if ($args['itemId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'shoppinglistform', [
|
||||
'products' => $this->Database->products(),
|
||||
'products' => $this->Database->products()->orderBy('name'),
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
@@ -154,7 +155,7 @@ class StockController extends BaseController
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'shoppinglistform', [
|
||||
'listItem' => $this->Database->shopping_list($args['itemId']),
|
||||
'products' => $this->Database->products(),
|
||||
'products' => $this->Database->products()->orderBy('name'),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
|
@@ -110,3 +110,28 @@ 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;
|
||||
}
|
||||
|
||||
function BoolToString(bool $bool)
|
||||
{
|
||||
return $bool ? 'true' : 'false';
|
||||
}
|
||||
|
||||
function Setting(string $name, string $value)
|
||||
{
|
||||
if (!defined($name))
|
||||
{
|
||||
define($name, $value);
|
||||
}
|
||||
}
|
||||
|
@@ -129,6 +129,21 @@ return array(
|
||||
'All' => 'Alle',
|
||||
'Track charge cycle of battery #1' => 'Erfasse einen Ladezyklus für Batterie #1',
|
||||
'Track execution of habit #1' => 'Erfasse eine Ausführung von #1',
|
||||
'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',
|
||||
'A best before date is required and must be later than today' => 'Ein Mindesthaltbarkeitsdatum ist erforderlich und muss später als heute sein',
|
||||
'Settings' => 'Einstellungen',
|
||||
'This can only be before now' => 'Dies kann nur vor jetzt sein',
|
||||
|
||||
//Constants
|
||||
'manually' => 'Manuell',
|
||||
@@ -138,7 +153,6 @@ return array(
|
||||
'timeago_locale' => 'de',
|
||||
'timeago_nan' => 'vor NaN Jahren',
|
||||
'moment_locale' => 'de',
|
||||
'bootstrap_datepicker_locale' => 'de',
|
||||
'datatables_localization' => '{"sEmptyTable":"Keine Daten in der Tabelle vorhanden","sInfo":"_START_ bis _END_ von _TOTAL_ Einträgen","sInfoEmpty":"Keine Daten vorhanden","sInfoFiltered":"(gefiltert von _MAX_ Einträgen)","sInfoPostFix":"","sInfoThousands":".","sLengthMenu":"_MENU_ Einträge anzeigen","sLoadingRecords":"Wird geladen ..","sProcessing":"Bitte warten ..","sSearch":"Suchen","sZeroRecords":"Keine Einträge vorhanden","oPaginate":{"sFirst":"Erste","sPrevious":"Zurück","sNext":"Nächste","sLast":"Letzte"},"oAria":{"sSortAscending":": aktivieren, um Spalte aufsteigend zu sortieren","sSortDescending":": aktivieren, um Spalte absteigend zu sortieren"},"select":{"rows":{"0":"Zum Auswählen auf eine Zeile klicken","1":"1 Zeile ausgewählt","_":"%d Zeilen ausgewählt"}},"buttons":{"print":"Drucken","colvis":"Spalten","copy":"Kopieren","copyTitle":"In Zwischenablage kopieren","copyKeys":"Taste <i>ctrl</i> oder <i>⌘</i> + <i>C</i> um Tabelle<br>in Zwischenspeicher zu kopieren.<br><br>Um abzubrechen die Nachricht anklicken oder Escape drücken.","copySuccess":{"1":"1 Spalte kopiert","_":"%d Spalten kopiert"}}}',
|
||||
|
||||
//Demo data
|
||||
|
@@ -9,6 +9,5 @@ return array(
|
||||
'timeago_locale' => 'en',
|
||||
'timeago_nan' => 'NaN years ago',
|
||||
'moment_locale' => '',
|
||||
'bootstrap_datepicker_locale' => '',
|
||||
'datatables_localization' => '{"sEmptyTable":"No data available in table","sInfo":"Showing _START_ to _END_ of _TOTAL_ entries","sInfoEmpty":"Showing 0 to 0 of 0 entries","sInfoFiltered":"(filtered from _MAX_ total entries)","sInfoPostFix":"","sInfoThousands":",","sLengthMenu":"Show _MENU_ entries","sLoadingRecords":"Loading...","sProcessing":"Processing...","sSearch":"Search:","sZeroRecords":"No matching records found","oPaginate":{"sFirst":"First","sLast":"Last","sNext":"Next","sPrevious":"Previous"},"oAria":{"sSortAscending":": activate to sort column ascending","sSortDescending":": activate to sort column descending"}}'
|
||||
);
|
||||
|
188
localization/it.php
Normal file
188
localization/it.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Stock overview' => 'Dispensa',
|
||||
'#1 products with #2 units in stock' => '#1 prodotti stano per finire(#2 unità)',
|
||||
'#1 products expiring within the next #2 days' => '#1 prodotti scadranno tra #2 giorni',
|
||||
'#1 products are already expired' => '#1 prodotti scaduti',
|
||||
'#1 products are below defined min. stock amount' => '#1 prodotti sotto il limite minimo',
|
||||
'Product' => 'prodotto',
|
||||
'Amount' => 'quantità',
|
||||
'Next best before date' => 'Prossima data di scadenza',
|
||||
'Logout' => 'Logout',
|
||||
'Habits overview' => 'Riepilogo delle abitudini',
|
||||
'Batteries overview' => 'Riepilogo delle batterie',
|
||||
'Purchase' => 'Acquisti',
|
||||
'Consume' => 'Consumi',
|
||||
'Inventory' => 'Inventario',
|
||||
'Shopping list' => 'Lista della spesa',
|
||||
'Habit tracking' => 'Dati abitudini',
|
||||
'Battery tracking' => 'Dati batterie',
|
||||
'Products' => 'Prodotti',
|
||||
'Locations' => 'Posizioni',
|
||||
'Quantity units' => 'Unità di misura',
|
||||
'Habits' => 'Abitudini',
|
||||
'Batteries' => 'Batterie',
|
||||
'Habit' => 'Abitudine',
|
||||
'Next estimated tracking' => 'Prossima esecuzione',
|
||||
'Last tracked' => 'Ultima esecuzione',
|
||||
'Battery' => 'Batterie',
|
||||
'Last charged' => 'Ultima ricarica',
|
||||
'Next planned charge cycle' => 'Prossima ricarica',
|
||||
'Best before' => 'Data di scadenza',
|
||||
'OK' => 'OK',
|
||||
'Product overview' => 'Riepilogo dei prodotti',
|
||||
'Stock quantity unit' => 'Unità di misura',
|
||||
'Stock amount' => 'Quantità',
|
||||
'Last purchased' => 'Ultimo acquisto',
|
||||
'Last used' => 'Ultimo utilizzo',
|
||||
'Spoiled' => 'Scaduto',
|
||||
'Barcode lookup is disabled' => 'I codici a barre sono disabilitati',
|
||||
'will be added to the list of barcodes for the selected product on submit' => 'sarà aggiunto alla lista dei codici a barre per questo prodotto',
|
||||
'New amount' => 'Nuova quantità',
|
||||
'Note' => 'Nota',
|
||||
'Tracked time' => 'Ora di esecuzione',
|
||||
'Habit overview' => 'Riepilogo dell\'abitudine',
|
||||
'Tracked count' => 'Numero di esecuzioni',
|
||||
'Battery overview' => 'Riepilogo della batteria',
|
||||
'Charge cycles count' => 'Numero di ricariche',
|
||||
'Create shopping list item' => 'Aggiungi un prodotto alla lista della spesa',
|
||||
'Edit shopping list item' => 'Modifica un\'entrata della lista della spesa',
|
||||
'#1 units were automatically added and will apply in addition to the amount entered here' => '#1 sono state aggiunte automaticamente',
|
||||
'Save' => 'Salva',
|
||||
'Add' => 'Aggiungi',
|
||||
'Name' => 'Nome',
|
||||
'Location' => 'Posizione',
|
||||
'Min. stock amount' => 'Quantità minima',
|
||||
'QU purchase' => 'Unità di acquisto',
|
||||
'QU stock' => 'Unità di dispensa',
|
||||
'QU factor' => 'Fattore di conversione',
|
||||
'Description' => 'Descrizione',
|
||||
'Create product' => 'Aggiungi prodotto',
|
||||
'Barcode(s)' => 'Codice a barre',
|
||||
'Minimum stock amount' => 'Quantità minima',
|
||||
'Default best before days' => 'Data di scadenza standard in giorni',
|
||||
'Quantity unit purchase' => 'Unità di acquisto',
|
||||
'Quantity unit stock' => 'Unità di dispensa',
|
||||
'Factor purchase to stock quantity unit' => 'Fattore di conversione tra quantità di acquisto e di dispensa',
|
||||
'Create location' => 'Aggiungi posizione',
|
||||
'Create quantity unit' => 'Aggiungi unità di misura',
|
||||
'Period type' => 'Tipo di ripetizione',
|
||||
'Period days' => 'Periodo in giorni',
|
||||
'Create habit' => 'Aggiungi abitudine',
|
||||
'Used in' => 'Usato in',
|
||||
'Create battery' => 'Aggiungi batteria',
|
||||
'Edit battery' => 'Modifica batteria',
|
||||
'Edit habit' => 'Modifica abitudine',
|
||||
'Edit quantity unit' => 'Modifica unità di misura',
|
||||
'Edit product' => 'Modifica prodotto',
|
||||
'Edit location' => 'Modifica posizione',
|
||||
'Record data' => 'Registra dati',
|
||||
'Manage master data' => 'Gestisci dati',
|
||||
'This will apply to added products' => 'Verrà applicato ai prodotti aggiunti',
|
||||
'never' => 'mai',
|
||||
'Add products that are below defined min. stock amount' => 'Aggiungi prodotti sotti il limite minimo',
|
||||
'For purchases this amount of days will be added to today for the best before date suggestion' => 'Questo numero di giorni verrà aggiunto alla data di acquisto per la data di scadenza',
|
||||
'This means 1 #1 purchased will be converted into #2 #3 in stock' => 'Questo significa che 1 #1 acquistato diventerà #2 #3 in dispensa',
|
||||
'Login' => 'Login',
|
||||
'Username' => 'Username',
|
||||
'Password' => 'Password',
|
||||
'Invalid credentials, please try again' => 'Credenziali non valide, per favore riprova',
|
||||
'Are you sure to delete battery "#1"?' => 'Sei sicuro di voler eliminare la batteria "#1"?',
|
||||
'Yes' => 'Si',
|
||||
'No' => 'No',
|
||||
'Are you sure to delete habit "#1"?' => 'Sei sicuro di voler eliminare l\'abitudine "#1"?',
|
||||
'"#1" could not be resolved to a product, how do you want to proceed?' => '"#1" non è stato associato a nessun prodotto, vuoi procedere?',
|
||||
'Create or assign product' => 'Aggiungi o assegna prodotto',
|
||||
'Cancel' => 'Annulla',
|
||||
'Add as new product' => 'Aggiungi come nuovo prodotto',
|
||||
'Add as barcode to existing product' => 'Assegna il codice a barre ad un prodotto',
|
||||
'Add as new product and prefill barcode' => 'Aggiungi come nuovo prodotto ed assegna il codice a barre',
|
||||
'Are you sure to delete quantity unit "#1"?' => 'Sei sicuro di voler eliminare l\'unità di misura "#1"?',
|
||||
'Are you sure to delete product "#1"?' => 'Sei sicuro di voler eliminare il prodotto "#1"?',
|
||||
'Are you sure to delete location "#1"?' => 'Sei sicuro di voler eliminare la posizione "#1"?',
|
||||
'Manage API keys' => 'Gestisci le chiavi API',
|
||||
'REST API & data model documentation' => 'REST API & Documentazione del modello di dati',
|
||||
'API keys' => 'Chiavi API',
|
||||
'Create new API key' => 'Crea nuova chiave API',
|
||||
'API key' => 'Chiave API',
|
||||
'Expires' => 'Scade il',
|
||||
'Created' => 'Creata il',
|
||||
'This product is not in stock' => 'Questo prodotto non è in dispensa',
|
||||
'This means #1 will be added to stock' => '#1 sarà aggiunto alla dispensa',
|
||||
'This means #1 will be removed from stock' => '#1 sarà rimosso dalla dispensa',
|
||||
'This means it is estimated that a new execution of this habit is tracked #1 days after the last was tracked' => 'L\'esecuzione dell\'abitudine è #1 giorni dopo la precedente',
|
||||
'Removed #1 #2 of #3 from stock' => '#1 #2 su #3 rimossi dalla dispensa',
|
||||
'About grocy' => 'Riguardo grocy',
|
||||
'Close' => 'Chiudi',
|
||||
'#1 batteries are due to be charged within the next #2 days' => '#1 batterie da ricaricare entro #2 giorni',
|
||||
'#1 batteries are overdue to be charged' => '#1 batterie devono essere ricaricate',
|
||||
'#1 habits are due to be done within the next #2 days' => '#1 abitudini da eseguire entro #2 giorni',
|
||||
'#1 habits are overdue to be done' => '#1 abitudini da eseguire',
|
||||
'Released on' => 'Rilasciato il',
|
||||
'Consume #3 #1 of #2' => 'Consumati #3 #1 di #2',
|
||||
'Added #1 #2 of #3 to stock' => 'Aggiunti #1 #2 di #3',
|
||||
'Stock amount of #1 is now #2 #3' => 'La quantità in dispensa di #1 è ora #2 #3',
|
||||
'Tracked execution of habit #1 on #2' => 'Esecuzione dell\'abitudine #1 registrata il #2',
|
||||
'Tracked charge cylce of battery #1 on #2' => 'Ricarica della batteria #1 effettuata il #2',
|
||||
'Consume all #1 which are currently in stock' => 'Consuma tutto #1 in dispensa',
|
||||
'All' => 'Tutto',
|
||||
'Track charge cycle of battery #1' => 'Registra la ricarica della batteria #1',
|
||||
'Track execution of habit #1' => 'Registra l\'esecuzione dell\'abitudine #1',
|
||||
'Filter by location' => 'Filtra per posizione',
|
||||
'Search' => 'Cerca',
|
||||
'Not logged in' => 'Non autenticato',
|
||||
'You have to select a product' => 'Devi selezionare un prodotto',
|
||||
'You have to select a habit' => 'Devi selezionare un\'abitudine',
|
||||
'You have to select a battery' => 'Devi selezionare una batteria',
|
||||
'A name is required' => 'Inserisci un nome',
|
||||
'A location is required' => 'Inserisci la posizione',
|
||||
'The amount cannot be lower than #1' => 'La quantità non può essere minore di #1',
|
||||
'This cannot be negative' => 'Il numero non può essere negativo',
|
||||
'A quantity unit is required' => 'Inserisci un\'unità di misura',
|
||||
'A period type is required' => 'Seleziona un tipo di ripetizione',
|
||||
|
||||
//Constants
|
||||
'manually' => 'Manualmente',
|
||||
'dynamic-regular' => 'Regolatore dinamico',
|
||||
|
||||
//Technical component translations
|
||||
'timeago_locale' => 'it',
|
||||
'timeago_nan' => 'NaN anni fa',
|
||||
'moment_locale' => 'it',
|
||||
'bootstrap_datepicker_locale' => 'it',
|
||||
'datatables_localization' => '{"sEmptyTable":"Nessun dato disponibile","sInfo":"Mostrando da _START_ a _END_ di _TOTAL_ voci","sInfoEmpty":"Mostrando da 0 a 0 di 0 voci","sInfoFiltered":"(Filtrato da _MAX_ voci totali)","sInfoPostFix":"","sInfoThousands":",","sLengthMenu":"Mostra _MENU_ voci","sLoadingRecords":"Caricando...","sProcessing":"Calcolando...","sSearch":"Cerca:","sZeroRecords":"Nessun risultato trovato","oPaginate":{"sFirst":"Prima","sLast":"Ultima","sNext":"Prossima","sPrevious":"Precedente"},"oAria":{"sSortAscending":": ordine crescente","sSortDescending":": ordine decrescente"}}',
|
||||
|
||||
//Demo data
|
||||
'Cookies' => 'Biscotti',
|
||||
'Chocolate' => 'Cioccolato',
|
||||
'Pantry' => 'Vorratskammer',
|
||||
'Candy cupboard' => 'Süßigkeitenschrank',
|
||||
'Tinned food cupboard' => 'Konservenschrank',
|
||||
'Fridge' => 'Kühlschrank',
|
||||
'Piece' => 'Pezzo',
|
||||
'Pack' => 'Pacco',
|
||||
'Glass' => 'Bicchiere',
|
||||
'Tin' => 'Scatola',
|
||||
'Can' => 'Lattina',
|
||||
'Bunch' => 'Cespo',
|
||||
'Gummy bears' => 'Caramelle',
|
||||
'Crisps' => 'Patatine',
|
||||
'Eggs' => 'Uova',
|
||||
'Noodles' => 'Spaghetti',
|
||||
'Pickles' => 'Marmellata',
|
||||
'Gulash soup' => 'Dado',
|
||||
'Yogurt' => 'Yogurt',
|
||||
'Cheese' => 'Parmigiano',
|
||||
'Cold cuts' => 'Pancetta',
|
||||
'Paprika' => 'Pepe',
|
||||
'Cucumber' => 'Zucchine',
|
||||
'Radish' => 'Radicchio',
|
||||
'Tomato' => 'Pomodori',
|
||||
'Changed towels in the bathroom' => 'Cambiare asciugamani in bagno',
|
||||
'Cleaned the kitchen floor' => 'Pulire la cucina',
|
||||
'Warranty ends' => 'Scadenza dalla garanzia',
|
||||
'TV remote control' => 'Telecomando',
|
||||
'Alarm clock' => 'Sveglia',
|
||||
'Heat remote control' => 'Termostato'
|
||||
);
|
26
package.json
Normal file
26
package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "grocy",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@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-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",
|
||||
"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",
|
||||
"timeago": "^1.6.3",
|
||||
"toastr": "^2.1.4"
|
||||
}
|
||||
}
|
@@ -1,118 +1,26 @@
|
||||
body {
|
||||
padding-top: 50px;
|
||||
/* Main style customizations */
|
||||
body {
|
||||
font-family: 'Noto Sans', sans-serif;
|
||||
}
|
||||
|
||||
.navbar-fixed-top {
|
||||
background-color: #e5e5e5;
|
||||
border-bottom: 2px solid;
|
||||
border-color: #d6d6d6;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-weight: bold;
|
||||
letter-spacing: -5px;
|
||||
font-size: 2.2em;
|
||||
color: #0b024c !important;
|
||||
margin-left: 0 !important;
|
||||
padding-left: 5px !important;
|
||||
|
||||
}
|
||||
|
||||
.navbar-fixed-side {
|
||||
top: 51px;
|
||||
padding-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
background-color: #e5e5e5;
|
||||
border-right: 2px solid #d6d6d6;
|
||||
max-width: 260px;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
#navbar-mobile {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.nav-copyright {
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.navbar-brand {
|
||||
margin-left: 25px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-nav > li > a {
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.sidebar-nav > li > a:hover {
|
||||
box-shadow: inset 5px 0 0 #337ab7;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.sidebar-nav > li > a:focus {
|
||||
box-shadow: inset 5px 0 0 #ab2230;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.sidebar-nav > .active > a,
|
||||
.sidebar-nav > .active > a:hover,
|
||||
.sidebar-nav > .active > a:focus {
|
||||
background-color: #d6d6d6;
|
||||
box-shadow: inset 5px 0 0 #ab2230;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.nav > li.disabled > a,
|
||||
.navbar-default .navbar-nav > .disabled > a {
|
||||
color: #a7a7a7;
|
||||
}
|
||||
|
||||
.nav-copyright {
|
||||
color: #a7a7a7;
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nav-copyright > li > a {
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav > .open > a {
|
||||
background-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background-color: #e5e5e5 !important;
|
||||
}
|
||||
|
||||
.well {
|
||||
background-color: #e5e5e5;
|
||||
padding-right: 25px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: middle !important;
|
||||
.content-text {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.responsive-button {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.discrete-link {
|
||||
.no-real-button {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.timeago-contextual {
|
||||
font-style: italic;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
a.discrete-link {
|
||||
color: inherit !important;
|
||||
transition: all 0.3s !important;
|
||||
}
|
||||
@@ -120,65 +28,131 @@ td {
|
||||
a.discrete-link:hover {
|
||||
color: #337ab7 !important;
|
||||
text-decoration: none !important;
|
||||
transition: all 0.3s !important;
|
||||
}
|
||||
|
||||
a.discrete-link:focus {
|
||||
color: #ab2230 !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.card {
|
||||
border: 2px solid;
|
||||
border-color: #d6d6d6;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
|
||||
.content-text .invalid-feedback {
|
||||
font-size: 95%;
|
||||
}
|
||||
|
||||
/* Navigation style customizations */
|
||||
#mainNav {
|
||||
background-color: #e5e5e5 !important;
|
||||
border-bottom: 2px solid !important;
|
||||
border-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
.navbar-sidenav {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.navbar-sidenav,
|
||||
.sidenav-second-level {
|
||||
background-color: #e5e5e5 !important;
|
||||
border-top: 2px solid !important;
|
||||
border-right: 2px solid !important;
|
||||
border-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
.navbar-nav .dropdown-menu {
|
||||
background-color: #e5e5e5 !important;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.navbar-nav .dropdown-divider {
|
||||
border-top: 2px solid !important;
|
||||
border-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
.sidenav-toggler {
|
||||
background-color: #d6d6d6 !important;
|
||||
border-right: 2px solid !important;
|
||||
border-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
.navbar-sidenav > li,
|
||||
.sidenav-second-level > li {
|
||||
transition: all 0.3s !important;
|
||||
}
|
||||
|
||||
.navbar-sidenav > li:hover,
|
||||
.sidenav-second-level > li:hover,
|
||||
.navbar-nav .dropdown-item:hover {
|
||||
box-shadow: inset 5px 0 0 #337ab7 !important;
|
||||
background-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
.navbar-sidenav > li > a:focus,
|
||||
.sidenav-second-level > li > a:focus,
|
||||
.navbar-nav .dropdown-item:focus {
|
||||
box-shadow: inset 5px 0 0 #ab2230 !important;
|
||||
background-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
.active-page {
|
||||
box-shadow: inset 5px 0 0 #ab2230 !important;
|
||||
background-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
/* Third party component customizations - DataTables */
|
||||
td {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
.table td.fit-content,
|
||||
.table th.fit-content {
|
||||
white-space: nowrap;
|
||||
width: 1%;
|
||||
}
|
||||
|
||||
.dataTables_info,
|
||||
.dataTables_length,
|
||||
.dataTables_filter {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.timeago-contextual {
|
||||
font-style: italic;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.disabled,
|
||||
.no-real-button {
|
||||
pointer-events: none;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.discrete-content-separator-2x {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.warning-bg {
|
||||
background-color: #fcf8e3 !important;
|
||||
}
|
||||
|
||||
.error-bg {
|
||||
background-color: #f2dede !important;
|
||||
}
|
||||
|
||||
.info-bg {
|
||||
background-color: #afd9ee !important;
|
||||
.dataTables_filter,
|
||||
.dataTables_info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Third party component customizations - toastr */
|
||||
#toast-container > div {
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
|
||||
.toast-success {
|
||||
background-color: #4c994c;
|
||||
background-color: #28a745;
|
||||
}
|
||||
|
||||
.toast-error {
|
||||
background-color: #dc3545;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB |
20
public/img/grocy_icon.svg
Normal file
20
public/img/grocy_icon.svg
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="60.000000pt" height="93.000000pt" viewBox="0 0 60.000000 93.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.15, written by Peter Selinger 2001-2017
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,93.000000) scale(0.100000,-0.100000)"
|
||||
fill="#0b024c" stroke="none">
|
||||
<path d="M165 905 c-52 -18 -109 -82 -132 -148 -14 -39 -18 -82 -18 -172 0
|
||||
-104 3 -127 23 -170 43 -94 114 -144 205 -145 59 0 112 21 156 63 l33 32 -7
|
||||
-75 c-10 -96 -17 -116 -57 -140 -43 -26 -130 -26 -233 0 -43 11 -80 20 -82 20
|
||||
-2 0 -3 -30 -1 -67 l3 -68 50 -13 c28 -8 100 -14 160 -15 172 -1 255 38 304
|
||||
142 l26 56 3 353 4 352 -75 0 -75 0 -7 -40 -7 -40 -36 31 c-67 59 -150 75
|
||||
-237 44z m206 -141 c45 -23 62 -72 62 -180 1 -112 -18 -152 -79 -172 -125 -42
|
||||
-201 80 -163 260 21 96 97 135 180 92z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1002 B |
33
public/img/grocy_logo.svg
Normal file
33
public/img/grocy_logo.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="242.000000pt" height="93.000000pt" viewBox="0 0 242.000000 93.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.15, written by Peter Selinger 2001-2017
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,93.000000) scale(0.100000,-0.100000)"
|
||||
fill="#0b024c" stroke="none">
|
||||
<path d="M165 905 c-52 -18 -109 -82 -132 -148 -14 -39 -18 -82 -18 -172 0
|
||||
-104 3 -127 23 -170 43 -94 114 -144 205 -145 59 0 112 21 156 63 l33 32 -7
|
||||
-75 c-10 -96 -17 -116 -57 -140 -43 -26 -130 -26 -233 0 -43 11 -80 20 -82 20
|
||||
-2 0 -3 -30 -1 -67 l3 -68 50 -13 c28 -8 100 -14 160 -15 121 -1 183 14 244
|
||||
60 36 28 81 112 81 155 0 54 6 58 90 58 l78 0 4 193 c3 180 4 194 25 223 20
|
||||
28 99 72 110 61 2 -3 -1 -24 -6 -48 -6 -24 -11 -79 -11 -121 0 -137 53 -233
|
||||
158 -285 50 -24 69 -28 147 -28 107 0 158 20 219 83 l40 41 23 -34 c13 -20 46
|
||||
-45 80 -62 51 -25 69 -28 153 -28 68 0 108 5 143 18 l47 19 0 74 0 74 -42 -21
|
||||
c-58 -30 -154 -37 -197 -15 -85 44 -98 250 -21 328 24 24 36 28 84 28 99 0 92
|
||||
9 200 -260 l97 -242 -23 -46 c-32 -65 -67 -87 -134 -87 l-54 0 0 -66 0 -67 45
|
||||
-6 c108 -17 215 34 269 128 20 33 296 754 296 771 0 3 -40 5 -89 5 l-90 0 -64
|
||||
-197 c-35 -109 -69 -214 -75 -233 -10 -34 -10 -34 -11 -7 -1 16 -31 120 -68
|
||||
232 l-66 202 -143 8 c-116 5 -154 4 -197 -9 -61 -18 -126 -61 -145 -98 l-14
|
||||
-25 -52 53 c-40 39 -67 56 -106 68 -87 26 -181 19 -272 -19 -14 -5 -18 -2 -18
|
||||
14 0 19 -6 21 -52 21 -64 0 -129 -30 -164 -76 -15 -19 -30 -34 -34 -34 -4 0
|
||||
-13 23 -20 50 l-12 50 -133 0 -133 0 -7 -40 -7 -40 -36 31 c-67 59 -150 75
|
||||
-237 44z m206 -141 c45 -23 62 -72 62 -180 1 -112 -18 -152 -79 -172 -125 -42
|
||||
-201 80 -163 260 21 96 97 135 180 92z m888 -10 c40 -33 54 -89 49 -184 -7
|
||||
-118 -41 -160 -131 -160 -87 0 -121 53 -121 185 0 135 34 185 125 185 36 0 55
|
||||
-6 78 -26z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
@@ -21,8 +21,8 @@ U = function(relativePath)
|
||||
|
||||
if (!Grocy.ActiveNav.isEmpty())
|
||||
{
|
||||
var menuItem = $('.nav').find("[data-nav-for-page='" + Grocy.ActiveNav + "']");
|
||||
menuItem.addClass('active');
|
||||
var menuItem = $('#sidebarResponsive').find("[data-nav-for-page='" + Grocy.ActiveNav + "']");
|
||||
menuItem.addClass('active-page');
|
||||
}
|
||||
|
||||
$.timeago.settings.allowFuture = true;
|
||||
@@ -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');
|
||||
}
|
||||
|
@@ -1,4 +1,25 @@
|
||||
$(document).on('click', '.battery-delete-button', function(e)
|
||||
var batteriesTable = $('#batteries-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
batteriesTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.battery-delete-button', function (e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-battery-name');
|
||||
var objectId = $(e.currentTarget).attr('data-battery-id');
|
||||
@@ -33,12 +54,3 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#batteries-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
});
|
||||
|
@@ -1,10 +1,22 @@
|
||||
$('#batteries-overview-table').DataTable({
|
||||
'pageLength': 50,
|
||||
var batteriesOverviewTable = $('#batteries-overview-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[2, 'desc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
batteriesOverviewTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.track-charge-cycle-button', function(e)
|
||||
|
@@ -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');
|
||||
|
@@ -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');
|
||||
});
|
||||
|
@@ -1,92 +0,0 @@
|
||||
$(function()
|
||||
{
|
||||
$('.datepicker').datepicker(
|
||||
{
|
||||
format: 'yyyy-mm-dd',
|
||||
startDate: '+0d',
|
||||
todayHighlight: true,
|
||||
autoclose: true,
|
||||
calendarWeeks: true,
|
||||
orientation: 'bottom auto',
|
||||
weekStart: 1,
|
||||
showOnFocus: false,
|
||||
language: L('bootstrap_datepicker_locale')
|
||||
});
|
||||
$('.datepicker').trigger('change');
|
||||
|
||||
EmptyElementWhenMatches('#datepicker-timeago', L('timeago_nan'));
|
||||
});
|
||||
|
||||
$('.datepicker').on('keydown', function(e)
|
||||
{
|
||||
if (e.keyCode === 13) //Enter
|
||||
{
|
||||
$('.datepicker').trigger('change');
|
||||
}
|
||||
});
|
||||
|
||||
$('.datepicker').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'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.datepicker').on('change', function(e)
|
||||
{
|
||||
var value = $('.datepicker').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');
|
||||
$('.datepicker').val(value);
|
||||
}
|
||||
|
||||
$('#datepicker-timeago').text($.timeago($('.datepicker').val()));
|
||||
EmptyElementWhenMatches('#datepicker-timeago', L('timeago_nan'));
|
||||
});
|
||||
|
||||
$('#datepicker-button').on('click', function(e)
|
||||
{
|
||||
$('.datepicker').datepicker('show');
|
||||
});
|
@@ -1,11 +1,162 @@
|
||||
$(function()
|
||||
Grocy.Components.DateTimePicker = { };
|
||||
|
||||
Grocy.Components.DateTimePicker.GetInputElement = function()
|
||||
{
|
||||
$('.datetimepicker').datetimepicker(
|
||||
{
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
showTodayButton: true,
|
||||
calendarWeeks: true,
|
||||
maxDate: moment(),
|
||||
locale: moment.locale('de')
|
||||
});
|
||||
return $('.datetimepicker').find('input');
|
||||
}
|
||||
|
||||
Grocy.Components.DateTimePicker.GetValue = function()
|
||||
{
|
||||
return Grocy.Components.DateTimePicker.GetInputElement().val();
|
||||
}
|
||||
|
||||
Grocy.Components.DateTimePicker.SetValue = function(value)
|
||||
{
|
||||
Grocy.Components.DateTimePicker.GetInputElement().val(value);
|
||||
Grocy.Components.DateTimePicker.GetInputElement().trigger('change');
|
||||
}
|
||||
|
||||
var startDate = null;
|
||||
if (Grocy.Components.DateTimePicker.GetInputElement().data('init-with-now') === true)
|
||||
{
|
||||
startDate = moment().format(Grocy.Components.DateTimePicker.GetInputElement().data('format'));
|
||||
}
|
||||
|
||||
var limitDate = moment('2999-12-31 23:59:59');
|
||||
if (Grocy.Components.DateTimePicker.GetInputElement().data('limit-end-to-now') === true)
|
||||
{
|
||||
limitDate = moment();
|
||||
}
|
||||
|
||||
$('.datetimepicker').datetimepicker(
|
||||
{
|
||||
format: Grocy.Components.DateTimePicker.GetInputElement().data('format'),
|
||||
buttons: {
|
||||
showToday: true,
|
||||
showClose: true
|
||||
},
|
||||
calendarWeeks: true,
|
||||
maxDate: limitDate,
|
||||
locale: moment.locale(),
|
||||
defaultDate: startDate,
|
||||
useCurrent: false,
|
||||
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,
|
||||
keyBinds: {
|
||||
up: function(widget) { },
|
||||
down: function(widget) { },
|
||||
'control up': function(widget) { },
|
||||
'control down': function(widget) { },
|
||||
left: function(widget) { },
|
||||
right: function(widget) { },
|
||||
pageUp: function(widget) { },
|
||||
pageDown: function(widget) { },
|
||||
enter: function(widget) { },
|
||||
escape: function(widget) { },
|
||||
'control space': function(widget) { },
|
||||
t: function(widget) { },
|
||||
'delete': function(widget) { }
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.Components.DateTimePicker.GetInputElement().on('keyup', function(e)
|
||||
{
|
||||
$('.datetimepicker').datetimepicker('hide');
|
||||
|
||||
var value = Grocy.Components.DateTimePicker.GetValue();
|
||||
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');
|
||||
var format = Grocy.Components.DateTimePicker.GetInputElement().data('format');
|
||||
var nextInputElement = $(Grocy.Components.DateTimePicker.GetInputElement().data('next-input-selector'));
|
||||
|
||||
//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))
|
||||
{
|
||||
Grocy.Components.DateTimePicker.SetValue(moment(new Date(), format, true).format(format));
|
||||
nextInputElement.focus();
|
||||
}
|
||||
else if (value === 'x' || value === 'X')
|
||||
{
|
||||
Grocy.Components.DateTimePicker.SetValue(moment('2999-12-31 23:59:59').format(format));
|
||||
nextInputElement.focus();
|
||||
}
|
||||
else if (value.length === 4 && !(Number.parseInt(value) > centuryStart && Number.parseInt(value) < centuryEnd))
|
||||
{
|
||||
Grocy.Components.DateTimePicker.SetValue((new Date()).getFullYear().toString() + value);
|
||||
nextInputElement.focus();
|
||||
}
|
||||
else if (value.length === 8 && $.isNumeric(value))
|
||||
{
|
||||
Grocy.Components.DateTimePicker.SetValue(value.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3'));
|
||||
nextInputElement.focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
var dateObj = moment(value, format, true);
|
||||
if (dateObj.isValid())
|
||||
{
|
||||
if (e.keyCode === 38) //Up
|
||||
{
|
||||
Grocy.Components.DateTimePicker.SetValue(dateObj.add(-1, 'days').format(format));
|
||||
}
|
||||
else if (e.keyCode === 40) //Down
|
||||
{
|
||||
Grocy.Components.DateTimePicker.SetValue(dateObj.add(1, 'days').format(format));
|
||||
}
|
||||
else if (e.keyCode === 37) //Left
|
||||
{
|
||||
Grocy.Components.DateTimePicker.SetValue(dateObj.add(-1, 'weeks').format(format));
|
||||
}
|
||||
else if (e.keyCode === 39) //Right
|
||||
{
|
||||
Grocy.Components.DateTimePicker.SetValue(dateObj.add(1, 'weeks').format(format));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Custom validation
|
||||
value = Grocy.Components.DateTimePicker.GetValue();
|
||||
dateObj = moment(value, format, true);
|
||||
var element = Grocy.Components.DateTimePicker.GetInputElement()[0];
|
||||
if (!dateObj.isValid())
|
||||
{
|
||||
element.setCustomValidity("error");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Grocy.Components.DateTimePicker.GetInputElement().data('limit-end-to-now') === true && dateObj.isAfter(moment()))
|
||||
{
|
||||
element.setCustomValidity("error");
|
||||
}
|
||||
else if (Grocy.Components.DateTimePicker.GetInputElement().data('limit-start-to-now') === true && dateObj.isBefore(moment()))
|
||||
{
|
||||
element.setCustomValidity("error");
|
||||
}
|
||||
else
|
||||
{
|
||||
element.setCustomValidity("");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.Components.DateTimePicker.GetInputElement().on('input', function(e)
|
||||
{
|
||||
$('#datetimepicker-timeago').text($.timeago(Grocy.Components.DateTimePicker.GetValue()));
|
||||
EmptyElementWhenMatches('#datetimepicker-timeago', L('timeago_nan'));
|
||||
});
|
||||
|
||||
$('.datetimepicker').on('update.datetimepicker', function(e)
|
||||
{
|
||||
Grocy.Components.DateTimePicker.GetInputElement().trigger('input');
|
||||
});
|
||||
|
@@ -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();
|
||||
}
|
||||
},
|
||||
@@ -103,30 +96,30 @@ $('#product_id').val('');
|
||||
$('#product_id_text_input').focus();
|
||||
$('#product_id_text_input').val('');
|
||||
$('#product_id_text_input').trigger('change');
|
||||
|
||||
$('#consume-form').validator();
|
||||
$('#consume-form').validator('validate');
|
||||
Grocy.FrontendHelpers.ValidateForm('consume-form');
|
||||
|
||||
$('#amount').on('focus', function(e)
|
||||
{
|
||||
if ($('#product_id_text_input').val().length === 0)
|
||||
{
|
||||
$('#product_id_text_input').focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
$(this).select();
|
||||
}
|
||||
$(this).select();
|
||||
});
|
||||
|
||||
$('#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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -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');
|
||||
}
|
||||
});
|
||||
|
@@ -1,4 +1,25 @@
|
||||
$(document).on('click', '.habit-delete-button', function(e)
|
||||
var habitsTable = $('#habits-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
habitsTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.habit-delete-button', function (e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-habit-name');
|
||||
var objectId = $(e.currentTarget).attr('data-habit-id');
|
||||
@@ -33,12 +54,3 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#habits-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
});
|
||||
|
@@ -1,10 +1,22 @@
|
||||
$('#habits-overview-table').DataTable({
|
||||
'pageLength': 50,
|
||||
var habitsOverviewTable = $('#habits-overview-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[2, 'desc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
habitsOverviewTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.track-habit-button', function(e)
|
||||
|
@@ -7,18 +7,17 @@
|
||||
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=' + Grocy.Components.DateTimePicker.GetValue(),
|
||||
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, Grocy.Components.DateTimePicker.GetValue()));
|
||||
|
||||
$('#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');
|
||||
Grocy.Components.DateTimePicker.SetValue(moment().format('YYYY-MM-DD HH:mm:ss'));
|
||||
$('#habit_id_text_input').trigger('change');
|
||||
$('#habittracking-form').validator('validate');
|
||||
Grocy.FrontendHelpers.ValidateForm('habittracking-form');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -40,18 +39,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();
|
||||
Grocy.Components.DateTimePicker.GetInputElement().focus();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -59,27 +47,32 @@ $('.combobox').combobox({
|
||||
appendId: '_text_input'
|
||||
});
|
||||
|
||||
$('#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)
|
||||
Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e)
|
||||
{
|
||||
$('#habittracking-form').validator('validate');
|
||||
Grocy.FrontendHelpers.ValidateForm('habittracking-form');
|
||||
});
|
||||
|
@@ -7,7 +7,7 @@
|
||||
Grocy.Api.Get('stock/get-product-details/' + jsonForm.product_id,
|
||||
function (productDetails)
|
||||
{
|
||||
Grocy.Api.Get('stock/inventory-product/' + jsonForm.product_id + '/' + jsonForm.new_amount + '?bestbeforedate=' + $('#best_before_date').val(),
|
||||
Grocy.Api.Get('stock/inventory-product/' + jsonForm.product_id + '/' + jsonForm.new_amount + '?bestbeforedate=' + Grocy.Components.DateTimePicker.GetValue(),
|
||||
function(result)
|
||||
{
|
||||
var addBarcode = GetUriParam('addbarcodetoselection');
|
||||
@@ -40,14 +40,14 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#inventory-change-info').hide();
|
||||
$('#inventory-change-info').addClass('d-none');
|
||||
$('#new_amount').val('');
|
||||
$('#best_before_date').val('');
|
||||
Grocy.Components.DateTimePicker.SetValue('');
|
||||
$('#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)
|
||||
@@ -164,38 +164,11 @@ $('#product_id_text_input').on('change', function(e)
|
||||
});
|
||||
|
||||
$('#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({
|
||||
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');
|
||||
Grocy.FrontendHelpers.ValidateForm('inventory-form');
|
||||
|
||||
$('#new_amount').on('focus', function(e)
|
||||
{
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -243,8 +225,8 @@ var addBarcode = GetUriParam('addbarcodetoselection');
|
||||
if (addBarcode !== undefined)
|
||||
{
|
||||
$('#addbarcodetoselection').text(addBarcode);
|
||||
$('#flow-info-addbarcodetoselection').removeClass('hide');
|
||||
$('#barcode-lookup-disabled-hint').removeClass('hide');
|
||||
$('#flow-info-addbarcodetoselection').removeClass('d-none');
|
||||
$('#barcode-lookup-disabled-hint').removeClass('d-none');
|
||||
}
|
||||
|
||||
$('#new_amount').on('keypress', function(e)
|
||||
@@ -252,63 +234,48 @@ $('#new_amount').on('keypress', function(e)
|
||||
$('#new_amount').trigger('change');
|
||||
});
|
||||
|
||||
$('#best_before_date').on('change', function(e)
|
||||
Grocy.Components.DateTimePicker.GetInputElement().on('change', function(e)
|
||||
{
|
||||
$('#inventory-form').validator('validate');
|
||||
Grocy.FrontendHelpers.ValidateForm('inventory-form');
|
||||
});
|
||||
|
||||
$('#best_before_date').on('keypress', function(e)
|
||||
Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e)
|
||||
{
|
||||
$('#inventory-form').validator('validate');
|
||||
Grocy.FrontendHelpers.ValidateForm('inventory-form');
|
||||
});
|
||||
|
||||
$('#best_before_date').on('keydown', function(e)
|
||||
$('#new_amount').on('keyup', function(e)
|
||||
{
|
||||
if (e.keyCode === 13) //Enter
|
||||
{
|
||||
$('#best_before_date').trigger('change');
|
||||
}
|
||||
});
|
||||
|
||||
$('#new_amount').on('change', function(e)
|
||||
{
|
||||
if ($('#product_id').parent().hasClass('has-error'))
|
||||
{
|
||||
$('#inventory-change-info').hide();
|
||||
return;
|
||||
}
|
||||
|
||||
var productId = $('#product_id').val();
|
||||
var newAmount = $('#new_amount').val();
|
||||
|
||||
var newAmount = parseInt($('#new_amount').val());
|
||||
|
||||
if (productId)
|
||||
{
|
||||
Grocy.Api.Get('stock/get-product-details/' + productId,
|
||||
function(productDetails)
|
||||
{
|
||||
var productStockAmount = productDetails.stock_amount || '0';
|
||||
|
||||
var productStockAmount = parseInt(productDetails.stock_amount || '0');
|
||||
|
||||
if (newAmount > productStockAmount)
|
||||
{
|
||||
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();
|
||||
$('#best_before_date').attr('required', 'required');
|
||||
$('#inventory-change-info').removeClass('d-none');
|
||||
Grocy.Components.DateTimePicker.GetInputElement().attr('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();
|
||||
$('#best_before_date').removeAttr('required');
|
||||
$('#inventory-change-info').removeClass('d-none');
|
||||
Grocy.Components.DateTimePicker.GetInputElement().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)
|
||||
{
|
||||
|
@@ -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');
|
||||
|
@@ -1,4 +1,25 @@
|
||||
$(document).on('click', '.location-delete-button', function(e)
|
||||
var locationsTable = $('#locations-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
locationsTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.location-delete-button', function (e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-location-name');
|
||||
var objectId = $(e.currentTarget).attr('data-location-id');
|
||||
@@ -33,12 +54,3 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#locations-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
});
|
||||
|
@@ -1,9 +1,7 @@
|
||||
$('.logout-button').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');
|
||||
}
|
||||
|
@@ -1,4 +1,31 @@
|
||||
$(document).on('click', '.apikey-delete-button', function(e)
|
||||
var apiKeysTable = $('#apikeys-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[4, 'desc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
var createdApiKeyId = GetUriParam('CreatedApiKeyId');
|
||||
if (createdApiKeyId !== undefined)
|
||||
{
|
||||
$('#apiKeyRow_' + createdApiKeyId).effect('highlight', {}, 3000);
|
||||
}
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
apiKeysTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.apikey-delete-button', function (e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-apikey-apikey');
|
||||
var objectId = $(e.currentTarget).attr('data-apikey-id');
|
||||
@@ -33,18 +60,3 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#apikeys-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[4, 'desc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
});
|
||||
|
||||
var createdApiKeyId = GetUriParam('CreatedApiKeyId');
|
||||
if (createdApiKeyId !== undefined)
|
||||
{
|
||||
$('#apiKeyRow_' + createdApiKeyId).effect('highlight', { }, 3000);
|
||||
}
|
||||
|
@@ -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');
|
||||
|
@@ -1,4 +1,25 @@
|
||||
$(document).on('click', '.product-delete-button', function(e)
|
||||
var productsTable = $('#products-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
productsTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.product-delete-button', function (e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-product-name');
|
||||
var objectId = $(e.currentTarget).attr('data-product-id');
|
||||
@@ -33,12 +54,3 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#products-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
});
|
||||
|
@@ -9,7 +9,7 @@
|
||||
{
|
||||
var amount = jsonForm.amount * productDetails.product.qu_factor_purchase_to_stock;
|
||||
|
||||
Grocy.Api.Get('stock/add-product/' + jsonForm.product_id + '/' + amount + '?bestbeforedate=' + $('#best_before_date').val(),
|
||||
Grocy.Api.Get('stock/add-product/' + jsonForm.product_id + '/' + amount + '?bestbeforedate=' + Grocy.Components.DateTimePicker.GetValue(),
|
||||
function(result)
|
||||
{
|
||||
var addBarcode = GetUriParam('addbarcodetoselection');
|
||||
@@ -43,12 +43,12 @@
|
||||
else
|
||||
{
|
||||
$('#amount').val(0);
|
||||
$('#best_before_date').val('');
|
||||
Grocy.Components.DateTimePicker.SetValue('');
|
||||
$('#product_id').val('');
|
||||
$('#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)
|
||||
@@ -79,13 +79,12 @@ $('#product_id').on('change', function(e)
|
||||
|
||||
if (productDetails.product.default_best_before_days.toString() !== '0')
|
||||
{
|
||||
$('#best_before_date').val(moment().add(productDetails.product.default_best_before_days, 'days').format('YYYY-MM-DD'));
|
||||
$('#best_before_date').trigger('change');
|
||||
Grocy.Components.DateTimePicker.SetValue(moment().add(productDetails.product.default_best_before_days, 'days').format('YYYY-MM-DD'));
|
||||
$('#amount').focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#best_before_date').focus();
|
||||
Grocy.Components.DateTimePicker.GetInputElement().focus();
|
||||
}
|
||||
},
|
||||
function(xhr)
|
||||
@@ -97,7 +96,8 @@ $('#product_id').on('change', function(e)
|
||||
});
|
||||
|
||||
$('.combobox').combobox({
|
||||
appendId: '_text_input'
|
||||
appendId: '_text_input',
|
||||
bsVersion: '4'
|
||||
});
|
||||
|
||||
$('#product_id_text_input').on('change', function(e)
|
||||
@@ -173,39 +173,11 @@ $('#product_id_text_input').on('change', function(e)
|
||||
});
|
||||
|
||||
$('#amount').val(0);
|
||||
$('#best_before_date').val('');
|
||||
$('#product_id').val('');
|
||||
$('#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)
|
||||
{
|
||||
$('#product_id_text_input').focus();
|
||||
}
|
||||
});
|
||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||
|
||||
$('#amount').on('focus', function(e)
|
||||
{
|
||||
@@ -219,15 +191,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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -245,7 +226,7 @@ if (prefillProduct !== undefined)
|
||||
$('#product_id').val(possibleOptionElement.val());
|
||||
$('#product_id').data('combobox').refresh();
|
||||
$('#product_id').trigger('change');
|
||||
$('#best_before_date').focus();
|
||||
Grocy.Components.DateTimePicker.GetInputElement().focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,16 +234,21 @@ var addBarcode = GetUriParam('addbarcodetoselection');
|
||||
if (addBarcode !== undefined)
|
||||
{
|
||||
$('#addbarcodetoselection').text(addBarcode);
|
||||
$('#flow-info-addbarcodetoselection').removeClass('hide');
|
||||
$('#barcode-lookup-disabled-hint').removeClass('hide');
|
||||
$('#flow-info-addbarcodetoselection').removeClass('d-none');
|
||||
$('#barcode-lookup-disabled-hint').removeClass('d-none');
|
||||
}
|
||||
|
||||
$('#best_before_date').on('change', function(e)
|
||||
Grocy.Components.DateTimePicker.GetInputElement().on('change', function(e)
|
||||
{
|
||||
$('#purchase-form').validator('validate');
|
||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||
});
|
||||
|
||||
$('#best_before_date').on('keypress', function(e)
|
||||
Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e)
|
||||
{
|
||||
$('#purchase-form').validator('validate');
|
||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||
});
|
||||
|
||||
$('#amount').on('change', function (e)
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||
});
|
||||
|
@@ -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');
|
||||
|
@@ -1,4 +1,25 @@
|
||||
$(document).on('click', '.quantityunit-delete-button', function(e)
|
||||
var quantityUnitsTable = $('#quantityunits-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
quantityUnitsTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.quantityunit-delete-button', function (e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-quantityunit-name');
|
||||
var objectId = $(e.currentTarget).attr('data-quantityunit-id');
|
||||
@@ -33,12 +54,3 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#quantityunits-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
});
|
||||
|
@@ -1,4 +1,25 @@
|
||||
$(document).on('click', '.shoppinglist-delete-button', function(e)
|
||||
var shoppingListTable = $('#shoppinglist-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
shoppingListTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.shoppinglist-delete-button', function (e)
|
||||
{
|
||||
Grocy.Api.Get('delete-object/shopping_list/' + $(e.currentTarget).attr('data-shoppinglist-id'),
|
||||
function(result)
|
||||
@@ -25,12 +46,3 @@ $(document).on('click', '#add-products-below-min-stock-amount', function(e)
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$('#shoppinglist-table').DataTable({
|
||||
'pageLength': 50,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
});
|
||||
|
@@ -42,43 +42,7 @@ $('#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);
|
||||
}
|
||||
);
|
||||
}
|
||||
$('#amount').focus();
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -97,7 +61,8 @@ $('#product_id_text_input').on('change', function(e)
|
||||
var input = $('#product_id_text_input').val().toString();
|
||||
var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + input + "']").first();
|
||||
|
||||
if (possibleOptionElement.length > 0 && possibleOptionElement.text().length > 0) {
|
||||
if (possibleOptionElement.length > 0 && possibleOptionElement.text().length > 0)
|
||||
{
|
||||
$('#product_id').val(possibleOptionElement.val());
|
||||
$('#product_id').data('combobox').refresh();
|
||||
$('#product_id').trigger('change');
|
||||
@@ -113,8 +78,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)
|
||||
{
|
||||
@@ -122,16 +86,29 @@ $('#amount').on('focus', function(e)
|
||||
{
|
||||
$('#product_id_text_input').focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
$(this).select();
|
||||
}
|
||||
});
|
||||
|
||||
$('#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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,10 +1,34 @@
|
||||
$('#stock-overview-table').DataTable({
|
||||
'pageLength': 50,
|
||||
var stockOverviewTable = $('#stock-overview-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[3, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
{ 'orderable': false, 'targets': 0 },
|
||||
{ 'visible': false, 'targets': 4 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization'))
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false
|
||||
});
|
||||
|
||||
$("#location-filter").on("change", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
stockOverviewTable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
stockOverviewTable.search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.product-consume-button', function(e)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"Version": "1.11.0",
|
||||
"ReleaseDate": "2018-06-15"
|
||||
"Version": "1.13.0",
|
||||
"ReleaseDate": "2018-07-12"
|
||||
}
|
||||
|
@@ -5,46 +5,59 @@
|
||||
@section('viewJsName', 'batteries')
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">
|
||||
@yield('title')
|
||||
<a class="btn btn-default" href="{{ $U('/battery/new') }}" role="button">
|
||||
<i class="fa fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
@yield('title')
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/battery/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="batteries-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
<th>{{ $L('Used in') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($batteries as $battery)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info" href="{{ $U('/battery/') }}{{ $battery->id }}" role="button">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-danger battery-delete-button" href="#" role="button" data-battery-id="{{ $battery->id }}" data-battery-name="{{ $battery->name }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $battery->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $battery->description }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $battery->used_in }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row mt-3">
|
||||
<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>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="batteries-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
<th>{{ $L('Used in') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($batteries as $battery)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info btn-sm" href="{{ $U('/battery/') }}{{ $battery->id }}">
|
||||
<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="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $battery->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $battery->description }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $battery->used_in }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,59 +5,65 @@
|
||||
@section('viewJsName', 'batteriesoverview')
|
||||
|
||||
@push('pageScripts')
|
||||
<script src="{{ $U('/bower_components/jquery-ui/jquery-ui.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/jquery-ui-dist/jquery-ui.min.js?v=', true) }}{{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<p class="btn btn-lg btn-warning no-real-button responsive-button">{{ $L('#1 batteries are due to be charged within the next #2 days', $countDueNextXDays, $nextXDays) }}</p>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>@yield('title')</h1>
|
||||
<p class="btn btn-lg btn-warning no-real-button responsive-button mr-2">{{ $L('#1 batteries are due to be charged within the next #2 days', $countDueNextXDays, $nextXDays) }}</p>
|
||||
<p class="btn btn-lg btn-danger no-real-button responsive-button">{{ $L('#1 batteries are overdue to be charged', $countOverdue) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="discrete-content-separator-2x"></div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||
<label for="search">{{ $L('Search') }}</label> <i class="fas fa-search"></i>
|
||||
<input type="text" class="form-control" id="search">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="batteries-overview-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Battery') }}</th>
|
||||
<th>{{ $L('Last charged') }}</th>
|
||||
<th>{{ $L('Next planned charge cycle') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($current as $curentBatteryEntry)
|
||||
<tr class="@if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0 && $nextChargeTimes[$curentBatteryEntry->battery_id] < date('Y-m-d H:i:s')) error-bg @endif">
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-success btn-xs 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>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
<span id="battery-{{ $curentBatteryEntry->battery_id }}-last-tracked-time">{{ $curentBatteryEntry->last_tracked_time }}</span>
|
||||
<time id="battery-{{ $curentBatteryEntry->battery_id }}-last-tracked-time-timeago" class="timeago timeago-contextual" datetime="{{ $curentBatteryEntry->last_tracked_time }}"></time>
|
||||
</td>
|
||||
<td>
|
||||
@if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0)
|
||||
{{ $nextChargeTimes[$curentBatteryEntry->battery_id] }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $nextChargeTimes[$curentBatteryEntry->battery_id] }}"></time>
|
||||
@else
|
||||
...
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="batteries-overview-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Battery') }}</th>
|
||||
<th>{{ $L('Last charged') }}</th>
|
||||
<th>{{ $L('Next planned charge cycle') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($current as $curentBatteryEntry)
|
||||
<tr class="@if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0 && $nextChargeTimes[$curentBatteryEntry->battery_id] < date('Y-m-d H:i:s')) table-danger @endif">
|
||||
<td class="fit-content">
|
||||
<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="fas fa-fire"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
<span id="battery-{{ $curentBatteryEntry->battery_id }}-last-tracked-time">{{ $curentBatteryEntry->last_tracked_time }}</span>
|
||||
<time id="battery-{{ $curentBatteryEntry->battery_id }}-last-tracked-time-timeago" class="timeago timeago-contextual" datetime="{{ $curentBatteryEntry->last_tracked_time }}"></time>
|
||||
</td>
|
||||
<td>
|
||||
@if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0)
|
||||
{{ $nextChargeTimes[$curentBatteryEntry->battery_id] }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $nextChargeTimes[$curentBatteryEntry->battery_id] }}"></time>
|
||||
@else
|
||||
...
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -9,35 +9,37 @@
|
||||
@section('viewJsName', 'batteryform')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
|
||||
@if($mode == 'edit')
|
||||
<script>Grocy.EditObjectId = {{ $battery->id }}</script>
|
||||
@endif
|
||||
@if($mode == 'edit')
|
||||
<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="help-block with-errors"></div>
|
||||
</div>
|
||||
<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">{{ $L('A name is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<input type="text" class="form-control" id="description" name="description" value="@if($mode == 'edit'){{ $battery->description }}@endif">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<input type="text" class="form-control" id="description" name="description" value="@if($mode == 'edit'){{ $battery->description }}@endif">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">{{ $L('Used in') }}</label>
|
||||
<input type="text" class="form-control" id="used_in" name="used_in" value="@if($mode == 'edit'){{ $battery->used_in }}@endif">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">{{ $L('Used in') }}</label>
|
||||
<input type="text" class="form-control" id="used_in" name="used_in" value="@if($mode == 'edit'){{ $battery->used_in }}@endif">
|
||||
</div>
|
||||
|
||||
<button id="save-battery-button" type="submit" class="btn btn-default">{{ $L('Save') }}</button>
|
||||
<button id="save-battery-button" type="submit" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,39 +5,40 @@
|
||||
@section('viewJsName', 'batterytracking')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6 col-xl-4 pb-3">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<form id="batterytracking-form">
|
||||
<form id="batterytracking-form" novalidate>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="battery_id">{{ $L('Battery') }}</label>
|
||||
<select class="form-control combobox" id="battery_id" name="battery_id" required>
|
||||
<option value=""></option>
|
||||
@foreach($batteries as $battery)
|
||||
<option value="{{ $battery->id }}">{{ $battery->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div id="battery-error" class="help-block with-errors"></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 class="form-group">
|
||||
<label for="battery_id">{{ $L('Battery') }}</label>
|
||||
<select class="form-control combobox" id="battery_id" name="battery_id" required>
|
||||
<option value=""></option>
|
||||
@foreach($batteries as $battery)
|
||||
<option value="{{ $battery->id }}">{{ $battery->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ $L('You have to select a battery') }}</div>
|
||||
</div>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<button id="save-batterytracking-button" type="submit" class="btn btn-default">{{ $L('OK') }}</button>
|
||||
@include('components.datetimepicker', array(
|
||||
'id' => 'tracked_time',
|
||||
'label' => 'Tracked time',
|
||||
'format' => 'YYYY-MM-DD HH:mm:ss',
|
||||
'initWithNow' => true,
|
||||
'limitEndToNow' => true,
|
||||
'limitStartToNow' => false,
|
||||
'invalidFeedback' => $L('This can only be before now')
|
||||
))
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<button id="save-batterytracking-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>
|
||||
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
@include('components.batterycard')
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-6 col-xl-4">
|
||||
@include('components.batterycard')
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -2,14 +2,14 @@
|
||||
<script src="{{ $U('/viewjs/components/batterycard.js', true) }}?v={{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
<div class="main well">
|
||||
|
||||
<h3>{{ $L('Battery overview') }} <strong><span id="batterycard-battery-name"></span></strong></h3>
|
||||
|
||||
<p>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<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>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,14 +0,0 @@
|
||||
@push('componentScripts')
|
||||
<script src="{{ $U('/viewjs/components/datepicker.js', true) }}?v={{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
<div class="form-group">
|
||||
<label for="{{ $id }}">{{ $L($label) }} <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">
|
||||
<div id="datepicker-button" class="input-group-addon">
|
||||
<i class="fa fa-calendar"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
@@ -3,12 +3,17 @@
|
||||
@endpush
|
||||
|
||||
<div class="form-group">
|
||||
<label for="{{ $id }}">{{ $L($label) }}</label>
|
||||
<div class="input-group date datetimepicker">
|
||||
<input type="text" class="form-control" id="{{ $id }}" name="{{ $id }}" required>
|
||||
<span class="input-group-addon">
|
||||
<span class="fa fa-calendar"></span>
|
||||
</span>
|
||||
<label for="{{ $id }}">{{ $L($label) }} <span class="small text-muted"><time id="datetimepicker-timeago" class="timeago timeago-contextual"></time>@if(!empty($hint))<br>{{ $L($hint) }}@endif</span></label>
|
||||
<div class="input-group date datetimepicker" id="{{ $id }}" data-target-input="nearest">
|
||||
<input type="text" required class="form-control datetimepicker-input"
|
||||
data-target="#{{ $id }}" data-format="{{ $format }}"
|
||||
data-init-with-now="{{ BoolToString($initWithNow) }}"
|
||||
data-limit-end-to-now="{{ BoolToString($limitEndToNow) }}"
|
||||
data-limit-start-to-now="{{ BoolToString($limitStartToNow) }}"
|
||||
data-next-input-selector="{{ $nextInputSelector }}" />
|
||||
<div class="input-group-append" data-target="#{{ $id }}" data-toggle="datetimepicker">
|
||||
<div class="input-group-text"><i class="fas fa-calendar"></i></div>
|
||||
</div>
|
||||
<div class="invalid-feedback">{{ $invalidFeedback }}</div>
|
||||
</div>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
@@ -2,13 +2,13 @@
|
||||
<script src="{{ $U('/viewjs/components/habitcard.js', true) }}?v={{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
<div class="main well">
|
||||
|
||||
<h3>{{ $L('Habit overview') }} <strong><span id="habitcard-habit-name"></span></strong></h3>
|
||||
|
||||
<p>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<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>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,66 +0,0 @@
|
||||
|
||||
<ul class="nav navbar-nav sidebar-nav">
|
||||
<li data-nav-for-page="stockoverview">
|
||||
<a class="discrete-link" href="{{ $U('/stockoverview') }}"><i class="fa fa-tachometer fa-fw"></i> {{ $L('Stock overview') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="habitsoverview">
|
||||
<a class="discrete-link" href="{{ $U('/habitsoverview') }}"><i class="fa fa-tachometer fa-fw"></i> {{ $L('Habits overview') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batteriesoverview">
|
||||
<a class="discrete-link" href="{{ $U('/batteriesoverview') }}"><i class="fa fa-tachometer fa-fw"></i> {{ $L('Batteries overview') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="discrete-content-separator-2x"></div>
|
||||
|
||||
<ul class="nav navbar-nav sidebar-nav">
|
||||
<li class="disabled"><a href="#"><strong>{{ $L('Record data') }}</strong></a></li>
|
||||
<li data-nav-for-page="purchase">
|
||||
<a class="discrete-link" href="{{ $U('/purchase') }}"><i class="fa fa-shopping-cart fa-fw"></i> {{ $L('Purchase') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="consume">
|
||||
<a class="discrete-link" href="{{ $U('/consume') }}"><i class="fa fa-cutlery fa-fw"></i> {{ $L('Consume') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="shoppinglist">
|
||||
<a class="discrete-link" href="{{ $U('/shoppinglist') }}"><i class="fa fa-shopping-bag fa-fw"></i> {{ $L('Shopping list') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="inventory">
|
||||
<a class="discrete-link" href="{{ $U('/inventory') }}"><i class="fa fa-list fa-fw"></i> {{ $L('Inventory') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="habittracking">
|
||||
<a class="discrete-link" href="{{ $U('/habittracking') }}"><i class="fa fa-play fa-fw"></i> {{ $L('Habit tracking') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batterytracking">
|
||||
<a class="discrete-link" href="{{ $U('/batterytracking') }}"><i class="fa fa-fire fa-fw"></i> {{ $L('Battery tracking') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="discrete-content-separator-2x"></div>
|
||||
|
||||
<ul class="nav navbar-nav sidebar-nav">
|
||||
<li class="disabled"><a href="#"><strong>{{ $L('Manage master data') }}</strong></a></li>
|
||||
<li data-nav-for-page="products">
|
||||
<a class="discrete-link" href="{{ $U('/products') }}"><i class="fa fa-product-hunt fa-fw"></i> {{ $L('Products') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="locations">
|
||||
<a class="discrete-link" href="{{ $U('/locations') }}"><i class="fa fa-map-marker fa-fw"></i> {{ $L('Locations') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="quantityunits">
|
||||
<a class="discrete-link" href="{{ $U('/quantityunits') }}"><i class="fa fa-balance-scale fa-fw"></i> {{ $L('Quantity units') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="habits">
|
||||
<a class="discrete-link" href="{{ $U('/habits') }}"><i class="fa fa-refresh fa-fw"></i> {{ $L('Habits') }}</a>
|
||||
</li>
|
||||
<li data-nav-for-page="batteries">
|
||||
<a class="discrete-link" href="{{ $U('/batteries') }}"><i class="fa fa-battery-three-quarters fa-fw"></i> {{ $L('Batteries') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="discrete-content-separator-2x hidden-xs"></div>
|
||||
|
||||
<ul class="nav navbar-nav sidebar-nav nav-copyright">
|
||||
<li>
|
||||
Version {{ $version }}<br>
|
||||
<a class="discrete-link" href="#" data-toggle="modal" data-target="#about-modal">{{ $L('About grocy') }}</a>
|
||||
</li>
|
||||
</ul>
|
@@ -2,15 +2,15 @@
|
||||
<script src="{{ $U('/viewjs/components/productcard.js', true) }}?v={{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
<div class="main well">
|
||||
|
||||
<h3>{{ $L('Product overview') }} <strong><span id="productcard-product-name"></span></strong></h3>
|
||||
<h4><strong>{{ $L('Stock quantity unit') }}:</strong> <span id="productcard-product-stock-qu-name"></span></h4>
|
||||
|
||||
<p>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<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>
|
||||
<strong>{{ $L('Last used') }}:</strong> <span id="productcard-product-last-used"></span> <time id="productcard-product-last-used-timeago" class="timeago timeago-contextual"></time>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,17 +0,0 @@
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">@if(AUTHENTICATED === true){{ HTTP_USER }}@endif <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a class="discrete-link logout-button" href="{{ $U('/logout') }}"><i class="fa fa-sign-out fa-fw"></i> {{ $L('Logout') }}</a>
|
||||
</li>
|
||||
<li class="divider logout-button"></li>
|
||||
<li>
|
||||
<a class="discrete-link" href="{{ $U('/manageapikeys') }}"><i class="fa fa-handshake-o fa-fw"></i> {{ $L('Manage API keys') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="discrete-link" target="_blank" href="{{ $U('/api') }}"><i class="fa fa-book"></i> {{ $L('REST API & data model documentation') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
@@ -5,40 +5,42 @@
|
||||
@section('viewJsName', 'consume')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6 col-xl-4 pb-3">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<form id="consume-form">
|
||||
<form id="consume-form" novalidate>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="product_id">{{ $L('Product') }} <i class="fa 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="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="product_id">{{ $L('Product') }} <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">{{ $L('You have to select a product') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="amount">{{ $L('Amount') }} <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="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="amount">{{ $L('Amount') }} <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">{{ $L('The amount cannot be lower than #1', '0') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label for="spoiled">
|
||||
<input type="checkbox" id="spoiled" name="spoiled"> {{ $L('Spoiled') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label for="spoiled">
|
||||
<input type="checkbox" id="spoiled" name="spoiled"> {{ $L('Spoiled') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button id="save-consume-button" type="submit" class="btn btn-default">{{ $L('OK') }}</button>
|
||||
<button id="save-consume-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
@include('components.productcard')
|
||||
<div class="col-xs-12 col-md-6 col-xl-4">
|
||||
@include('components.productcard')
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -9,48 +9,50 @@
|
||||
@section('viewJsName', 'habitform')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
|
||||
@if($mode == 'edit')
|
||||
<script>Grocy.EditObjectId = {{ $habit->id }};</script>
|
||||
@endif
|
||||
@if($mode == 'edit')
|
||||
<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="help-block with-errors"></div>
|
||||
</div>
|
||||
<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">{{ $L('A name is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $habit->description }}@endif</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $habit->description }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="period_type">{{ $L('Period type') }}</label>
|
||||
<select required class="form-control input-group-habit-period-type" id="period_type" name="period_type">
|
||||
@foreach($periodTypes as $periodType)
|
||||
<option @if($mode == 'edit' && $periodType == $habit->period_type) selected="selected" @endif value="{{ $periodType }}">{{ $L($periodType) }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="period_type">{{ $L('Period type') }}</label>
|
||||
<select required class="form-control input-group-habit-period-type" id="period_type" name="period_type">
|
||||
@foreach($periodTypes as $periodType)
|
||||
<option @if($mode == 'edit' && $periodType == $habit->period_type) selected="selected" @endif value="{{ $periodType }}">{{ $L($periodType) }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<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="help-block with-errors"></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" 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-default">{{ $L('Save') }}</button>
|
||||
<button id="save-habit-button" type="submit" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,15 +5,27 @@
|
||||
@section('viewJsName', 'habits')
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">
|
||||
@yield('title')
|
||||
<a class="btn btn-default" href="{{ $U('/habit/new') }}" role="button">
|
||||
<i class="fa fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
@yield('title')
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/habit/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="habits-table" class="table table-striped">
|
||||
<div class="row mt-3">
|
||||
<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>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="habits-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
@@ -27,11 +39,11 @@
|
||||
@foreach($habits as $habit)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info" href="{{ $U('/habit/') }}{{ $habit->id }}" role="button">
|
||||
<i class="fa fa-pencil"></i>
|
||||
<a class="btn btn-info btn-sm" href="{{ $U('/habit/') }}{{ $habit->id }}">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a class="btn btn-danger habit-delete-button" href="#" role="button" data-habit-id="{{ $habit->id }}" data-habit-name="{{ $habit->name }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
<a class="btn btn-danger btn-sm habit-delete-button" href="#" data-habit-id="{{ $habit->id }}" data-habit-name="{{ $habit->name }}">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
@@ -49,6 +61,7 @@
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,59 +5,65 @@
|
||||
@section('viewJsName', 'habitsoverview')
|
||||
|
||||
@push('pageScripts')
|
||||
<script src="{{ $U('/bower_components/jquery-ui/jquery-ui.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/jquery-ui-dist/jquery-ui.min.js?v=', true) }}{{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<p class="btn btn-lg btn-warning no-real-button responsive-button">{{ $L('#1 habits are due to be done within the next #2 days', $countDueNextXDays, $nextXDays) }}</p>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>@yield('title')</h1>
|
||||
<p class="btn btn-lg btn-warning no-real-button responsive-button mr-2">{{ $L('#1 habits are due to be done within the next #2 days', $countDueNextXDays, $nextXDays) }}</p>
|
||||
<p class="btn btn-lg btn-danger no-real-button responsive-button">{{ $L('#1 habits are overdue to be done', $countOverdue) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="discrete-content-separator-2x"></div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||
<label for="search">{{ $L('Search') }}</label> <i class="fas fa-search"></i>
|
||||
<input type="text" class="form-control" id="search">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="habits-overview-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Habit') }}</th>
|
||||
<th>{{ $L('Next estimated tracking') }}</th>
|
||||
<th>{{ $L('Last tracked') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($currentHabits as $curentHabitEntry)
|
||||
<tr class="@if(FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === \Grocy\Services\HabitsService::HABIT_TYPE_DYNAMIC_REGULAR && $nextHabitTimes[$curentHabitEntry->habit_id] < date('Y-m-d H:i:s')) error-bg @endif">
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-success btn-xs 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>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
@if(FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === \Grocy\Services\HabitsService::HABIT_TYPE_DYNAMIC_REGULAR)
|
||||
{{ $nextHabitTimes[$curentHabitEntry->habit_id] }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $nextHabitTimes[$curentHabitEntry->habit_id] }}"></time>
|
||||
@else
|
||||
...
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<span id="habit-{{ $curentHabitEntry->habit_id }}-last-tracked-time">{{ $curentHabitEntry->last_tracked_time }}</span>
|
||||
<time id="habit-{{ $curentHabitEntry->habit_id }}-last-tracked-time-timeago" class="timeago timeago-contextual" datetime="{{ $curentHabitEntry->last_tracked_time }}"></time>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="habits-overview-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Habit') }}</th>
|
||||
<th>{{ $L('Next estimated tracking') }}</th>
|
||||
<th>{{ $L('Last tracked') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($currentHabits as $curentHabitEntry)
|
||||
<tr class="@if(FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === \Grocy\Services\HabitsService::HABIT_TYPE_DYNAMIC_REGULAR && $nextHabitTimes[$curentHabitEntry->habit_id] < date('Y-m-d H:i:s')) table-danger @endif">
|
||||
<td class="fit-content">
|
||||
<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="fas fa-play"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
@if(FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === \Grocy\Services\HabitsService::HABIT_TYPE_DYNAMIC_REGULAR)
|
||||
{{ $nextHabitTimes[$curentHabitEntry->habit_id] }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $nextHabitTimes[$curentHabitEntry->habit_id] }}"></time>
|
||||
@else
|
||||
...
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<span id="habit-{{ $curentHabitEntry->habit_id }}-last-tracked-time">{{ $curentHabitEntry->last_tracked_time }}</span>
|
||||
<time id="habit-{{ $curentHabitEntry->habit_id }}-last-tracked-time-timeago" class="timeago timeago-contextual" datetime="{{ $curentHabitEntry->last_tracked_time }}"></time>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,33 +5,40 @@
|
||||
@section('viewJsName', 'habittracking')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6 col-xl-4 pb-3">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<form id="habittracking-form">
|
||||
<form id="habittracking-form" novalidate>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="habit_id">{{ $L('Habit') }}</label>
|
||||
<select class="form-control combobox" id="habit_id" name="habit_id" required>
|
||||
<option value=""></option>
|
||||
@foreach($habits as $habit)
|
||||
<option value="{{ $habit->id }}">{{ $habit->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div id="product-error" class="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="habit_id">{{ $L('Habit') }}</label>
|
||||
<select class="form-control combobox" id="habit_id" name="habit_id" required>
|
||||
<option value=""></option>
|
||||
@foreach($habits as $habit)
|
||||
<option value="{{ $habit->id }}">{{ $habit->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ $L('You have to select a habit') }}</div>
|
||||
</div>
|
||||
|
||||
@include('components.datetimepicker', array(
|
||||
'id' => 'tracked_time',
|
||||
'label' => 'Tracked time'
|
||||
))
|
||||
@include('components.datetimepicker', array(
|
||||
'id' => 'tracked_time',
|
||||
'label' => 'Tracked time',
|
||||
'format' => 'YYYY-MM-DD HH:mm:ss',
|
||||
'initWithNow' => true,
|
||||
'limitEndToNow' => true,
|
||||
'limitStartToNow' => false,
|
||||
'invalidFeedback' => $L('This can only be before now')
|
||||
))
|
||||
|
||||
<button id="save-habittracking-button" type="submit" class="btn btn-default">{{ $L('OK') }}</button>
|
||||
<button id="save-habittracking-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
@include('components.habitcard')
|
||||
<div class="col-xs-12 col-md-6 col-xl-4">
|
||||
@include('components.habitcard')
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,42 +5,50 @@
|
||||
@section('viewJsName', 'inventory')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6 col-xl-4 pb-3">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<form id="inventory-form">
|
||||
<form id="inventory-form" novalidate>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="product_id">{{ $L('Product') }} <i class="fa fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted hide"> {{ $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="help-block with-errors"></div>
|
||||
<div id="flow-info-addbarcodetoselection" class="text-muted small hide"><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="product_id">{{ $L('Product') }} <i class="fas fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted d-none"> {{ $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">{{ $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') }} <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="help-block with-errors"></div>
|
||||
<div id="inventory-change-info" class="help-block text-muted"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new_amount">{{ $L('New amount') }} <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">{{ $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.datetimepicker', array(
|
||||
'id' => 'best_before_date',
|
||||
'label' => 'Best before',
|
||||
'hint' => 'This will apply to added products',
|
||||
'format' => 'YYYY-MM-DD',
|
||||
'initWithNow' => false,
|
||||
'limitEndToNow' => false,
|
||||
'limitStartToNow' => true,
|
||||
'invalidFeedback' => $L('A best before date is required and must be later than today'),
|
||||
'nextInputSelector' => '#best_before_date'
|
||||
))
|
||||
|
||||
@include('components.datepicker', array(
|
||||
'id' => 'best_before_date',
|
||||
'label' => 'Best before',
|
||||
'hint' => 'This will apply to added products'
|
||||
))
|
||||
<button id="save-inventory-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>
|
||||
|
||||
<button id="save-inventory-button" type="submit" class="btn btn-default">{{ $L('OK') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
@include('components.productcard')
|
||||
<div class="col-xs-12 col-md-6 col-xl-4">
|
||||
@include('components.productcard')
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -9,24 +9,27 @@
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
|
||||
<meta name="author" content="Bernd Bestel (bernd@berrnd.de)">
|
||||
<link rel="icon" type="image/png" sizes="200x200" href="{{ $U('/img/grocy.png?v=', true) }}{{ $version }}">
|
||||
<link rel="icon" href="{{ $U('/img/grocy_icon.svg?v=', true) }}{{ $version }}">
|
||||
|
||||
<title>@yield('title') | grocy</title>
|
||||
|
||||
<link href="{{ $U('/bower_components/bootstrap/dist/css/bootstrap.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/font-awesome/css/font-awesome.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/bootstrap-datepicker/dist/css/bootstrap-datepicker3.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/bootstrap-combobox/css/bootstrap-combobox.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/datatables.net-responsive-bs/css/responsive.bootstrap.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/toastr/toastr.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/tagmanager/tagmanager.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/bower_components/bootstrap-side-navbar/source/assets/stylesheets/navbar-fixed-side.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<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/@fortawesome/fontawesome-free/css/all.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">
|
||||
<link href="{{ $U('/node_modules/datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/toastr/build/toastr.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/tagmanager/tagmanager.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/components_unmanaged/noto-sans-v6-latin/noto-sans-v6-latin.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/css/grocy.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
@stack('pageStyles')
|
||||
|
||||
@if(file_exists(__DIR__ . '/../../data/custom.css'))
|
||||
@php include __DIR__ . '/../../data/custom.css' @endphp
|
||||
@endif
|
||||
|
||||
<script>
|
||||
var Grocy = { };
|
||||
Grocy.Components = { };
|
||||
@@ -36,93 +39,199 @@
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-mobile" >
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="{{ $U('/') }}">grocy</a>
|
||||
</div>
|
||||
<body class="fixed-nav">
|
||||
<nav id="mainNav" class="navbar navbar-expand-lg navbar-light fixed-top">
|
||||
<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="navbar" class="navbar-collapse collapse">
|
||||
@include('components.usermenu')
|
||||
</div>
|
||||
<div id="sidebarResponsive" class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav navbar-sidenav pt-2">
|
||||
|
||||
<div id="navbar-mobile" class="navbar-collapse collapse">
|
||||
@include('components.menu')
|
||||
@include('components.usermenu')
|
||||
</div>
|
||||
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="fas fa-battery-three-quarters"></i>
|
||||
<span class="nav-link-text">{{ $L('Batteries') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav sidenav-toggler">
|
||||
<li class="nav-item">
|
||||
<a id="sidenavToggler" class="nav-link text-center">
|
||||
<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 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="fas fa-sign-out-alt"></i> {{ $L('Logout') }}</a>
|
||||
</div>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle discrete-link" href="#" data-toggle="dropdown"><i class="fas fa-wrench"></i> <span class="d-inline d-lg-none">{{ $L('Settings') }}</span></a>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item discrete-link" href="{{ $U('/manageapikeys') }}"><i class="fas fa-handshake"></i> {{ $L('Manage API keys') }}</a>
|
||||
<a class="dropdown-item discrete-link" target="_blank" href="{{ $U('/api') }}"><i class="fas fa-book"></i> {{ $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="fas fa-info fa-fw"></i> {{ $L('About grocy') }} (Version {{ $version }})</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<div id="sidebar" class="col-sm-3 col-lg-2">
|
||||
<nav class="navbar navbar-default navbar-fixed-side hidden-xs">
|
||||
<div class="navbar-collapse collapse">
|
||||
@include('components.menu')
|
||||
</div>
|
||||
</nav>
|
||||
<div class="content-wrapper">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col content-text">
|
||||
@yield('content')
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-9 col-lg-10">
|
||||
@yield('content')
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="about-modal" tabindex="-1">
|
||||
<div class="modal fade content-text" id="about-modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content text-center">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">{{ $L('About grocy') }}</h4>
|
||||
<h4 class="modal-title w-100">{{ $L('About grocy') }}</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" title="{{ $L('Close') }}">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
grocy is a project by
|
||||
<a href="https://berrnd.de" target="_blank">Bernd Bestel</a><br>
|
||||
<a href="https://berrnd.de" class="discrete-link" target="_blank">Bernd Bestel</a><br>
|
||||
Created with passion since 2017<br>
|
||||
<br>
|
||||
Version {{ $version }}<br>
|
||||
{{ $L('Released on') }} {{ $releaseDate }} <time class="timeago timeago-contextual" datetime="{{ $releaseDate }}"></time><br>
|
||||
<br>
|
||||
Life runs on code<br>
|
||||
<a href="https://github.com/berrnd/grocy" target="_blank">
|
||||
<i class="fa fa-github"></i>
|
||||
<a href="https://github.com/berrnd/grocy" class="discrete-link" target="_blank">
|
||||
<i class="fas fa-github"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ $L('Close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{{ $U('/bower_components/jquery/dist/jquery.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/bootstrap/dist/js/bootstrap.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/bootbox/bootbox.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/jquery.serializeJSON/jquery.serializejson.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/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
|
||||
<script src="{{ $U('/bower_components/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('/bower_components/bootstrap-validator/dist/validator.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/bootstrap-combobox/js/bootstrap-combobox.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/datatables.net/js/jquery.dataTables.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/datatables.net-responsive/js/dataTables.responsive.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/datatables.net-responsive-bs/js/responsive.bootstrap.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/jquery-timeago/jquery.timeago.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components', true) }}/jquery-timeago/locales/jquery.timeago.{{ $L('timeago_locale') }}.js?v={{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/toastr/toastr.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/tagmanager/tagmanager.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/jquery/dist/jquery.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/startbootstrap-sb-admin/js/sb-admin.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<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/moment/min/moment.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>
|
||||
<script src="{{ $U('/node_modules/datatables.net-responsive/js/dataTables.responsive.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/datatables.net-responsive-bs4/js/responsive.bootstrap4.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/timeago/jquery.timeago.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules', true) }}/timeago/locales/jquery.timeago.{{ $L('timeago_locale') }}.js?v={{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/toastr/build/toastr.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/tagmanager/tagmanager.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min.js?v=', true) }}{{ $version }}"></script>
|
||||
|
||||
<script src="{{ $U('/js/extensions.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/js/grocy.js?v=', true) }}{{ $version }}"></script>
|
||||
@@ -130,8 +239,9 @@
|
||||
@stack('componentScripts')
|
||||
<script src="{{ $U('/viewjs', true) }}/@yield('viewJsName').js?v={{ $version }}"></script>
|
||||
|
||||
@if(file_exists(__DIR__ . '/../../data/add_before_end_body.html'))
|
||||
@php include __DIR__ . '/../../data/add_before_end_body.html' @endphp
|
||||
@if(file_exists(__DIR__ . '/../../data/custom.js'))
|
||||
@php include __DIR__ . '/../../data/custom.js' @endphp
|
||||
@endif
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
@@ -9,30 +9,32 @@
|
||||
@section('viewJsName', 'locationform')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
|
||||
@if($mode == 'edit')
|
||||
<script>Grocy.EditObjectId = {{ $location->id }};</script>
|
||||
@endif
|
||||
@if($mode == 'edit')
|
||||
<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="help-block with-errors"></div>
|
||||
</div>
|
||||
<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">{{ $L('A name is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $location->description }}@endif</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $location->description }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
<button id="save-location-button" type="submit" class="btn btn-default">{{ $L('Save') }}</button>
|
||||
<button id="save-location-button" type="submit" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,42 +5,55 @@
|
||||
@section('viewJsName', 'locations')
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">
|
||||
@yield('title')
|
||||
<a class="btn btn-default" href="{{ $U('/location/new') }}" role="button">
|
||||
<i class="fa fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
@yield('title')
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/location/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="locations-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($locations as $location)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info" href="{{ $U('/location/') }}{{ $location->id }}" role="button">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-danger location-delete-button" href="#" role="button" data-location-id="{{ $location->id }}" data-location-name="{{ $location->name }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $location->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $location->description }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row mt-3">
|
||||
<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>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="locations-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($locations as $location)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info btn-sm" href="{{ $U('/location/') }}{{ $location->id }}">
|
||||
<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="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $location->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $location->description }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -4,25 +4,27 @@
|
||||
@section('viewJsName', 'login')
|
||||
|
||||
@section('content')
|
||||
<div class="col-md-6 col-md-offset-3 col-xs-12">
|
||||
<h1 class="page-header text-center">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<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>
|
||||
<input type="text" class="form-control" required id="username" name="username">
|
||||
<div class="help-block with-errors"></div>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<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="help-block with-errors"></div>
|
||||
<div id="login-error" class="form-text text-danger d-none"></div>
|
||||
</div>
|
||||
|
||||
<button id="login-button" type="submit" class="btn btn-default">{{ $L('OK') }}</button>
|
||||
<button id="login-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,56 +5,67 @@
|
||||
@section('viewJsName', 'manageapikeys')
|
||||
|
||||
@push('pageScripts')
|
||||
<script src="{{ $U('/bower_components/jquery-ui/jquery-ui.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/jquery-ui-dist/jquery-ui.min.js?v=', true) }}{{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">
|
||||
@yield('title')
|
||||
<a class="btn btn-default" href="{{ $U('/manageapikeys/new') }}" role="button">
|
||||
<i class="fa fa-plus"></i> {{ $L('Create new API key') }}
|
||||
</a>
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
@yield('title')
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/manageapikeys/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="lead"><a href="{{ $U('/api') }}" target="_blank">{{ $L('REST API & data model documentation') }}</a></p>
|
||||
<div class="row mt-3">
|
||||
<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>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="apikeys-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('API key') }}</th>
|
||||
<th>{{ $L('Expires') }}</th>
|
||||
<th>{{ $L('Last used') }}</th>
|
||||
<th>{{ $L('Created') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($apiKeys as $apiKey)
|
||||
<tr id="apiKeyRow_{{ $apiKey->id }}">
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-danger apikey-delete-button" href="#" role="button" data-apikey-id="{{ $apiKey->id }}" data-apikey-apikey="{{ $apiKey->api_key }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $apiKey->api_key }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $apiKey->expires }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $apiKey->expires }}"></time>
|
||||
</td>
|
||||
<td>
|
||||
@if(empty($apiKey->last_used)){{ $L('never') }}@else{{ $apiKey->last_used }}@endif
|
||||
<time class="timeago timeago-contextual" datetime="{{ $apiKey->last_used }}"></time>
|
||||
</td>
|
||||
<td>
|
||||
{{ $apiKey->row_created_timestamp }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $apiKey->row_created_timestamp }}"></time>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="apikeys-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('API key') }}</th>
|
||||
<th>{{ $L('Expires') }}</th>
|
||||
<th>{{ $L('Last used') }}</th>
|
||||
<th>{{ $L('Created') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($apiKeys as $apiKey)
|
||||
<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="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $apiKey->api_key }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $apiKey->expires }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $apiKey->expires }}"></time>
|
||||
</td>
|
||||
<td>
|
||||
@if(empty($apiKey->last_used)){{ $L('never') }}@else{{ $apiKey->last_used }}@endif
|
||||
<time class="timeago timeago-contextual" datetime="{{ $apiKey->last_used }}"></time>
|
||||
</td>
|
||||
<td>
|
||||
{{ $apiKey->row_created_timestamp }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $apiKey->row_created_timestamp }}"></time>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -9,11 +9,11 @@
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
|
||||
<meta name="author" content="Bernd Bestel (bernd@berrnd.de)">
|
||||
<link rel="icon" type="image/png" sizes="200x200" href="{{ $U('/img/grocy.png?v=', true) }}{{ $version }}">
|
||||
<link rel="icon" href="{{ $U('/img/grocy_icon.svg?v=', true) }}{{ $version }}">
|
||||
|
||||
<title>{{ $L('REST API & data model documentation') }} | grocy</title>
|
||||
|
||||
<link href="{{ $U('/bower_components/swagger-ui/dist/swagger-ui.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/swagger-ui-dist/swagger-ui.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
|
||||
<script>
|
||||
var Grocy = { };
|
||||
@@ -25,8 +25,9 @@
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="{{ $U('/bower_components/swagger-ui/dist/swagger-ui-bundle.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/bower_components/swagger-ui/dist/swagger-ui-standalone-preset.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/swagger-ui-dist/swagger-ui.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/swagger-ui-dist/swagger-ui-bundle.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/swagger-ui-dist/swagger-ui-standalone-preset.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/viewjs', true) }}/openapiui.js?v={{ $version }}"></script>
|
||||
|
||||
@if(file_exists(__DIR__ . '/../../data/add_before_end_body.html'))
|
||||
|
@@ -9,85 +9,87 @@
|
||||
@section('viewJsName', 'productform')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
|
||||
@if($mode == 'edit')
|
||||
<script>Grocy.EditObjectId = {{ $product->id }};</script>
|
||||
@endif
|
||||
@if($mode == 'edit')
|
||||
<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="help-block with-errors"></div>
|
||||
</div>
|
||||
<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">{{ $L('A name is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $product->description }}@endif</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $product->description }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group tm-group">
|
||||
<label for="barcode-taginput">{{ $L('Barcode(s)') }} <i class="fa fa-barcode"></i></label>
|
||||
<input type="text" class="form-control tm-input" id="barcode-taginput">
|
||||
<div id="barcode-taginput-container"></div>
|
||||
</div>
|
||||
<div class="form-group tm-group">
|
||||
<label for="barcode-taginput">{{ $L('Barcode(s)') }} <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>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="location_id">{{ $L('Location') }}</label>
|
||||
<select required class="form-control" id="location_id" name="location_id">
|
||||
@foreach($locations as $location)
|
||||
<option @if($mode == 'edit' && $location->id == $product->location_id) selected="selected" @endif value="{{ $location->id }}">{{ $location->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="location_id">{{ $L('Location') }}</label>
|
||||
<select required class="form-control" id="location_id" name="location_id">
|
||||
@foreach($locations as $location)
|
||||
<option @if($mode == 'edit' && $location->id == $product->location_id) selected="selected" @endif value="{{ $location->id }}">{{ $location->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<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="help-block with-errors"></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">{{ $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="help-block with-errors"></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">{{ $L('This cannot be negative') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="qu_id_purchase">{{ $L('Quantity unit purchase') }}</label>
|
||||
<select required class="form-control input-group-qu" id="qu_id_purchase" name="qu_id_purchase">
|
||||
@foreach($quantityunits as $quantityunit)
|
||||
<option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_purchase) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="qu_id_purchase">{{ $L('Quantity unit purchase') }}</label>
|
||||
<select required class="form-control input-group-qu" id="qu_id_purchase" name="qu_id_purchase">
|
||||
@foreach($quantityunits as $quantityunit)
|
||||
<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">{{ $L('A quantity unit is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="qu_id_stock">{{ $L('Quantity unit stock') }}</label>
|
||||
<select required class="form-control input-group-qu" id="qu_id_stock" name="qu_id_stock">
|
||||
@foreach($quantityunits as $quantityunit)
|
||||
<option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_stock) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="qu_id_stock">{{ $L('Quantity unit stock') }}</label>
|
||||
<select required class="form-control input-group-qu" id="qu_id_stock" name="qu_id_stock">
|
||||
@foreach($quantityunits as $quantityunit)
|
||||
<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">{{ $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="help-block with-errors"></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">{{ $L('The amount cannot be lower than #1', '1') }}</div>
|
||||
</div>
|
||||
|
||||
<p id="qu-conversion-info" class="help-block 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-default">{{ $L('Save') }}</button>
|
||||
</form>
|
||||
<button id="save-product-button" type="submit" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,62 +5,75 @@
|
||||
@section('viewJsName', 'products')
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">
|
||||
@yield('title')
|
||||
<a class="btn btn-default" href="{{ $U('/product/new') }}" role="button">
|
||||
<i class="fa fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
@yield('title')
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/product/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="products-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Location') }}</th>
|
||||
<th>{{ $L('Min. stock amount') }}</th>
|
||||
<th>{{ $L('QU purchase') }}</th>
|
||||
<th>{{ $L('QU stock') }}</th>
|
||||
<th>{{ $L('QU factor') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($products as $product)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info" href="{{ $U('/product/') }}{{ $product->id }}" role="button">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-danger product-delete-button" href="#" role="button" data-product-id="{{ $product->id }}" data-product-name="{{ $product->name }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $product->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($locations, 'id', $product->location_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $product->min_stock_amount }}
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_purchase)->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_stock)->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $product->qu_factor_purchase_to_stock }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $product->description }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row mt-3">
|
||||
<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>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="products-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Location') }}</th>
|
||||
<th>{{ $L('Min. stock amount') }}</th>
|
||||
<th>{{ $L('QU purchase') }}</th>
|
||||
<th>{{ $L('QU stock') }}</th>
|
||||
<th>{{ $L('QU factor') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($products as $product)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info btn-sm" href="{{ $U('/product/') }}{{ $product->id }}">
|
||||
<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="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $product->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($locations, 'id', $product->location_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $product->min_stock_amount }}
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_purchase)->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_stock)->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $product->qu_factor_purchase_to_stock }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $product->description }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,40 +5,48 @@
|
||||
@section('viewJsName', 'purchase')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6 col-xl-4 pb-3">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<form id="purchase-form">
|
||||
<form id="purchase-form" novalidate>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="product_id">{{ $L('Product') }} <i class="fa fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted hide"> 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="help-block with-errors"></div>
|
||||
<div id="flow-info-addbarcodetoselection" class="text-muted small hide"><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="product_id">{{ $L('Product') }} <i class="fas fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted d-none"> 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">{{ $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(
|
||||
'id' => 'best_before_date',
|
||||
'label' => 'Best before'
|
||||
))
|
||||
@include('components.datetimepicker', array(
|
||||
'id' => 'best_before_date',
|
||||
'label' => 'Best before',
|
||||
'format' => 'YYYY-MM-DD',
|
||||
'initWithNow' => false,
|
||||
'limitEndToNow' => false,
|
||||
'limitStartToNow' => true,
|
||||
'invalidFeedback' => $L('A best before date is required and must be later than today'),
|
||||
'nextInputSelector' => '#amount'
|
||||
))
|
||||
|
||||
<div class="form-group">
|
||||
<label for="amount">{{ $L('Amount') }} <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="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="amount">{{ $L('Amount') }} <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">{{ $L('The amount cannot be lower than #1', '1') }}</div>
|
||||
</div>
|
||||
|
||||
<button id="save-purchase-button" type="submit" class="btn btn-default">{{ $L('OK') }}</button>
|
||||
<button id="save-purchase-button" type="submit" class="btn btn-success">{{ $L('OK') }}</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
@include('components.productcard')
|
||||
<div class="col-xs-12 col-md-6 col-xl-4">
|
||||
@include('components.productcard')
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -9,30 +9,32 @@
|
||||
@section('viewJsName', 'quantityunitform')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
|
||||
@if($mode == 'edit')
|
||||
<script>Grocy.EditObjectId = {{ $quantityunit->id }};</script>
|
||||
@endif
|
||||
@if($mode == 'edit')
|
||||
<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="help-block with-errors"></div>
|
||||
</div>
|
||||
<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">{{ $L('A name is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $quantityunit->description }}@endif</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">{{ $L('Description') }}</label>
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $quantityunit->description }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
<button id="save-quantityunit-button" type="submit" class="btn btn-default">{{ $L('Save') }}</button>
|
||||
<button id="save-quantityunit-button" type="submit" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,42 +5,55 @@
|
||||
@section('viewJsName', 'quantityunits')
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">
|
||||
@yield('title')
|
||||
<a class="btn btn-default" href="{{ $U('/quantityunit/new') }}" role="button">
|
||||
<i class="fa fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
@yield('title')
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/quantityunit/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="quantityunits-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($quantityunits as $quantityunit)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info" href="{{ $U('/quantityunit/') }}{{ $quantityunit->id }}" role="button">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-danger quantityunit-delete-button" href="#" role="button" data-quantityunit-id="{{ $quantityunit->id }}" data-quantityunit-name="{{ $quantityunit->name }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $quantityunit->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $quantityunit->description }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row mt-3">
|
||||
<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>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="quantityunits-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($quantityunits as $quantityunit)
|
||||
<tr>
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info btn-sm" href="{{ $U('/quantityunit/') }}{{ $quantityunit->id }}">
|
||||
<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="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $quantityunit->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $quantityunit->description }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,45 +5,58 @@
|
||||
@section('viewJsName', 'shoppinglist')
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">
|
||||
@yield('title')
|
||||
<a class="btn btn-default" href="{{ $U('/shoppinglistitem/new') }}" role="button">
|
||||
<i class="fa fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a id="add-products-below-min-stock-amount" class="btn btn-info" href="#" role="button">
|
||||
<i class="fa fa-plus"></i> {{ $L('Add products that are below defined min. stock amount') }}
|
||||
</a>
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
@yield('title')
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/shoppinglistitem/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a id="add-products-below-min-stock-amount" class="btn btn-info" href="#">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add products that are below defined min. stock amount') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="shoppinglist-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Product') }} / <em>{{ $L('Note') }}</em></th>
|
||||
<th>{{ $L('Amount') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($listItems as $listItem)
|
||||
<tr class="@if($listItem->amount_autoadded > 0) info-bg @endif">
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-info" href="{{ $U('/shoppinglistitem/') }}{{ $listItem->id }}" role="button">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-danger shoppinglist-delete-button" href="#" role="button" data-shoppinglist-id="{{ $listItem->id }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
@if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name }}<br>@endif<em>{{ $listItem->note }}</em>
|
||||
</td>
|
||||
<td>
|
||||
{{ $listItem->amount + $listItem->amount_autoadded }} @if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name }}@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row mt-3">
|
||||
<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>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="shoppinglist-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Product') }} / <em>{{ $L('Note') }}</em></th>
|
||||
<th>{{ $L('Amount') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($listItems as $listItem)
|
||||
<tr class="@if($listItem->amount_autoadded > 0) table-info @endif">
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-sm btn-info" href="{{ $U('/shoppinglistitem/') }}{{ $listItem->id }}">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<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>
|
||||
@if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name }}<br>@endif<em>{{ $listItem->note }}</em>
|
||||
</td>
|
||||
<td>
|
||||
{{ $listItem->amount + $listItem->amount_autoadded }} @if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name }}@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -9,45 +9,46 @@
|
||||
@section('viewJsName', 'shoppinglistform')
|
||||
|
||||
@section('content')
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
<h1 class="page-header">@yield('title')</h1>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6 col-xl-4 pb-3">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
|
||||
@if($mode == 'edit')
|
||||
<script>Grocy.EditObjectId = {{ $listItem->id }};</script>
|
||||
@endif
|
||||
@if($mode == 'edit')
|
||||
<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') }} <i class="fa 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="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="product_id">{{ $L('Product') }} <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>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="amount">{{ $L('Amount') }} <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="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="amount">{{ $L('Amount') }} <span id="amount_qu_unit" class="small text-muted"></span><br><span class="small text-muted">@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">{{ $L('This cannot be negative') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="note">{{ $L('Note') }}</label>
|
||||
<textarea class="form-control" rows="2" id="note" name="note">@if($mode == 'edit'){{ $listItem->note }}@endif</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="note">{{ $L('Note') }}</label>
|
||||
<textarea class="form-control" rows="2" id="note" name="note">@if($mode == 'edit'){{ $listItem->note }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
<button id="save-shoppinglist-button" type="submit" class="btn btn-default">{{ $L('Save') }}</button>
|
||||
<button id="save-shoppinglist-button" type="submit" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-xs-12">
|
||||
@include('components.productcard')
|
||||
<div class="col-xs-12 col-md-6 col-xl-4">
|
||||
@include('components.productcard')
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@@ -5,64 +5,83 @@
|
||||
@section('viewJsName', 'stockoverview')
|
||||
|
||||
@push('pageScripts')
|
||||
<script src="{{ $U('/bower_components/jquery-ui/jquery-ui.min.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/node_modules/jquery-ui-dist/jquery-ui.min.js?v=', true) }}{{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<h1 class="page-header">{{ $L('Stock overview') }} <span class="text-muted small">{{ $L('#1 products with #2 units in stock', count($currentStock), SumArrayValue($currentStock, 'amount')) }}</span></h1>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<p class="btn btn-lg btn-warning no-real-button responsive-button">{{ $L('#1 products expiring within the next #2 days', $countExpiringNextXDays, $nextXDays) }}</p>
|
||||
<p class="btn btn-lg btn-danger no-real-button responsive-button">{{ $L('#1 products are already expired', $countAlreadyExpired) }}</p>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>@yield('title') <small class="text-muted">{{ $L('#1 products with #2 units in stock', count($currentStock), SumArrayValue($currentStock, 'amount')) }}</small></h1>
|
||||
<p class="btn btn-lg btn-warning no-real-button responsive-button mr-2">{{ $L('#1 products expiring within the next #2 days', $countExpiringNextXDays, $nextXDays) }}</p>
|
||||
<p class="btn btn-lg btn-danger no-real-button responsive-button mr-2">{{ $L('#1 products are already expired', $countAlreadyExpired) }}</p>
|
||||
<p class="btn btn-lg btn-info no-real-button responsive-button">{{ $L('#1 products are below defined min. stock amount', count($missingProducts)) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="discrete-content-separator-2x"></div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="stock-overview-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Product') }}</th>
|
||||
<th>{{ $L('Amount') }}</th>
|
||||
<th>{{ $L('Next best before date') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($currentStock as $currentStockEntry)
|
||||
<tr id="product-{{ $currentStockEntry->product_id }}-row" class="@if($currentStockEntry->best_before_date < date('Y-m-d', strtotime('-1 days'))) error-bg @elseif($currentStockEntry->best_before_date < date('Y-m-d', strtotime('+5 days'))) warning-bg @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) info-bg @endif">
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-success btn-xs product-consume-button" href="#" title="{{ $L('Consume #3 #1 of #2', FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name, 1) }}"
|
||||
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="1">
|
||||
<i class="fa fa-cutlery"></i> 1
|
||||
</a>
|
||||
<a id="product-{{ $currentStockEntry->product_id }}-consume-all-button" class="btn btn-danger btn-xs 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') }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
<span id="product-{{ $currentStockEntry->product_id }}-amount">{{ $currentStockEntry->amount }}</span> {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $currentStockEntry->best_before_date }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $currentStockEntry->best_before_date }}"></time>
|
||||
</td>
|
||||
</tr>
|
||||
<div class="row mt-3">
|
||||
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||
<label for="location-filter">{{ $L('Filter by location') }}</label> <i class="fas fa-filter"></i>
|
||||
<select class="form-control" id="location-filter">
|
||||
<option value="all">{{ $L('All') }}</option>
|
||||
@foreach($locations as $location)
|
||||
<option value="{{ $location->name }}">{{ $location->name }}</option>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||
<label for="search">{{ $L('Search') }}</label> <i class="fas fa-search"></i>
|
||||
<input type="text" class="form-control" id="search">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="stock-overview-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{{ $L('Product') }}</th>
|
||||
<th>{{ $L('Amount') }}</th>
|
||||
<th>{{ $L('Next best before date') }}</th>
|
||||
<th class="hidden">Hidden location</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($currentStock as $currentStockEntry)
|
||||
<tr id="product-{{ $currentStockEntry->product_id }}-row" class="@if($currentStockEntry->best_before_date < date('Y-m-d', strtotime('-1 days'))) table-danger @elseif($currentStockEntry->best_before_date < date('Y-m-d', strtotime('+5 days'))) table-warning @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) table-info @endif">
|
||||
<td class="fit-content">
|
||||
<a class="btn btn-success btn-sm product-consume-button" href="#" title="{{ $L('Consume #3 #1 of #2', FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name, 1) }}"
|
||||
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="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="fas fa-utensils"></i> {{ $L('All') }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
<span id="product-{{ $currentStockEntry->product_id }}-amount">{{ $currentStockEntry->amount }}</span> {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $currentStockEntry->best_before_date }}
|
||||
<time class="timeago timeago-contextual" datetime="{{ $currentStockEntry->best_before_date }}"></time>
|
||||
</td>
|
||||
<td class="hidden">
|
||||
{{ FindObjectInArrayByPropertyValue($locations, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->location_id)->name }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
181
yarn.lock
Normal file
181
yarn.lock
Normal file
@@ -0,0 +1,181 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@danielfarrell/bootstrap-combobox@https://github.com/pallidus-fintech/bootstrap-combobox.git#enhance/boostrap_4":
|
||||
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"
|
||||
|
||||
"bootstrap-side-navbar@https://github.com/samrayner/bootstrap-side-navbar.git#1.0.1":
|
||||
version "0.0.0"
|
||||
resolved "https://github.com/samrayner/bootstrap-side-navbar.git#bda4883fd2b278df3a48db4add7dc4d994477734"
|
||||
|
||||
bootstrap@4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.0.0.tgz#ceb03842c145fcc1b9b4e15da2a05656ba68469a"
|
||||
|
||||
bootstrap@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.1.tgz#3aec85000fa619085da8d2e4983dfd67cf2114cb"
|
||||
|
||||
chart.js@2.7.1:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.7.1.tgz#ae90b4aa4ff1f02decd6b1a2a8dabfd73c9f9886"
|
||||
dependencies:
|
||||
chartjs-color "~2.2.0"
|
||||
moment "~2.18.0"
|
||||
|
||||
chartjs-color-string@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz#8d3752d8581d86687c35bfe2cb80ac5213ceb8c1"
|
||||
dependencies:
|
||||
color-name "^1.0.0"
|
||||
|
||||
chartjs-color@~2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.2.0.tgz#84a2fb755787ed85c39dd6dd8c7b1d88429baeae"
|
||||
dependencies:
|
||||
chartjs-color-string "^0.5.0"
|
||||
color-convert "^0.5.3"
|
||||
|
||||
color-convert@^0.5.3:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
|
||||
|
||||
color-name@^1.0.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
|
||||
datatables.net-bs4@1.10.16:
|
||||
version "1.10.16"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-bs4/-/datatables.net-bs4-1.10.16.tgz#9eee67cfa8565bd3807a603a188305f7d0e20e32"
|
||||
dependencies:
|
||||
datatables.net "1.10.16"
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net-bs4@^1.10.15, datatables.net-bs4@^1.10.19:
|
||||
version "1.10.19"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-bs4/-/datatables.net-bs4-1.10.19.tgz#0608dff22008cf3c7b8a68b1bc702ed255b404fb"
|
||||
dependencies:
|
||||
datatables.net "1.10.19"
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net-responsive-bs4@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-responsive-bs4/-/datatables.net-responsive-bs4-2.2.3.tgz#639de17c1d31210ebf2b3c25f1c774c13f729e94"
|
||||
dependencies:
|
||||
datatables.net-bs4 "^1.10.15"
|
||||
datatables.net-responsive "2.2.3"
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net-responsive@2.2.3, datatables.net-responsive@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-responsive/-/datatables.net-responsive-2.2.3.tgz#50a2b1b4955b16b32f573a3f00f473b0bfbee913"
|
||||
dependencies:
|
||||
datatables.net "^1.10.15"
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net@1.10.16:
|
||||
version "1.10.16"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.16.tgz#4b052d1082824261b68eed9d22741b711d3d2469"
|
||||
dependencies:
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net@1.10.19, datatables.net@^1.10.15, datatables.net@^1.10.19:
|
||||
version "1.10.19"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.19.tgz#97a1ed41c85e62d61040603481b59790a172dd1f"
|
||||
dependencies:
|
||||
jquery ">=1.7"
|
||||
|
||||
font-awesome@4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133"
|
||||
|
||||
jquery-serializejson@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery-serializejson/-/jquery-serializejson-2.8.1.tgz#fc40dd11e5d9a6fd2a3614fdcba89e4af794f0a8"
|
||||
|
||||
jquery-ui-dist@^1.12.1:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery-ui-dist/-/jquery-ui-dist-1.12.1.tgz#5c0815d3cc6f90ff5faaf5b268a6e23b4ca904fa"
|
||||
|
||||
jquery.easing@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery.easing/-/jquery.easing-1.4.1.tgz#47982c5836bd758fd48494923c4a101ef6e93e3b"
|
||||
|
||||
jquery@1:
|
||||
version "1.12.4"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-1.12.4.tgz#01e1dfba290fe73deba77ceeacb0f9ba2fec9e0c"
|
||||
|
||||
jquery@3.3.1, jquery@>=1.12.0, jquery@>=1.2.3, jquery@>=1.7, jquery@^3.0, jquery@^3.3.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
|
||||
|
||||
moment-timezone@^0.5.11:
|
||||
version "0.5.21"
|
||||
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845"
|
||||
dependencies:
|
||||
moment ">= 2.9.0"
|
||||
|
||||
"moment@>= 2.9.0", moment@^2.22.2:
|
||||
version "2.22.2"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
|
||||
|
||||
moment@~2.18.0:
|
||||
version "2.18.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
|
||||
|
||||
popper.js@^1.12.9:
|
||||
version "1.14.3"
|
||||
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095"
|
||||
|
||||
startbootstrap-sb-admin@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/startbootstrap-sb-admin/-/startbootstrap-sb-admin-4.0.0.tgz#cf141a260d031b36bdc013c68200a1c1ea6c9881"
|
||||
dependencies:
|
||||
bootstrap "4.0.0"
|
||||
chart.js "2.7.1"
|
||||
datatables.net-bs4 "1.10.16"
|
||||
font-awesome "4.7.0"
|
||||
jquery "3.3.1"
|
||||
jquery.easing "^1.4.1"
|
||||
|
||||
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"
|
||||
|
||||
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"
|
||||
dependencies:
|
||||
bootstrap "4.0.0"
|
||||
jquery "^3.0"
|
||||
moment "^2.22.2"
|
||||
moment-timezone "^0.5.11"
|
||||
popper.js "^1.12.9"
|
||||
|
||||
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.4:
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181"
|
||||
dependencies:
|
||||
jquery ">=1.12.0"
|
Reference in New Issue
Block a user