mirror of
https://github.com/grocy/grocy.git
synced 2025-09-16 09:51:30 +00:00
Compare commits
76 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
04dacacd73 | ||
|
a9502d1ddb | ||
|
5c25e91984 | ||
|
02163c4305 | ||
|
c3731b3200 | ||
|
5cdf2c14d3 | ||
|
e92d74f5c3 | ||
|
2b3516dadd | ||
|
8041dd9c26 | ||
|
2f7b78bc40 | ||
|
61fc6e05f4 | ||
|
367a3e52de | ||
|
a3617cffb8 | ||
|
ff341d8547 | ||
|
01fab6999f | ||
|
b6152ce874 | ||
|
ca5df3b217 | ||
|
dd48be595c | ||
|
306d0f7da6 | ||
|
c61c37e67a | ||
|
f7f90238f2 | ||
|
589ad36855 | ||
|
5da24d2d4f | ||
|
f7f2bf3fc0 | ||
|
34d1bdd53f | ||
|
e021c93d22 | ||
|
2ff5faacc0 | ||
|
a489190e81 | ||
|
a403bb687a | ||
|
5966a3d678 | ||
|
c71e46191f | ||
|
862fd7c644 | ||
|
10ea9c44fd | ||
|
816ca6460f | ||
|
b6d60c4e34 | ||
|
6f67619784 | ||
|
db0b48e7ae | ||
|
973f07b360 | ||
|
0f73d849eb | ||
|
1a6849ad37 | ||
|
8f31f891fd | ||
|
83985e9f21 | ||
|
04e9ba8e34 | ||
|
960ee919f9 | ||
|
f4534a4bfb | ||
|
89553b7fa0 | ||
|
364f6b2051 | ||
|
fe83e2fa6f | ||
|
1f3dd58ddf | ||
|
da98efa833 | ||
|
3e6cf545d7 | ||
|
1080c3486c | ||
|
cd7b6b686d | ||
|
b84e6da0dd | ||
|
fc3a4c6899 | ||
|
12a2cb0bdf | ||
|
57a0864465 | ||
|
b3da837ede | ||
|
3de3e03ab3 | ||
|
78865a9d3c | ||
|
5b3230d63d | ||
|
04c93d937e | ||
|
5318e79f55 | ||
|
7bf4421d44 | ||
|
366152c049 | ||
|
70c00e81d9 | ||
|
f13abf483e | ||
|
0e723a0a9b | ||
|
4a35477c35 | ||
|
df7d360516 | ||
|
03eaa6c79f | ||
|
132999ce36 | ||
|
188407e3c7 | ||
|
8cf68ade30 | ||
|
d62657c698 | ||
|
3262e534dc |
@@ -1,6 +0,0 @@
|
||||
.git
|
||||
.vscode
|
||||
.gitignore
|
||||
build.bat
|
||||
Dockerfile
|
||||
.DS_store
|
37
.tx/config
Normal file
37
.tx/config
Normal file
@@ -0,0 +1,37 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[grocy.stringsphp]
|
||||
file_filter = localization/<lang>/strings.php
|
||||
minimum_perc = 0
|
||||
source_file = localization/en/strings.php
|
||||
source_lang = en
|
||||
type = PHP_ARRAY
|
||||
|
||||
[grocy.stock_transaction_typesphp]
|
||||
file_filter = localization/<lang>/stock_transaction_types.php
|
||||
minimum_perc = 0
|
||||
source_file = localization/en/stock_transaction_types.php
|
||||
source_lang = en
|
||||
type = PHP_ARRAY
|
||||
|
||||
[grocy.chore_typesphp]
|
||||
file_filter = localization/<lang>/chore_types.php
|
||||
minimum_perc = 0
|
||||
source_file = localization/en/chore_types.php
|
||||
source_lang = en
|
||||
type = PHP_ARRAY
|
||||
|
||||
[grocy.component_translationsphp]
|
||||
file_filter = localization/<lang>/component_translations.php
|
||||
minimum_perc = 0
|
||||
source_file = localization/en/component_translations.php
|
||||
source_lang = en
|
||||
type = PHP_ARRAY
|
||||
|
||||
[grocy.demo_dataphp]
|
||||
file_filter = localization/<lang>/demo_data.php
|
||||
minimum_perc = 0
|
||||
source_file = localization/en/demo_data.php
|
||||
source_lang = en
|
||||
type = PHP_ARRAY
|
@@ -1,58 +0,0 @@
|
||||
FROM php:7.2-fpm-alpine
|
||||
MAINTAINER Talmai Oliveira <to@talm.ai>
|
||||
|
||||
RUN apk update && \
|
||||
apk upgrade && \
|
||||
apk add --update yarn git &&\
|
||||
mkdir -p /www && \
|
||||
# Set environments
|
||||
sed -i "s|;*daemonize\s*=\s*yes|daemonize = no|g" /usr/local/etc/php-fpm.conf && \
|
||||
sed -i "s|;*listen\s*=\s*127.0.0.1:9000|listen = 9000|g" /usr/local/etc/php-fpm.conf && \
|
||||
sed -i "s|;*listen\s*=\s*/||g" /usr/local/etc/php-fpm.conf && \
|
||||
# sed -i "s|;*log_level\s*=\s*notice|log_level = debug|g" /usr/local/etc/php-fpm.conf && \
|
||||
sed -i "s|;*chdir\s*=\s*/var/www|chdir = /www|g" /usr/local/etc/php-fpm.d/www.conf && \
|
||||
# sed -i "s|;*access.log\s*=\s*log/\$pool.access.log|access.log = \$pool.access.log|g" /usr/local/etc/php-fpm.d/www.conf && \
|
||||
# sed -i "s|;*pm.status_path\s*=\s*/status|pm.status_path = /status|g" /usr/local/etc/php-fpm.d/www.conf && \
|
||||
# sed -i "s|;*memory_limit =.*|memory_limit = ${PHP_MEMORY_LIMIT}|i" /usr/local/etc/php.ini && \
|
||||
# sed -i "s|;*upload_max_filesize =.*|upload_max_filesize = ${MAX_UPLOAD}|i" /usr/local/etc/php.ini && \
|
||||
# sed -i "s|;*max_file_uploads =.*|max_file_uploads = ${PHP_MAX_FILE_UPLOAD}|i" /usr/local/etc/php.ini && \
|
||||
# sed -i "s|;*post_max_size =.*|post_max_size = ${PHP_MAX_POST}|i" /usr/local/etc/php.ini && \
|
||||
# sed -i "s|;*cgi.fix_pathinfo=.*|cgi.fix_pathinfo= 0|i" /usr/local/etc/php.ini && \
|
||||
wget https://raw.githubusercontent.com/composer/getcomposer.org/1b137f8bf6db3e79a38a5bc45324414a6b1f9df2/web/installer -O - -q | php -- --quiet && \
|
||||
# Cleaning up
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
COPY public /www/public
|
||||
COPY info.php /www/public
|
||||
COPY controllers /www/controllers
|
||||
COPY data /www/data
|
||||
COPY helpers /www/helpers
|
||||
COPY localization/ /www/localization
|
||||
COPY middleware/ /www/middleware
|
||||
COPY migrations/ /www/migrations
|
||||
COPY publication_assets/ /www/publication_assets
|
||||
COPY services/ /www/services
|
||||
COPY views/ /www/views
|
||||
COPY .yarnrc /www/
|
||||
COPY *.php /www/
|
||||
COPY *.json /www/
|
||||
COPY composer.* /root/.composer/
|
||||
COPY *yarn* /www/
|
||||
COPY *.sh /www/
|
||||
|
||||
# run php composer.phar with -vvv for extra debug information
|
||||
RUN cd /var/www/html && \
|
||||
php composer.phar --working-dir=/www/ -n install && \
|
||||
cp /www/config-dist.php /www/data/config.php && \
|
||||
cd /www && \
|
||||
yarn install && \
|
||||
chown www-data:www-data -R /www/
|
||||
|
||||
# Set Workdir
|
||||
WORKDIR /www/public
|
||||
|
||||
# Expose volumes
|
||||
VOLUME ["/www"]
|
||||
|
||||
# Expose ports
|
||||
EXPOSE 9000
|
@@ -1,32 +0,0 @@
|
||||
FROM alpine:latest
|
||||
MAINTAINER Talmai Oliveira <to@talm.ai>
|
||||
|
||||
RUN apk update && \
|
||||
apk upgrade && \
|
||||
apk add --update openssl nginx && \
|
||||
mkdir -p /etc/nginx/certificates && \
|
||||
mkdir -p /var/run/nginx && \
|
||||
mkdir -p /usr/share/nginx/html && \
|
||||
openssl req \
|
||||
-x509 \
|
||||
-newkey rsa:2048 \
|
||||
-keyout /etc/nginx/certificates/key.pem \
|
||||
-out /etc/nginx/certificates/cert.pem \
|
||||
-days 365 \
|
||||
-nodes \
|
||||
-subj /CN=localhost && \
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
COPY docker_nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
COPY docker_nginx/common.conf /etc/nginx/common.conf
|
||||
COPY docker_nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
|
||||
COPY docker_nginx/conf.d/ssl.conf /etc/nginx/conf.d/ssl.conf
|
||||
|
||||
# Expose volumes
|
||||
VOLUME ["/etc/nginx/conf.d", "/var/log/nginx"]
|
||||
|
||||
# Expose ports
|
||||
EXPOSE 80 443
|
||||
|
||||
# Entry point
|
||||
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
|
24
README.md
24
README.md
@@ -13,9 +13,9 @@ A household needs to be managed. I did this so far (almost 10 years) with my fir
|
||||
>
|
||||
> There is now grocy-desktop if you want to run grocy without a webserver just like a normal (windows) desktop application.
|
||||
>
|
||||
> See https://github.com/berrnd/grocy-desktop or directly download the [latest release](https://releases.grocy.info/latest-desktop) - the installation is nothing more than just clicking 2 times "next"...
|
||||
> See https://github.com/grocy/grocy-desktop or directly download the [latest release](https://releases.grocy.info/latest-desktop) - the installation is nothing more than just clicking 2 times "next"...
|
||||
|
||||
Just unpack the [latest release](https://releases.grocy.info/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, (to make writable `chown -R www-data:www-data data/`). Default login is user `admin` with password `admin`, please change the password immediately (see user menu).
|
||||
Just unpack the [latest release](https://releases.grocy.info/latest) on your PHP (SQLite (3.8.3 or higher) 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, (to make writable `chown -R www-data:www-data data/`). Default login is user `admin` with password `admin`, please change the password immediately (see user menu).
|
||||
|
||||
Alternatively clone this repository and install Composer and Yarn dependencies manually.
|
||||
|
||||
@@ -25,13 +25,7 @@ If, however, your webserver does not support URL rewriting, set `DISABLE_URL_REW
|
||||
|
||||
## How to run using Docker
|
||||
|
||||
The docker images build are based on [Alpine](https://hub.docker.com/_/alpine/), with an extremelly low footprint (less than 10 MB for nginx, and less than 70MB for grocy with php-fm. That number is eventually bumped up to 353MB after all the dependencies are downloaded, however). Anyhow, to run using docker just do the following:
|
||||
|
||||
```
|
||||
> docker-compose up
|
||||
```
|
||||
|
||||
And grocy should be accessible via `http(s)://localhost/`. The https option will work. However, since the certificate is self-signed, most browsers will complain.
|
||||
See [grocy/grocy-docker](https://github.com/grocy/grocy-docker) for instructions.
|
||||
|
||||
## 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` (the default from values `config-dist.php` will be used for not in `data/config.php` defined settings). Just to be sure, please empty `data/viewcache`.
|
||||
@@ -39,7 +33,9 @@ Just overwrite everything with the latest release while keeping the `data` direc
|
||||
If you run grocy on Linux, there is also `update.sh` (remember to make the script executable, `chmod +x update.sh` and ensure that you have `unzip` installed) which does exactly this and additionally creates a backup (`.tgz` archive) of the current installation in `data/backups` (backups older than 60 days will be deleted during the update).
|
||||
|
||||
## 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');`)
|
||||
grocy is fully localizable - the default language is English (integrated into code), a German localization is always maintained by me.
|
||||
You can easily help translating grocy at https://www.transifex.com/grocy/grocy, if your language is incomplete or not available yet.
|
||||
(Language can be changed in `data/config.php`, e. g. `Setting('CULTURE', 'it');`)
|
||||
|
||||
### Maintaining your own localization
|
||||
As the German translation will always be the most complete one, for maintaining your localization it would be easiest when you compare your localization with the German one with a diff tool of your choice.
|
||||
@@ -85,19 +81,19 @@ Database schema migration is automatically done when visiting the root (`/`) rou
|
||||
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.
|
||||
|
||||
### Embedded mode
|
||||
When the file `embedded.txt` exists, it must contain a valid and writable path which will be used as the data directory instead of `data` and authentication will be disabled (used in [grocy-desktop](https://github.com/berrnd/grocy-desktop)).
|
||||
When the file `embedded.txt` exists, it must contain a valid and writable path which will be used as the data directory instead of `data` and authentication will be disabled (used in [grocy-desktop](https://github.com/grocy/grocy-desktop)).
|
||||
|
||||
In embedded mode, settings can be overridden by text files in `data/settingoverrides`, the file name must be `<SettingName>.txt` (e. g. `BASE_URL.txt`) and the content must be the setting value (normally one single line).
|
||||
|
||||
## Screenshots
|
||||
#### Dashboard
|
||||

|
||||

|
||||
|
||||
#### Purchase - with barcode scan
|
||||

|
||||

|
||||
|
||||
#### Consume - with manual search
|
||||

|
||||

|
||||
|
||||
## License
|
||||
The MIT License (MIT)
|
||||
|
128
composer.lock
generated
128
composer.lock
generated
@@ -159,20 +159,21 @@
|
||||
},
|
||||
{
|
||||
"name": "illuminate/container",
|
||||
"version": "v5.7.8",
|
||||
"version": "v5.7.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/container.git",
|
||||
"reference": "2582a994f2f8a153a4880de757a89ad4eeb083d7"
|
||||
"reference": "4c90c3d3ba88e52da152e885d24c9f891a2ec545"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/container/zipball/2582a994f2f8a153a4880de757a89ad4eeb083d7",
|
||||
"reference": "2582a994f2f8a153a4880de757a89ad4eeb083d7",
|
||||
"url": "https://api.github.com/repos/illuminate/container/zipball/4c90c3d3ba88e52da152e885d24c9f891a2ec545",
|
||||
"reference": "4c90c3d3ba88e52da152e885d24c9f891a2ec545",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/contracts": "5.7.*",
|
||||
"illuminate/support": "5.7.*",
|
||||
"php": "^7.1.3",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
@@ -199,20 +200,20 @@
|
||||
],
|
||||
"description": "The Illuminate Container package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"time": "2018-10-03T15:20:19+00:00"
|
||||
"time": "2018-10-18T03:39:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/contracts",
|
||||
"version": "v5.7.8",
|
||||
"version": "v5.7.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/contracts.git",
|
||||
"reference": "9532d673de305b0c0028c0ce60c8952b807d7bc3"
|
||||
"reference": "64df81d3382d876f1c1d3d5481d89c93b61b8279"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/contracts/zipball/9532d673de305b0c0028c0ce60c8952b807d7bc3",
|
||||
"reference": "9532d673de305b0c0028c0ce60c8952b807d7bc3",
|
||||
"url": "https://api.github.com/repos/illuminate/contracts/zipball/64df81d3382d876f1c1d3d5481d89c93b61b8279",
|
||||
"reference": "64df81d3382d876f1c1d3d5481d89c93b61b8279",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -243,20 +244,20 @@
|
||||
],
|
||||
"description": "The Illuminate Contracts package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"time": "2018-10-03T14:04:39+00:00"
|
||||
"time": "2018-10-08T13:34:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/events",
|
||||
"version": "v5.7.8",
|
||||
"version": "v5.7.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/events.git",
|
||||
"reference": "4cf622acc05592f86d4a5c77ad1a544d38e58dee"
|
||||
"reference": "a8e5e3d601ad7f3571428176a578ddf03ce649d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/events/zipball/4cf622acc05592f86d4a5c77ad1a544d38e58dee",
|
||||
"reference": "4cf622acc05592f86d4a5c77ad1a544d38e58dee",
|
||||
"url": "https://api.github.com/repos/illuminate/events/zipball/a8e5e3d601ad7f3571428176a578ddf03ce649d8",
|
||||
"reference": "a8e5e3d601ad7f3571428176a578ddf03ce649d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -288,20 +289,20 @@
|
||||
],
|
||||
"description": "The Illuminate Events package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"time": "2018-07-26T15:27:42+00:00"
|
||||
"time": "2018-10-06T18:48:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/filesystem",
|
||||
"version": "v5.7.8",
|
||||
"version": "v5.7.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/filesystem.git",
|
||||
"reference": "a09fae4470494dc9867609221b46fe844f2f3b70"
|
||||
"reference": "cbb5650be36d7370f7ae5f039d2143952fa58f51"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/filesystem/zipball/a09fae4470494dc9867609221b46fe844f2f3b70",
|
||||
"reference": "a09fae4470494dc9867609221b46fe844f2f3b70",
|
||||
"url": "https://api.github.com/repos/illuminate/filesystem/zipball/cbb5650be36d7370f7ae5f039d2143952fa58f51",
|
||||
"reference": "cbb5650be36d7370f7ae5f039d2143952fa58f51",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -340,20 +341,20 @@
|
||||
],
|
||||
"description": "The Illuminate Filesystem package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"time": "2018-08-14T19:42:44+00:00"
|
||||
"time": "2018-10-24T12:49:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/support",
|
||||
"version": "v5.7.8",
|
||||
"version": "v5.7.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/support.git",
|
||||
"reference": "c7583db6703a36b7fa76254073046e0a920ed276"
|
||||
"reference": "45bfc0cd080c51946f61c04e324c2b4c6df58a9d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/support/zipball/c7583db6703a36b7fa76254073046e0a920ed276",
|
||||
"reference": "c7583db6703a36b7fa76254073046e0a920ed276",
|
||||
"url": "https://api.github.com/repos/illuminate/support/zipball/45bfc0cd080c51946f61c04e324c2b4c6df58a9d",
|
||||
"reference": "45bfc0cd080c51946f61c04e324c2b4c6df58a9d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -399,20 +400,20 @@
|
||||
],
|
||||
"description": "The Illuminate Support package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"time": "2018-10-04T13:27:30+00:00"
|
||||
"time": "2018-10-22T17:36:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/view",
|
||||
"version": "v5.7.8",
|
||||
"version": "v5.7.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/view.git",
|
||||
"reference": "86b8c60e502286135d9c91b0836a58445c4998b5"
|
||||
"reference": "97dbb6910aa5df5a7414877da89b7520f4260a58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/view/zipball/86b8c60e502286135d9c91b0836a58445c4998b5",
|
||||
"reference": "86b8c60e502286135d9c91b0836a58445c4998b5",
|
||||
"url": "https://api.github.com/repos/illuminate/view/zipball/97dbb6910aa5df5a7414877da89b7520f4260a58",
|
||||
"reference": "97dbb6910aa5df5a7414877da89b7520f4260a58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -447,7 +448,7 @@
|
||||
],
|
||||
"description": "The Illuminate View package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"time": "2018-10-02T13:51:18+00:00"
|
||||
"time": "2018-10-11T15:32:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "morris/lessql",
|
||||
@@ -554,16 +555,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "1.34.0",
|
||||
"version": "1.36.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||
"reference": "1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33"
|
||||
"reference": "63da8cdf89d7a5efe43aabc794365f6e7b7b8983"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33",
|
||||
"reference": "1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/63da8cdf89d7a5efe43aabc794365f6e7b7b8983",
|
||||
"reference": "63da8cdf89d7a5efe43aabc794365f6e7b7b8983",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -571,9 +572,12 @@
|
||||
"symfony/translation": "~2.6 || ~3.0 || ~4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "~2",
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7"
|
||||
},
|
||||
"suggest": {
|
||||
"friendsofphp/php-cs-fixer": "Needed for the `composer phpcs` command. Allow to automatically fix code style.",
|
||||
"phpstan/phpstan": "Needed for the `composer phpstan` command. Allow to detect potential errors."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
@@ -605,7 +609,7 @@
|
||||
"datetime",
|
||||
"time"
|
||||
],
|
||||
"time": "2018-09-20T19:36:25+00:00"
|
||||
"time": "2018-11-22T18:23:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
@@ -845,16 +849,16 @@
|
||||
},
|
||||
{
|
||||
"name": "psr/http-server-handler",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-server-handler.git",
|
||||
"reference": "439d92054dc06097f2406ec074a2627839955a02"
|
||||
"reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/439d92054dc06097f2406ec074a2627839955a02",
|
||||
"reference": "439d92054dc06097f2406ec074a2627839955a02",
|
||||
"url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/aff2f80e33b7f026ec96bb42f63242dc50ffcae7",
|
||||
"reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -894,7 +898,7 @@
|
||||
"response",
|
||||
"server"
|
||||
],
|
||||
"time": "2018-01-22T17:04:15+00:00"
|
||||
"time": "2018-10-30T16:46:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-server-middleware",
|
||||
@@ -951,16 +955,16 @@
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
|
||||
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
|
||||
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
|
||||
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -994,7 +998,7 @@
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2016-10-10T12:19:37+00:00"
|
||||
"time": "2018-11-20T15:27:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
@@ -1167,16 +1171,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "v4.1.6",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/debug.git",
|
||||
"reference": "e3f76ce6198f81994e019bb2b4e533e9de1b9b90"
|
||||
"reference": "19090917b848a799cbae4800abf740fe4eb71c1d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/e3f76ce6198f81994e019bb2b4e533e9de1b9b90",
|
||||
"reference": "e3f76ce6198f81994e019bb2b4e533e9de1b9b90",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/19090917b848a799cbae4800abf740fe4eb71c1d",
|
||||
"reference": "19090917b848a799cbae4800abf740fe4eb71c1d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1219,11 +1223,11 @@
|
||||
],
|
||||
"description": "Symfony Debug Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-10-02T16:36:10+00:00"
|
||||
"time": "2018-10-31T09:09:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v4.1.6",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
@@ -1272,16 +1276,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.9.0",
|
||||
"version": "v1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8"
|
||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8",
|
||||
"reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1327,20 +1331,20 @@
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2018-08-06T14:22:27+00:00"
|
||||
"time": "2018-09-21T13:07:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v4.1.6",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "9f0b61e339160a466ebcde167a6c5521c810e304"
|
||||
"reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/9f0b61e339160a466ebcde167a6c5521c810e304",
|
||||
"reference": "9f0b61e339160a466ebcde167a6c5521c810e304",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
|
||||
"reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1396,7 +1400,7 @@
|
||||
],
|
||||
"description": "Symfony Translation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-10-02T16:36:10+00:00"
|
||||
"time": "2018-10-28T18:38:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tuupola/callable-handler",
|
||||
|
@@ -38,7 +38,18 @@ DefaultUserSetting('auto_night_mode_time_range_from', "20:00"); // Format HH:mm
|
||||
DefaultUserSetting('auto_night_mode_time_range_to', "07:00"); // Format HH:mm
|
||||
DefaultUserSetting('auto_night_mode_time_range_goes_over_midnight', true); // If the time range above goes over midnight
|
||||
DefaultUserSetting('currently_inside_night_mode_range', false); // If we're currently inside of night mode time range (this is not user configurable, but stored as a user setting because it's evaluated client side to be able to use the client time instead of the maybe different server time)
|
||||
DefaultUserSetting('product_presets_location_id', -1); // Default location id for new products (-1 means no location is preset)
|
||||
DefaultUserSetting('product_presets_product_group_id', -1); // Default product group id for new products (-1 means no product group is preset)
|
||||
DefaultUserSetting('product_presets_qu_id', -1); // Default quantity unit id for new products (-1 means no quantity unit is preset)
|
||||
|
||||
# If the page should be automatically reloaded when there was
|
||||
# an external change
|
||||
DefaultUserSetting('auto_reload_on_db_change', true);
|
||||
|
||||
# Show a clock in the header next to the logo or not
|
||||
DefaultUserSetting('show_clock_in_header', false);
|
||||
|
||||
# Shopping list to stock workflow:
|
||||
# Automatically do the booking using the last price and the amount
|
||||
# of the shopping list item, if the product has "Default best before days" set
|
||||
DefaultUserSetting('shopping_list_to_stock_workflow_auto_submit_when_prefilled', false);
|
||||
|
@@ -42,9 +42,20 @@ class BaseController
|
||||
return $container->UrlManager->ConstructUrl($relativePath, $isResource);
|
||||
});
|
||||
|
||||
try {
|
||||
$embedded = false;
|
||||
if (isset($container->request->getQueryParams()['embedded']))
|
||||
{
|
||||
$embedded = true;
|
||||
}
|
||||
$container->view->set('embedded', $embedded);
|
||||
|
||||
try
|
||||
{
|
||||
$usersService = new UsersService();
|
||||
$container->view->set('userSettings', $usersService->GetUserSettings(GROCY_USER_ID));
|
||||
if (defined('GROCY_USER_ID'))
|
||||
{
|
||||
$container->view->set('userSettings', $usersService->GetUserSettings(GROCY_USER_ID));
|
||||
}
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
|
@@ -24,8 +24,8 @@ class BatteriesApiController extends BaseApiController
|
||||
|
||||
try
|
||||
{
|
||||
$this->BatteriesService->TrackChargeCycle($args['batteryId'], $trackedTime);
|
||||
return $this->VoidApiActionResponse($response);
|
||||
$chargeCycleId = $this->BatteriesService->TrackChargeCycle($args['batteryId'], $trackedTime);
|
||||
return $this->ApiResponse(array('charge_cycle_id' => $chargeCycleId));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
@@ -49,4 +49,17 @@ class BatteriesApiController extends BaseApiController
|
||||
{
|
||||
return $this->ApiResponse($this->BatteriesService->GetCurrent());
|
||||
}
|
||||
|
||||
public function UndoChargeCycle(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->ApiResponse($this->BatteriesService->UndoChargeCycle($args['chargeCycleId']));
|
||||
return $this->ApiResponse(array('success' => true));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -53,4 +53,12 @@ class BatteriesController extends BaseController
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function Journal(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteriesjournal', [
|
||||
'chargeCycles' => $this->Database->battery_charge_cycles()->orderBy('tracked_time', 'DESC'),
|
||||
'batteries' => $this->Database->batteries()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
81
controllers/CalendarController.php
Normal file
81
controllers/CalendarController.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use \Grocy\Services\StockService;
|
||||
use \Grocy\Services\TasksService;
|
||||
use \Grocy\Services\ChoresService;
|
||||
use \Grocy\Services\BatteriesService;
|
||||
|
||||
class CalendarController extends BaseController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->StockService = new StockService();
|
||||
$this->TasksService = new TasksService();
|
||||
$this->ChoresService = new ChoresService();
|
||||
$this->BatteriesService = new BatteriesService();
|
||||
}
|
||||
|
||||
protected $StockService;
|
||||
protected $TasksService;
|
||||
protected $ChoresService;
|
||||
protected $BatteriesService;
|
||||
|
||||
public function Overview(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
$products = $this->Database->products();
|
||||
$titlePrefix = $this->LocalizationService->Localize('Product expires') . ': ';
|
||||
$stockEvents = array();
|
||||
foreach($this->StockService->GetCurrentStock() as $currentStockEntry)
|
||||
{
|
||||
$stockEvents[] = array(
|
||||
'title' => $titlePrefix . FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name,
|
||||
'start' => $currentStockEntry->best_before_date
|
||||
);
|
||||
}
|
||||
|
||||
$titlePrefix = $this->LocalizationService->Localize('Task due') . ': ';
|
||||
$taskEvents = array();
|
||||
foreach($this->TasksService->GetCurrent() as $currentTaskEntry)
|
||||
{
|
||||
$taskEvents[] = array(
|
||||
'title' => $titlePrefix . $currentTaskEntry->name,
|
||||
'start' => $currentTaskEntry->due_date
|
||||
);
|
||||
}
|
||||
|
||||
$chores = $this->Database->chores();
|
||||
$titlePrefix = $this->LocalizationService->Localize('Chore due') . ': ';
|
||||
$choreEvents = array();
|
||||
foreach($this->ChoresService->GetCurrent() as $currentChoreEntry)
|
||||
{
|
||||
$choreEvents[] = array(
|
||||
'title' => $titlePrefix . FindObjectInArrayByPropertyValue($chores, 'id', $currentChoreEntry->chore_id)->name,
|
||||
'start' => $currentChoreEntry->next_estimated_execution_time
|
||||
);
|
||||
}
|
||||
|
||||
$batteries = $this->Database->batteries();
|
||||
$titlePrefix = $this->LocalizationService->Localize('Battery charge cycle due') . ': ';
|
||||
$batteryEvents = array();
|
||||
foreach($this->BatteriesService->GetCurrent() as $currentBatteryEntry)
|
||||
{
|
||||
$batteryEvents[] = array(
|
||||
'title' => $titlePrefix . FindObjectInArrayByPropertyValue($batteries, 'id', $currentBatteryEntry->battery_id)->name,
|
||||
'start' => $currentBatteryEntry->next_estimated_charge_time
|
||||
);
|
||||
}
|
||||
|
||||
$fullcalendarEventSources = array();
|
||||
$fullcalendarEventSources[] = $stockEvents;
|
||||
$fullcalendarEventSources[] = $taskEvents;
|
||||
$fullcalendarEventSources[] = $choreEvents;
|
||||
$fullcalendarEventSources[] = $batteryEvents;
|
||||
|
||||
return $this->AppContainer->view->render($response, 'calendar', [
|
||||
'fullcalendarEventSources' => $fullcalendarEventSources
|
||||
]);
|
||||
}
|
||||
}
|
@@ -30,8 +30,8 @@ class ChoresApiController extends BaseApiController
|
||||
|
||||
try
|
||||
{
|
||||
$this->ChoresService->TrackChore($args['choreId'], $trackedTime, $doneBy);
|
||||
return $this->VoidApiActionResponse($response);
|
||||
$choreExecutionId = $this->ChoresService->TrackChore($args['choreId'], $trackedTime, $doneBy);
|
||||
return $this->ApiResponse(array('chore_execution_id' => $choreExecutionId));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
@@ -55,4 +55,17 @@ class ChoresApiController extends BaseApiController
|
||||
{
|
||||
return $this->ApiResponse($this->ChoresService->GetCurrent());
|
||||
}
|
||||
|
||||
public function UndoChoreExecution(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->ApiResponse($this->ChoresService->UndoChoreExecution($args['executionId']));
|
||||
return $this->ApiResponse(array('success' => true));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,9 +38,9 @@ class ChoresController extends BaseController
|
||||
]);
|
||||
}
|
||||
|
||||
public function Analysis(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
public function Journal(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'choresanalysis', [
|
||||
return $this->AppContainer->view->render($response, 'choresjournal', [
|
||||
'choresLog' => $this->Database->chores_log()->orderBy('tracked_time', 'DESC'),
|
||||
'chores' => $this->Database->chores()->orderBy('name'),
|
||||
'users' => $this->Database->users()->orderBy('username')
|
||||
|
@@ -6,7 +6,7 @@ class GenericEntityApiController extends BaseApiController
|
||||
{
|
||||
public function GetObjects(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
if ($this->IsValidEntity($args['entity']))
|
||||
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||
{
|
||||
return $this->ApiResponse($this->Database->{$args['entity']}());
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class GenericEntityApiController extends BaseApiController
|
||||
|
||||
public function GetObject(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
if ($this->IsValidEntity($args['entity']))
|
||||
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||
{
|
||||
return $this->ApiResponse($this->Database->{$args['entity']}($args['objectId']));
|
||||
}
|
||||
@@ -77,4 +77,9 @@ class GenericEntityApiController extends BaseApiController
|
||||
{
|
||||
return in_array($entity, $this->OpenApiSpec->components->internalSchemas->ExposedEntity->enum);
|
||||
}
|
||||
|
||||
private function IsEntityWithPreventedListing($entity)
|
||||
{
|
||||
return in_array($entity, $this->OpenApiSpec->components->internalSchemas->ExposedEntitiesPreventListing->enum);
|
||||
}
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ class LoginController extends BaseController
|
||||
if ($user !== null && password_verify($inputPassword, $user->password))
|
||||
{
|
||||
$sessionKey = $this->SessionService->CreateSession($user->id, $stayLoggedInPermanently);
|
||||
setcookie($this->SessionCookieName, $sessionKey, time() + 31220640000); // Cookie expires in 999 years, but session validity is up to SessionService
|
||||
setcookie($this->SessionCookieName, $sessionKey, intval(time() + 31220640000)); // Cookie expires in 999 years, but session validity is up to SessionService
|
||||
|
||||
if (password_needs_rehash($user->password, PASSWORD_DEFAULT))
|
||||
{
|
||||
|
@@ -23,18 +23,21 @@ class RecipesController extends BaseController
|
||||
if (isset($request->getQueryParams()['recipe']))
|
||||
{
|
||||
$selectedRecipe = $this->Database->recipes($request->getQueryParams()['recipe']);
|
||||
$selectedRecipePositions = $this->Database->recipes_pos()->where('recipe_id', $request->getQueryParams()['recipe']);
|
||||
$selectedRecipePositions = $this->Database->recipes_pos()->where('recipe_id', $request->getQueryParams()['recipe'])->orderBy('ingredient_group');
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($recipes as $recipe)
|
||||
{
|
||||
$selectedRecipe = $recipe;
|
||||
$selectedRecipePositions = $this->Database->recipes_pos()->where('recipe_id', $recipe->id);
|
||||
$selectedRecipePositions = $this->Database->recipes_pos()->where('recipe_id', $recipe->id)->orderBy('ingredient_group');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$selectedRecipeSubRecipes = $this->Database->recipes()->where('id IN (SELECT includes_recipe_id FROM recipes_nestings_resolved WHERE recipe_id = :1 AND includes_recipe_id != :1)', $selectedRecipe->id)->orderBy('name')->fetchAll();
|
||||
$selectedRecipeSubRecipesPositions = $this->Database->recipes_pos()->where('recipe_id IN (SELECT includes_recipe_id FROM recipes_nestings_resolved WHERE recipe_id = :1 AND includes_recipe_id != :1)', $selectedRecipe->id)->orderBy('ingredient_group')->fetchAll();
|
||||
|
||||
return $this->AppContainer->view->render($response, 'recipes', [
|
||||
'recipes' => $recipes,
|
||||
'recipesFulfillment' => $this->RecipesService->GetRecipesFulfillment(),
|
||||
@@ -42,7 +45,9 @@ class RecipesController extends BaseController
|
||||
'selectedRecipe' => $selectedRecipe,
|
||||
'selectedRecipePositions' => $selectedRecipePositions,
|
||||
'products' => $this->Database->products(),
|
||||
'quantityunits' => $this->Database->quantity_units()
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'selectedRecipeSubRecipes' => $selectedRecipeSubRecipes,
|
||||
'selectedRecipeSubRecipesPositions' => $selectedRecipeSubRecipesPositions
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -66,7 +71,9 @@ class RecipesController extends BaseController
|
||||
'products' => $this->Database->products(),
|
||||
'quantityunits' => $this->Database->quantity_units(),
|
||||
'recipesFulfillment' => $this->RecipesService->GetRecipesFulfillment(),
|
||||
'recipesSumFulfillment' => $this->RecipesService->GetRecipesSumFulfillment()
|
||||
'recipesSumFulfillment' => $this->RecipesService->GetRecipesSumFulfillment(),
|
||||
'recipes' => $this->Database->recipes()->orderBy('name'),
|
||||
'recipeNestings' => $this->Database->recipes_nestings()->where('recipe_id', $recipeId)
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -60,8 +60,8 @@ class StockApiController extends BaseApiController
|
||||
|
||||
try
|
||||
{
|
||||
$this->StockService->AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType, date('Y-m-d'), $price);
|
||||
return $this->VoidApiActionResponse($response);
|
||||
$bookingId = $this->StockService->AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType, date('Y-m-d'), $price);
|
||||
return $this->ApiResponse(array('booking_id' => $bookingId));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
@@ -83,10 +83,16 @@ class StockApiController extends BaseApiController
|
||||
$transactionType = $request->getQueryParams()['transactiontype'];
|
||||
}
|
||||
|
||||
$specificStockEntryId = "default";
|
||||
if (isset($request->getQueryParams()['stock_entry_id']) && !empty($request->getQueryParams()['stock_entry_id']))
|
||||
{
|
||||
$specificStockEntryId = $request->getQueryParams()['stock_entry_id'];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$this->StockService->ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType);
|
||||
return $this->VoidApiActionResponse($response);
|
||||
$bookingId = $this->StockService->ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType, $specificStockEntryId);
|
||||
return $this->ApiResponse(array('booking_id' => $bookingId));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
@@ -104,8 +110,27 @@ class StockApiController extends BaseApiController
|
||||
|
||||
try
|
||||
{
|
||||
$this->StockService->InventoryProduct($args['productId'], $args['newAmount'], $bestBeforeDate);
|
||||
return $this->VoidApiActionResponse($response);
|
||||
$bookingId = $this->StockService->InventoryProduct($args['productId'], $args['newAmount'], $bestBeforeDate);
|
||||
return $this->ApiResponse(array('booking_id' => $bookingId));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function OpenProduct(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
$specificStockEntryId = "default";
|
||||
if (isset($request->getQueryParams()['stock_entry_id']) && !empty($request->getQueryParams()['stock_entry_id']))
|
||||
{
|
||||
$specificStockEntryId = $request->getQueryParams()['stock_entry_id'];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$bookingId = $this->StockService->OpenProduct($args['productId'], $args['amount'], $specificStockEntryId);
|
||||
return $this->ApiResponse(array('booking_id' => $bookingId));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
@@ -165,4 +190,22 @@ class StockApiController extends BaseApiController
|
||||
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function UndoBooking(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->ApiResponse($this->StockService->UndoBooking($args['bookingId']));
|
||||
return $this->ApiResponse(array('success' => true));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function ProductStockEntries(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->ApiResponse($this->StockService->GetProductStockEntries($args['productId']));
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,8 @@ class StockController extends BaseController
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'currentStock' => $this->StockService->GetCurrentStock(),
|
||||
'missingProducts' => $this->StockService->GetMissingProducts(),
|
||||
'nextXDays' => 5
|
||||
'nextXDays' => 5,
|
||||
'productGroups' => $this->Database->product_groups()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -69,6 +70,15 @@ class StockController extends BaseController
|
||||
]);
|
||||
}
|
||||
|
||||
public function StockSettings(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'stocksettings', [
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'productGroups' => $this->Database->product_groups()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
|
||||
public function LocationsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'locations', [
|
||||
@@ -182,4 +192,13 @@ class StockController extends BaseController
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function Journal(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'stockjournal', [
|
||||
'stockLog' => $this->Database->stock_log()->orderBy('row_created_timestamp', 'DESC'),
|
||||
'products' => $this->Database->products()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -1,30 +0,0 @@
|
||||
# Usage:
|
||||
# docker-compose build && docker-compose up
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
grocy-nginx:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile-grocy-nginx
|
||||
depends_on:
|
||||
- grocy
|
||||
ports:
|
||||
- '80:80'
|
||||
- '443:443'
|
||||
volumes_from:
|
||||
- grocy
|
||||
container_name: grocy-nginx
|
||||
|
||||
grocy:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile-grocy
|
||||
expose:
|
||||
- 9000
|
||||
environment:
|
||||
PHP_MEMORY_LIMIT: 512M
|
||||
MAX_UPLOAD: 50M
|
||||
PHP_MAX_FILE_UPLOAD: 200
|
||||
PHP_MAX_POST: 100M
|
||||
container_name: grocy
|
@@ -1,28 +0,0 @@
|
||||
index index.php index.html index.htm;
|
||||
|
||||
charset utf-8;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
|
||||
expires 365d;
|
||||
}
|
||||
|
||||
error_page 404 /404.html;
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass grocy:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name _;
|
||||
|
||||
root /www/public; # see: volumes_from
|
||||
|
||||
include /etc/nginx/common.conf;
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name _;
|
||||
|
||||
root /www/public; # see: volumes_from
|
||||
|
||||
ssl_certificate /etc/nginx/certificates/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/certificates/key.pem;
|
||||
|
||||
error_log /var/log/nginx/error.log;
|
||||
|
||||
# ssl_session_cache shared:SSL:1m;
|
||||
# ssl_session_timeout 5m;
|
||||
|
||||
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
# ssl_prefer_server_ciphers on;
|
||||
|
||||
include /etc/nginx/common.conf;
|
||||
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
user nobody;
|
||||
worker_processes 1;
|
||||
|
||||
pid /var/run/nginx/nginx.pid;
|
||||
|
||||
error_log /var/log/nginx/error.log;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
client_body_timeout 12;
|
||||
client_header_timeout 12;
|
||||
keepalive_timeout 15;
|
||||
send_timeout 10;
|
||||
|
||||
client_body_buffer_size 10K;
|
||||
client_header_buffer_size 1k;
|
||||
client_max_body_size 50M;
|
||||
large_client_header_buffers 2 1k;
|
||||
|
||||
gzip on;
|
||||
gzip_comp_level 2;
|
||||
gzip_min_length 1000;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_types text/plain application/x-javascript text/xml text/css application/xml;
|
||||
|
||||
access_log on;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
@@ -968,6 +968,15 @@
|
||||
"schema": {
|
||||
"$ref": "#/components/internalSchemas/StockTransactionType"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "stock_entry_id",
|
||||
"required": false,
|
||||
"description": "A specific stock entry id to consume, if used, the amount has to be 1",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -994,6 +1003,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/stock/open-product/{productId}/{amount}": {
|
||||
"get": {
|
||||
"description": "Marks the the given amount of the given product as opened",
|
||||
"tags": [
|
||||
"Stock"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "productId",
|
||||
"required": true,
|
||||
"description": "A valid product id",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "path",
|
||||
"name": "amount",
|
||||
"required": false,
|
||||
"description": "The amount to remove",
|
||||
"schema": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "stock_entry_id",
|
||||
"required": false,
|
||||
"description": "A specific stock entry id to open, if used, the amount has to be 1",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A VoidApiActionResponse object",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/VoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "A VoidApiActionResponse object (possible errors are: Not existing product)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorExampleVoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/stock/inventory-product/{productId}/{newAmount}": {
|
||||
"get": {
|
||||
"description": "Inventories the the given product (adds/removes based on the given new current amount)",
|
||||
@@ -1139,6 +1208,50 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/stock/get-product-stock-entries/{productId}": {
|
||||
"get": {
|
||||
"description": "Returns all stock entries of the given product in order of next use (first expiring first, then first in first out)",
|
||||
"tags": [
|
||||
"Stock"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "productId",
|
||||
"required": true,
|
||||
"description": "A valid product id",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "An array of StockEntry objects",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/StockEntry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "A VoidApiActionResponse object (possible errors are: Not existing product)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorExampleVoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/stock/get-current-stock": {
|
||||
"get": {
|
||||
"description": "Returns all products which are currently in stock incl. the next expiring date per product",
|
||||
@@ -1288,6 +1401,47 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/stock/undo-booking/{bookingId}": {
|
||||
"get": {
|
||||
"description": "Undoes a booking",
|
||||
"tags": [
|
||||
"Stock"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "bookingId",
|
||||
"required": true,
|
||||
"description": "A valid stock booking id",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A VoidApiActionResponse object",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/VoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "A VoidApiActionResponse object (possible errors are: Not existing booking)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorExampleVoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/recipes/add-not-fulfilled-products-to-shopping-list/{recipeId}": {
|
||||
"get": {
|
||||
"description": "Adds all missing products for the given recipe to the shopping list",
|
||||
@@ -1473,6 +1627,47 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/chores/undo-chore-execution/{executionId}": {
|
||||
"get": {
|
||||
"description": "Undoes a chore execution",
|
||||
"tags": [
|
||||
"Chores"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "executionId",
|
||||
"required": true,
|
||||
"description": "A valid chore execution id",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A VoidApiActionResponse object",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/VoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "A VoidApiActionResponse object (possible errors are: Not existing booking)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorExampleVoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/batteries/track-charge-cycle/{batteryId}": {
|
||||
"get": {
|
||||
"description": "Tracks a charge cycle of the given battery",
|
||||
@@ -1588,6 +1783,47 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/batteries/undo-charge-cycle/{chargeCycleId}": {
|
||||
"get": {
|
||||
"description": "Undoes a chore execution",
|
||||
"tags": [
|
||||
"Batteries"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "chargeCycleId",
|
||||
"required": true,
|
||||
"description": "A valid charge cycle id",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A VoidApiActionResponse object",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/VoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "A VoidApiActionResponse object (possible errors are: Not existing booking)",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorExampleVoidApiActionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/get-current": {
|
||||
"get": {
|
||||
"description": "Returns all tasks which are not done yet",
|
||||
@@ -1675,10 +1911,18 @@
|
||||
"shopping_list",
|
||||
"recipes",
|
||||
"recipes_pos",
|
||||
"recipes_nestings",
|
||||
"tasks",
|
||||
"task_categories",
|
||||
"product_groups",
|
||||
"equipment"
|
||||
"equipment",
|
||||
"api_keys"
|
||||
]
|
||||
},
|
||||
"ExposedEntitiesPreventListing": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"api_keys"
|
||||
]
|
||||
},
|
||||
"StockTransactionType": {
|
||||
@@ -1831,6 +2075,9 @@
|
||||
"stock_amount": {
|
||||
"type": "integer"
|
||||
},
|
||||
"stock_amount_opened": {
|
||||
"type": "integer"
|
||||
},
|
||||
"next_best_before_date": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
|
6
info.php
6
info.php
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
|
||||
// Show all information, defaults to INFO_ALL
|
||||
phpinfo();
|
||||
|
||||
?>
|
6
localization/de/chore_types.php
Normal file
6
localization/de/chore_types.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'manually' => 'Manuell',
|
||||
'dynamic-regular' => 'Dynamisch regelmäßig'
|
||||
);
|
10
localization/de/component_translations.php
Normal file
10
localization/de/component_translations.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'timeago_locale' => 'de',
|
||||
'timeago_nan' => 'vor NaN Jahren',
|
||||
'moment_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"}}}',
|
||||
'summernote_locale' => 'de-DE',
|
||||
'fullcalendar_locale' => 'de'
|
||||
);
|
87
localization/de/demo_data.php
Normal file
87
localization/de/demo_data.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Cookies' => 'Cookies',
|
||||
'Chocolate' => 'Schokolade',
|
||||
'Pantry' => 'Vorratskammer',
|
||||
'Candy cupboard' => 'Süßigkeitenschrank',
|
||||
'Tinned food cupboard' => 'Konservenschrank',
|
||||
'Fridge' => 'Kühlschrank',
|
||||
'Piece' => 'Stück',
|
||||
'Pieces' => 'Stücke',
|
||||
'Pack' => 'Packung',
|
||||
'Packs' => 'Packungen',
|
||||
'Glass' => 'Glas',
|
||||
'Glasses' => 'Gläser',
|
||||
'Tin' => 'Dose',
|
||||
'Tins' => 'Dosen',
|
||||
'Can' => 'Becher',
|
||||
'Cans' => 'Becher',
|
||||
'Bunch' => 'Bund',
|
||||
'Bunches' => 'Bunde',
|
||||
'Gummy bears' => 'Gummibärchen',
|
||||
'Crisps' => 'Chips',
|
||||
'Eggs' => 'Eier',
|
||||
'Noodles' => 'Nudeln',
|
||||
'Pickles' => 'Essiggurken',
|
||||
'Gulash soup' => 'Gulaschsuppe',
|
||||
'Yogurt' => 'Joghurt',
|
||||
'Cheese' => 'Käse',
|
||||
'Cold cuts' => 'Aufschnitt',
|
||||
'Paprika' => 'Paprika',
|
||||
'Cucumber' => 'Gurke',
|
||||
'Radish' => 'Radieschen',
|
||||
'Tomato' => 'Tomaten',
|
||||
'Changed towels in the bathroom' => 'Handtücher im Bad gewechselt',
|
||||
'Cleaned the kitchen floor' => 'Küchenboden gewischt',
|
||||
'Warranty ends' => 'Garantie endet',
|
||||
'TV remote control' => 'TV Fernbedienung',
|
||||
'Alarm clock' => 'Wecker',
|
||||
'Heat remote control' => 'Fernbedienung Heizung',
|
||||
'Lawn mowed in the garden' => 'Rasen im Garten gemäht',
|
||||
'Some good snacks' => 'Paar gute Snacks',
|
||||
'Pizza dough' => 'Pizzateig',
|
||||
'Sieved tomatoes' => 'Passierte Tomaten',
|
||||
'Salami' => 'Salami',
|
||||
'Toast' => 'Toast',
|
||||
'Minced meat' => 'Hackfleisch',
|
||||
'Pizza' => 'Pizza',
|
||||
'Spaghetti bolognese' => 'Spaghetti Bolognese',
|
||||
'Sandwiches' => 'Belegte Toasts',
|
||||
'English' => 'Englisch',
|
||||
'German' => 'Deutsch',
|
||||
'Italian' => 'Italienisch',
|
||||
'Demo in different language' => 'Demo in anderer Sprache',
|
||||
'This is the note content of the recipe ingredient' => 'Dies ist der Inhalt der Notiz der Zutat',
|
||||
'Demo User' => 'Demo Benutzer',
|
||||
'Gram' => 'Gramm',
|
||||
'Grams' => 'Gramm',
|
||||
'Flour' => 'Mehl',
|
||||
'Pancakes' => 'Pfannkuchen',
|
||||
'Sugar' => 'Zucker',
|
||||
'Home' => 'Zuhause',
|
||||
'Life' => 'Leben',
|
||||
'Projects' => 'Projekte',
|
||||
'Repair the garage door' => 'Garagentor reparieren',
|
||||
'Fork and improve grocy' => 'grocy forken und verbessern',
|
||||
'Find a solution for what to do when I forget the door keys' => 'Eine Lösung für "Haustürschlüssel vergessen" finden',
|
||||
'Sweets' => 'Süßigkeiten',
|
||||
'Bakery products' => 'Bäckerei Produkte',
|
||||
'Tinned food' => 'Konservern',
|
||||
'Butchery products' => 'Metzgerei',
|
||||
'Vegetables/Fruits' => 'Obst/Gemüse',
|
||||
'Refrigerated products' => 'Kühlregal',
|
||||
'Coffee machine' => 'Kaffeemaschine',
|
||||
'Dishwasher' => 'Spülmaschine',
|
||||
'Liter' => 'Liter',
|
||||
'Liters' => 'Liter',
|
||||
'Bottle' => 'Flasche',
|
||||
'Bottles' => 'Flaschen',
|
||||
'Milk' => 'Milch',
|
||||
'Chocolate sauce' => 'Schokoladensoße',
|
||||
'Milliliters' => 'Milliliter',
|
||||
'Milliliter' => 'Milliliter',
|
||||
'Bottom' => 'Boden',
|
||||
'Topping' => 'Belag',
|
||||
'French' => 'Französisch'
|
||||
);
|
8
localization/de/stock_transaction_types.php
Normal file
8
localization/de/stock_transaction_types.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'purchase' => 'Einkauf',
|
||||
'consume' => 'Verbrauch',
|
||||
'inventory-correction' => 'Inventur-Korrektur',
|
||||
'product-opened' => 'Produkt geöffnet'
|
||||
);
|
@@ -101,12 +101,12 @@ return array(
|
||||
'Are you sure to delete product "#1"?' => 'Produkt "#1" wirklich löschen?',
|
||||
'Are you sure to delete location "#1"?' => 'Standort "#1" wirklich löschen?',
|
||||
'Manage API keys' => 'API-Keys verwalten',
|
||||
'REST API & data model documentation' => 'REST-API & Datenmodell Dokumentation',
|
||||
'API keys' => 'API-Keys',
|
||||
'Create new API key' => 'Neuen API-Key erstellen',
|
||||
'API key' => 'API-Key',
|
||||
'Expires' => 'Läuft ab',
|
||||
'Created' => 'Erstellt',
|
||||
'REST API & data model documentation' => 'REST-API & Datenmodell Dokumentation',
|
||||
'API keys' => 'API-Keys',
|
||||
'Create new API key' => 'Neuen API-Key erstellen',
|
||||
'API key' => 'API-Key',
|
||||
'Expires' => 'Läuft ab',
|
||||
'Created' => 'Erstellt',
|
||||
'This product is not in stock' => 'Dieses Produkt ist nicht vorrätig',
|
||||
'This means #1 will be added to stock' => 'Das bedeutet #1 wird dem Bestand hinzugefügt',
|
||||
'This means #1 will be removed from stock' => 'Das bedeutet #1 wird aus dem Bestand entfernt',
|
||||
@@ -184,7 +184,7 @@ return array(
|
||||
'Last done by' => 'Zuletzt ausgeführt von',
|
||||
'Unknown' => 'Unbekannt',
|
||||
'Filter by chore' => 'Nach Hausarbeit filtern',
|
||||
'Chores analysis' => 'Hausarbeiten Analyse',
|
||||
'Chores journal' => 'Hausarbeitenjournal',
|
||||
'0 means suggestions for the next charge cycle are disabled' => '0 bedeutet dass Vorschläge für den nächsten Ladezyklus deaktiviert sind',
|
||||
'Charge cycle interval (days)' => 'Ladezyklusintervall (Tage)',
|
||||
'Last price' => 'Letzter Preis',
|
||||
@@ -277,89 +277,54 @@ return array(
|
||||
'Current instruction manual' => 'Aktuelle Bedienungsanleitung',
|
||||
'No instruction manual available' => 'Keine Bedienungsanleitung vorhanden',
|
||||
'The current instruction manual will be deleted when you save the equipment' => 'Die aktuelle Bedienungsanleitung wird beim Speichern des Geräts gelöscht',
|
||||
|
||||
//Constants
|
||||
'manually' => 'Manuell',
|
||||
'dynamic-regular' => 'Dynamisch regelmäßig',
|
||||
|
||||
//Technical component translations
|
||||
'timeago_locale' => 'de',
|
||||
'timeago_nan' => 'vor NaN Jahren',
|
||||
'moment_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"}}}',
|
||||
'summernote_locale' => 'de-DE',
|
||||
|
||||
//Demo data
|
||||
'Cookies' => 'Cookies',
|
||||
'Chocolate' => 'Schokolade',
|
||||
'Pantry' => 'Vorratskammer',
|
||||
'Candy cupboard' => 'Süßigkeitenschrank',
|
||||
'Tinned food cupboard' => 'Konservenschrank',
|
||||
'Fridge' => 'Kühlschrank',
|
||||
'Piece' => 'Stück',
|
||||
'Pieces' => 'Stücke',
|
||||
'Pack' => 'Packung',
|
||||
'Packs' => 'Packungen',
|
||||
'Glass' => 'Glas',
|
||||
'Glasses' => 'Gläser',
|
||||
'Tin' => 'Dose',
|
||||
'Tins' => 'Dosen',
|
||||
'Can' => 'Becher',
|
||||
'Cans' => 'Becher',
|
||||
'Bunch' => 'Bund',
|
||||
'Bunches' => 'Bunde',
|
||||
'Gummy bears' => 'Gummibärchen',
|
||||
'Crisps' => 'Chips',
|
||||
'Eggs' => 'Eier',
|
||||
'Noodles' => 'Nudeln',
|
||||
'Pickles' => 'Essiggurken',
|
||||
'Gulash soup' => 'Gulaschsuppe',
|
||||
'Yogurt' => 'Joghurt',
|
||||
'Cheese' => 'Käse',
|
||||
'Cold cuts' => 'Aufschnitt',
|
||||
'Paprika' => 'Paprika',
|
||||
'Cucumber' => 'Gurke',
|
||||
'Radish' => 'Radieschen',
|
||||
'Tomato' => 'Tomaten',
|
||||
'Changed towels in the bathroom' => 'Handtücher im Bad gewechselt',
|
||||
'Cleaned the kitchen floor' => 'Küchenboden gewischt',
|
||||
'Warranty ends' => 'Garantie endet',
|
||||
'TV remote control' => 'TV Fernbedienung',
|
||||
'Alarm clock' => 'Wecker',
|
||||
'Heat remote control' => 'Fernbedienung Heizung',
|
||||
'Lawn mowed in the garden' => 'Rasen im Garten gemäht',
|
||||
'Some good snacks' => 'Paar gute Snacks',
|
||||
'Pizza dough' => 'Pizzateig',
|
||||
'Sieved tomatoes' => 'Passierte Tomaten',
|
||||
'Salami' => 'Salami',
|
||||
'Toast' => 'Toast',
|
||||
'Minced meat' => 'Hackfleisch',
|
||||
'Pizza' => 'Pizza',
|
||||
'Spaghetti bolognese' => 'Spaghetti Bolognese',
|
||||
'Sandwiches' => 'Belegte Toasts',
|
||||
'English' => 'Englisch',
|
||||
'German' => 'Deutsch',
|
||||
'Italian' => 'Italienisch',
|
||||
'Demo in different language' => 'Demo in anderer Sprache',
|
||||
'This is the note content of the recipe ingredient' => 'Dies ist der Inhalt der Notiz der Zutat',
|
||||
'Demo User' => 'Demo Benutzer',
|
||||
'Gram' => 'Gramm',
|
||||
'Grams' => 'Gramm',
|
||||
'Flour' => 'Mehl',
|
||||
'Pancakes' => 'Pfannkuchen',
|
||||
'Sugar' => 'Zucker',
|
||||
'Home' => 'Zuhause',
|
||||
'Life' => 'Leben',
|
||||
'Projects' => 'Projekte',
|
||||
'Repair the garage door' => 'Garagentor reparieren',
|
||||
'Fork and improve grocy' => 'grocy forken und verbessern',
|
||||
'Find a solution for what to do when I forget the door keys' => 'Eine Lösung für "Haustürschlüssel vergessen" finden',
|
||||
'Sweets' => 'Süßigkeiten',
|
||||
'Bakery products' => 'Bäckerei Produkte',
|
||||
'Tinned food' => 'Konservern',
|
||||
'Butchery products' => 'Metzgerei',
|
||||
'Vegetables/Fruits' => 'Obst/Gemüse',
|
||||
'Refrigerated products' => 'Kühlregal',
|
||||
'Coffee machine' => 'Kaffeemaschine',
|
||||
'Dishwasher' => 'Spülmaschine'
|
||||
'No picture available' => 'Kein Bild vorhanden',
|
||||
'Filter by product group' => 'Nach Produktgruppe filtern',
|
||||
'Presets for new products' => 'Vorgaben für neue Produkte',
|
||||
'Included recipes' => 'Enthaltene Rezepte',
|
||||
'A recipe is required' => 'Ein Rezept ist erforderlich',
|
||||
'Add included recipe' => 'Enthaltenes Rezept hinzufügen',
|
||||
'Edit included recipe' => 'Enthaltenes Rezept bearbeiten',
|
||||
'Group' => 'Gruppe',
|
||||
'This will be used as a headline to group ingredients together' => 'Dies wird als Überschrift verwendet, um Zutaten zusammenzufassen',
|
||||
'Journal' => 'Journal',
|
||||
'Stock journal' => 'Bestandsjournal',
|
||||
'Filter by product' => 'Nach Produkt filtern',
|
||||
'Booking time' => 'Buchungszeit',
|
||||
'Booking type' => 'Buchungsart',
|
||||
'Undo booking' => 'Buchung rückgängig machen',
|
||||
'Undone on' => 'Rückgängig gemacht am',
|
||||
'Batteries journal' => 'Batteriejournal',
|
||||
'Filter by battery' => 'Nach Batterie filtern',
|
||||
'Undo charge cycle' => 'Ladezyklus rückgängig machen',
|
||||
'Undo chore execution' => 'Ausführung rückgängig machen',
|
||||
'Chore execution successfully undone' => 'Ausführung erfolgreich rückgängig gemacht',
|
||||
'Undo' => 'Rückgängig machen',
|
||||
'Booking successfully undone' => 'Buchung erfolgreich rückgängig gemacht',
|
||||
'Charge cycle successfully undone' => 'Ladezyklus erfolgreich rückgängig gemacht',
|
||||
'This cannot be negative and must be an integral number' => 'Diese darf nicht negativ und muss eine ganze Zahl sein',
|
||||
'Disable stock fulfillment checking for this ingredient' => 'Bestandsprüfung für diese Zutat deaktivieren',
|
||||
'Add all list items to stock' => 'Alle Einträge zum Bestand hinzufügen',
|
||||
'Add #3 #1 of #2 to stock' => 'Füge #3 #1 of #2 dem Bestand hinzu',
|
||||
'Adding shopping list item #1 of #2' => 'Bearbeite Einkausfzettel-Eintrag #1 von #2',
|
||||
'Use a specific stock item' => 'Einen bestimmten Bestandseintrag verwenden',
|
||||
'The first item in this list would be picked by the default rule which is "First expiring first, then first in first out"' => 'Der erste Eintrag in dieser Liste würde von der Standardregel "Zuerst ablaufende zuerst, dann First In - First Out" ausgewählt werden',
|
||||
'Mark #3 #1 of #2 as open' => '#3 #1 von #2 als geöffnet markieren',
|
||||
'When a product was marked as opened, the best before date will be replaced by today + this amount of days (a value of 0 disables this)' => 'Wenn ein Produkt als geöffnet markiert wurde, wird das Mindesthaltbarkeitsdatum durch heute + diese Anzahl von Tagen ersetzt (ein Wert von 0 deaktiviert dies)',
|
||||
'Default best before days after opened' => 'Standard Haltbarkeit in Tagen nach dem Öffnen',
|
||||
'Marked #1 #2 of #3 as opened' => '#1 #2 von #3 als geöffnet markiert',
|
||||
'Mark as opened' => 'Als geöffnet markieren',
|
||||
'Expires on #1; Bought on #2' => 'Läuft ab am #1; Gekauft am #2',
|
||||
'Not opened' => 'Nicht geöffnet',
|
||||
'Opened' => 'Geöffnet',
|
||||
'Mark #3 #1 of #2 as open' => '#3 #1 von #2 als geöffnet markieren',
|
||||
'#1 opened' => '#1 geöffnet',
|
||||
'Product expires' => 'Produkt läuft ab',
|
||||
'Task due' => 'Aufgabe fällig',
|
||||
'Chore due' => 'Hausarbeit fällig',
|
||||
'Battery charge cycle due' => 'Battery-Ladezyklus fällig',
|
||||
'Show clock in header' => 'Uhr in der Kopfzeile anzeigen',
|
||||
'Stock settings' => 'Bestandseinstellungen',
|
||||
'Shopping list to stock workflow' => 'Einkaufsliste -> Bestand Workflow',
|
||||
'Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default best before days" set' => 'Buchung automatisch ausführen, wenn das Produkt "Standard Haltbarkeit in Tagen" hinterlegt hat (als Preis wird der letzte Preis verwendet)',
|
||||
'Skip' => 'Überspringen'
|
||||
);
|
6
localization/en/chore_types.php
Normal file
6
localization/en/chore_types.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'manually' => 'Manually',
|
||||
'dynamic-regular' => 'Dynamic regular'
|
||||
);
|
@@ -1,14 +1,10 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
//Constants
|
||||
'manually' => 'Manually',
|
||||
'dynamic-regular' => 'Dynamic regular',
|
||||
|
||||
//Technical component translations
|
||||
'timeago_locale' => 'en',
|
||||
'timeago_nan' => 'NaN years ago',
|
||||
'moment_locale' => '',
|
||||
'moment_locale' => 'x',
|
||||
'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"}}',
|
||||
'summernote_locale' => ''
|
||||
'summernote_locale' => 'x',
|
||||
'fullcalendar_locale' => 'x'
|
||||
);
|
87
localization/en/demo_data.php
Normal file
87
localization/en/demo_data.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Cookies' => 'Cookies',
|
||||
'Chocolate' => 'Chocolate',
|
||||
'Pantry' => 'Pantry',
|
||||
'Candy cupboard' => 'Candy cupboard',
|
||||
'Tinned food cupboard' => 'Tinned food cupboard',
|
||||
'Fridge' => 'Fridge',
|
||||
'Piece' => 'Piece',
|
||||
'Pieces' => 'Pieces',
|
||||
'Pack' => 'Pack',
|
||||
'Packs' => 'Packs',
|
||||
'Glass' => 'Glass',
|
||||
'Glasses' => 'Glasses',
|
||||
'Tin' => 'Tin',
|
||||
'Tins' => 'Tins',
|
||||
'Can' => 'Can',
|
||||
'Cans' => 'Cans',
|
||||
'Bunch' => 'Bunch',
|
||||
'Bunches' => 'Bunches',
|
||||
'Gummy bears' => 'Gummy bears',
|
||||
'Crisps' => 'Crisps',
|
||||
'Eggs' => 'Eggs',
|
||||
'Noodles' => 'Noodles',
|
||||
'Pickles' => 'Pickles',
|
||||
'Gulash soup' => 'Gulash soup',
|
||||
'Yogurt' => 'Yogurt',
|
||||
'Cheese' => 'Cheese',
|
||||
'Cold cuts' => 'Cold cuts',
|
||||
'Paprika' => 'Paprika',
|
||||
'Cucumber' => 'Cucumber',
|
||||
'Radish' => 'Radish',
|
||||
'Tomato' => 'Tomato',
|
||||
'Changed towels in the bathroom' => 'Changed towels in the bathroom',
|
||||
'Cleaned the kitchen floor' => 'Cleaned the kitchen floor',
|
||||
'Warranty ends' => 'Warranty ends',
|
||||
'TV remote control' => 'TV remote control',
|
||||
'Alarm clock' => 'Alarm clock',
|
||||
'Heat remote control' => 'Heat remote control',
|
||||
'Lawn mowed in the garden' => 'Lawn mowed in the garden',
|
||||
'Some good snacks' => 'Some good snacks',
|
||||
'Pizza dough' => 'Pizza dough',
|
||||
'Sieved tomatoes' => 'Sieved tomatoes',
|
||||
'Salami' => 'Salami',
|
||||
'Toast' => 'Toast',
|
||||
'Minced meat' => 'Minced meat',
|
||||
'Pizza' => 'Pizza',
|
||||
'Spaghetti bolognese' => 'Spaghetti bolognese',
|
||||
'Sandwiches' => 'Sandwiches',
|
||||
'English' => 'English',
|
||||
'German' => 'German',
|
||||
'Italian' => 'Italian',
|
||||
'Demo in different language' => 'Demo in different language',
|
||||
'This is the note content of the recipe ingredient' => 'This is the note content of the recipe ingredient',
|
||||
'Demo User' => 'Demo User',
|
||||
'Gram' => 'Gram',
|
||||
'Grams' => 'Grams',
|
||||
'Flour' => 'Flour',
|
||||
'Pancakes' => 'Pancakes',
|
||||
'Sugar' => 'Sugar',
|
||||
'Home' => 'Home',
|
||||
'Life' => 'Life',
|
||||
'Projects' => 'Projects',
|
||||
'Repair the garage door' => 'Repair the garage door',
|
||||
'Fork and improve grocy' => 'Fork and improve grocy',
|
||||
'Find a solution for what to do when I forget the door keys' => 'Find a solution for what to do when I forget the door keys',
|
||||
'Sweets' => 'Sweets',
|
||||
'Bakery products' => 'Bakery products',
|
||||
'Tinned food' => 'Tinned food',
|
||||
'Butchery products' => 'Butchery products',
|
||||
'Vegetables/Fruits' => 'Vegetables/Fruits',
|
||||
'Refrigerated products' => 'Refrigerated products',
|
||||
'Coffee machine' => 'Coffee machine',
|
||||
'Dishwasher' => 'Dishwasher',
|
||||
'Liter' => 'Liter',
|
||||
'Liters' => 'Liters',
|
||||
'Bottle' => 'Bottle',
|
||||
'Bottles' => 'Bottles',
|
||||
'Milk' => 'Milk',
|
||||
'Chocolate sauce' => 'Chocolate sauce',
|
||||
'Milliliters' => 'Milliliters',
|
||||
'Milliliter' => 'Milliliter',
|
||||
'Bottom' => 'Bottom',
|
||||
'Topping' => 'Topping',
|
||||
'French' => 'French'
|
||||
);
|
8
localization/en/stock_transaction_types.php
Normal file
8
localization/en/stock_transaction_types.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'purchase' => 'Purchase',
|
||||
'consume' => 'Consume',
|
||||
'inventory-correction' => 'Inventory correction',
|
||||
'product-opened' => 'Product opened'
|
||||
);
|
330
localization/en/strings.php
Normal file
330
localization/en/strings.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Stock overview' => 'Stock overview',
|
||||
'#1 products expiring within the next #2 days' => '#1 products expiring within the next #2 days',
|
||||
'#1 products are already expired' => '#1 products are already expired',
|
||||
'#1 products are below defined min. stock amount' => '#1 products are below defined min. stock amount',
|
||||
'Product' => 'Product',
|
||||
'Amount' => 'Amount',
|
||||
'Next best before date' => 'Next best before date',
|
||||
'Logout' => 'Logout',
|
||||
'Chores overview' => 'Chores overview',
|
||||
'Batteries overview' => 'Batteries overview',
|
||||
'Purchase' => 'Purchase',
|
||||
'Consume' => 'Consume',
|
||||
'Inventory' => 'Inventory',
|
||||
'Shopping list' => 'Shopping list',
|
||||
'Chore tracking' => 'Chore tracking',
|
||||
'Battery tracking' => 'Battery tracking',
|
||||
'Products' => 'Products',
|
||||
'Locations' => 'Locations',
|
||||
'Quantity units' => 'Quantity units',
|
||||
'Chores' => 'Chores',
|
||||
'Batteries' => 'Batteries',
|
||||
'Chore' => 'Chore',
|
||||
'Next estimated tracking' => 'Next estimated tracking',
|
||||
'Last tracked' => 'Last tracked',
|
||||
'Battery' => 'Battery',
|
||||
'Last charged' => 'Last charged',
|
||||
'Next planned charge cycle' => 'Next planned charge cycle',
|
||||
'Best before' => 'Best before',
|
||||
'OK' => 'OK',
|
||||
'Product overview' => 'Product overview',
|
||||
'Stock quantity unit' => 'Stock quantity unit',
|
||||
'Stock amount' => 'Stock amount',
|
||||
'Last purchased' => 'Last purchased',
|
||||
'Last used' => 'Last used',
|
||||
'Spoiled' => 'Spoiled',
|
||||
'Barcode lookup is disabled' => 'Barcode lookup is disabled',
|
||||
'will be added to the list of barcodes for the selected product on submit' => 'will be added to the list of barcodes for the selected product on submit',
|
||||
'New amount' => 'New amount',
|
||||
'Note' => 'Note',
|
||||
'Tracked time' => 'Tracked time',
|
||||
'Chore overview' => 'Chore overview',
|
||||
'Tracked count' => 'Tracked count',
|
||||
'Battery overview' => 'Battery overview',
|
||||
'Charge cycles count' => 'Charge cycles count',
|
||||
'Create shopping list item' => 'Create shopping list item',
|
||||
'Edit shopping list item' => 'Edit shopping list item',
|
||||
'#1 units were automatically added and will apply in addition to the amount entered here' => '#1 units were automatically added and will apply in addition to the amount entered here',
|
||||
'Save' => 'Save',
|
||||
'Add' => 'Add',
|
||||
'Name' => 'Name',
|
||||
'Location' => 'Location',
|
||||
'Min. stock amount' => 'Min. stock amount',
|
||||
'QU purchase' => 'QU purchase',
|
||||
'QU stock' => 'QU stock',
|
||||
'QU factor' => 'QU factor',
|
||||
'Description' => 'Description',
|
||||
'Create product' => 'Create product',
|
||||
'Barcode(s)' => 'Barcode(s)',
|
||||
'Minimum stock amount' => 'Minimum stock amount',
|
||||
'Default best before days' => 'Default best before days',
|
||||
'Quantity unit purchase' => 'Quantity unit purchase',
|
||||
'Quantity unit stock' => 'Quantity unit stock',
|
||||
'Factor purchase to stock quantity unit' => 'Factor purchase to stock quantity unit',
|
||||
'Create location' => 'Create location',
|
||||
'Create quantity unit' => 'Create quantity unit',
|
||||
'Period type' => 'Period type',
|
||||
'Period days' => 'Period days',
|
||||
'Create chore' => 'Create chore',
|
||||
'Used in' => 'Used in',
|
||||
'Create battery' => 'Create battery',
|
||||
'Edit battery' => 'Edit battery',
|
||||
'Edit chore' => 'Edit chore',
|
||||
'Edit quantity unit' => 'Edit quantity unit',
|
||||
'Edit product' => 'Edit product',
|
||||
'Edit location' => 'Edit location',
|
||||
'Record data' => 'Record data',
|
||||
'Manage master data' => 'Manage master data',
|
||||
'This will apply to added products' => 'This will apply to added products',
|
||||
'never' => 'never',
|
||||
'Add products that are below defined min. stock amount' => 'Add products that are below defined min. stock amount',
|
||||
'For purchases this amount of days will be added to today for the best before date suggestion' => 'For purchases this amount of days will be added to today for the best before date suggestion',
|
||||
'This means 1 #1 purchased will be converted into #2 #3 in stock' => 'This means 1 #1 purchased will be converted into #2 #3 in stock',
|
||||
'Login' => 'Login',
|
||||
'Username' => 'Username',
|
||||
'Password' => 'Password',
|
||||
'Invalid credentials, please try again' => 'Invalid credentials, please try again',
|
||||
'Are you sure to delete battery "#1"?' => 'Are you sure to delete battery "#1"?',
|
||||
'Yes' => 'Yes',
|
||||
'No' => 'No',
|
||||
'Are you sure to delete chore "#1"?' => 'Are you sure to delete chore "#1"?',
|
||||
'"#1" could not be resolved to a product, how do you want to proceed?' => '"#1" could not be resolved to a product, how do you want to proceed?',
|
||||
'Create or assign product' => 'Create or assign product',
|
||||
'Cancel' => 'Cancel',
|
||||
'Add as new product' => 'Add as new product',
|
||||
'Add as barcode to existing product' => 'Add as barcode to existing product',
|
||||
'Add as new product and prefill barcode' => 'Add as new product and prefill barcode',
|
||||
'Are you sure to delete quantity unit "#1"?' => 'Are you sure to delete quantity unit "#1"?',
|
||||
'Are you sure to delete product "#1"?' => 'Are you sure to delete product "#1"?',
|
||||
'Are you sure to delete location "#1"?' => 'Are you sure to delete location "#1"?',
|
||||
'Manage API keys' => 'Manage API keys',
|
||||
'REST API & data model documentation' => 'REST API & data model documentation',
|
||||
'API keys' => 'API keys',
|
||||
'Create new API key' => 'Create new API key',
|
||||
'API key' => 'API key',
|
||||
'Expires' => 'Expires',
|
||||
'Created' => 'Created',
|
||||
'This product is not in stock' => 'This product is not in stock',
|
||||
'This means #1 will be added to stock' => 'This means #1 will be added to stock',
|
||||
'This means #1 will be removed from stock' => 'This means #1 will be removed from stock',
|
||||
'This means it is estimated that a new execution of this chore is tracked #1 days after the last was tracked' => 'This means it is estimated that a new execution of this chore is tracked #1 days after the last was tracked',
|
||||
'Removed #1 #2 of #3 from stock' => 'Removed #1 #2 of #3 from stock',
|
||||
'About grocy' => 'About grocy',
|
||||
'Close' => 'Close',
|
||||
'#1 batteries are due to be charged within the next #2 days' => '#1 batteries are due to be charged within the next #2 days',
|
||||
'#1 batteries are overdue to be charged' => '#1 batteries are overdue to be charged',
|
||||
'#1 chores are due to be done within the next #2 days' => '#1 chores are due to be done within the next #2 days',
|
||||
'#1 chores are overdue to be done' => '#1 chores are overdue to be done',
|
||||
'Released on' => 'Released on',
|
||||
'Consume #3 #1 of #2' => 'Consume #3 #1 of #2',
|
||||
'Added #1 #2 of #3 to stock' => 'Added #1 #2 of #3 to stock',
|
||||
'Stock amount of #1 is now #2 #3' => 'Stock amount of #1 is now #2 #3',
|
||||
'Tracked execution of chore #1 on #2' => 'Tracked execution of chore #1 on #2',
|
||||
'Tracked charge cycle of battery #1 on #2' => 'Tracked charge cycle of battery #1 on #2',
|
||||
'Consume all #1 which are currently in stock' => 'Consume all #1 which are currently in stock',
|
||||
'All' => 'All',
|
||||
'Track charge cycle of battery #1' => 'Track charge cycle of battery #1',
|
||||
'Track execution of chore #1' => 'Track execution of chore #1',
|
||||
'Filter by location' => 'Filter by location',
|
||||
'Search' => 'Search',
|
||||
'Not logged in' => 'Not logged in',
|
||||
'You have to select a product' => 'You have to select a product',
|
||||
'You have to select a chore' => 'You have to select a chore',
|
||||
'You have to select a battery' => 'You have to select a battery',
|
||||
'A name is required' => 'A name is required',
|
||||
'A location is required' => 'A location is required',
|
||||
'The amount cannot be lower than #1' => 'The amount cannot be lower than #1',
|
||||
'This cannot be negative' => 'This cannot be negative',
|
||||
'A quantity unit is required' => 'A quantity unit is required',
|
||||
'A period type is required' => 'A period type is required',
|
||||
'A best before date is required and must be later than today' => 'A best before date is required and must be later than today',
|
||||
'Settings' => 'Settings',
|
||||
'This can only be before now' => 'This can only be before now',
|
||||
'Calendar' => 'Calendar',
|
||||
'Recipes' => 'Recipes',
|
||||
'Edit recipe' => 'Edit recipe',
|
||||
'New recipe' => 'New recipe',
|
||||
'Ingredients list' => 'Ingredients list',
|
||||
'Add recipe ingredient' => 'Add recipe ingredient',
|
||||
'Edit recipe ingredient' => 'Edit recipe ingredient',
|
||||
'Are you sure to delete recipe "#1"?' => 'Are you sure to delete recipe "#1"?',
|
||||
'Are you sure to delete recipe ingredient "#1"?' => 'Are you sure to delete recipe ingredient "#1"?',
|
||||
'Are you sure to empty the shopping list?' => 'Are you sure to empty the shopping list?',
|
||||
'Clear list' => 'Clear list',
|
||||
'Requirements fulfilled' => 'Requirements fulfilled',
|
||||
'Put missing products on shopping list' => 'Put missing products on shopping list',
|
||||
'Not enough in stock, #1 ingredients missing' => 'Not enough in stock, #1 ingredients missing',
|
||||
'Enough in stock' => 'Enough in stock',
|
||||
'Not enough in stock, #1 ingredients missing but already on the shopping list' => 'Not enough in stock, #1 ingredients missing but already on the shopping list',
|
||||
'Expand to fullscreen' => 'Expand to fullscreen',
|
||||
'Ingredients' => 'Ingredients',
|
||||
'Preparation' => 'Preparation',
|
||||
'Recipe' => 'Recipe',
|
||||
'Not enough in stock, #1 missing, #2 already on shopping list' => 'Not enough in stock, #1 missing, #2 already on shopping list',
|
||||
'Show notes' => 'Show notes',
|
||||
'Put missing amount on shopping list' => 'Put missing amount on shopping list',
|
||||
'Are you sure to put all missing ingredients for recipe "#1" on the shopping list?' => 'Are you sure to put all missing ingredients for recipe "#1" on the shopping list?',
|
||||
'Added for recipe #1' => 'Added for recipe #1',
|
||||
'Manage users' => 'Manage users',
|
||||
'User' => 'User',
|
||||
'Users' => 'Users',
|
||||
'Are you sure to delete user "#1"?' => 'Are you sure to delete user "#1"?',
|
||||
'Create user' => 'Create user',
|
||||
'Edit user' => 'Edit user',
|
||||
'First name' => 'First name',
|
||||
'Last name' => 'Last name',
|
||||
'A username is required' => 'A username is required',
|
||||
'Confirm password' => 'Confirm password',
|
||||
'Passwords do not match' => 'Passwords do not match',
|
||||
'Change password' => 'Change password',
|
||||
'Done by' => 'Done by',
|
||||
'Last done by' => 'Last done by',
|
||||
'Unknown' => 'Unknown',
|
||||
'Filter by chore' => 'Filter by chore',
|
||||
'Chores journal' => 'Chores journal',
|
||||
'0 means suggestions for the next charge cycle are disabled' => '0 means suggestions for the next charge cycle are disabled',
|
||||
'Charge cycle interval (days)' => 'Charge cycle interval (days)',
|
||||
'Last price' => 'Last price',
|
||||
'Price history' => 'Price history',
|
||||
'No price history available' => 'No price history available',
|
||||
'Price' => 'Price',
|
||||
'in #1 per purchase quantity unit' => 'in #1 per purchase quantity unit',
|
||||
'The price cannot be lower than #1' => 'The price cannot be lower than #1',
|
||||
'#1 product expires within the next #2 days' => '#1 product expires within the next #2 days',
|
||||
'#1 product is already expired' => '#1 product is already expired',
|
||||
'#1 product is below defined min. stock amount' => '#1 product is below defined min. stock amount',
|
||||
'Unit' => 'Unit',
|
||||
'Units' => 'Units',
|
||||
'#1 chore is due to be done within the next #2 days' => '#1 chore is due to be done within the next #2 days',
|
||||
'#1 chore is overdue to be done' => '#1 chore is overdue to be done',
|
||||
'#1 battery is due to be charged within the next #2 days' => '#1 battery is due to be charged within the next #2 days',
|
||||
'#1 battery is overdue to be charged' => '#1 battery is overdue to be charged',
|
||||
'#1 unit was automatically added and will apply in addition to the amount entered here' => '#1 unit was automatically added and will apply in addition to the amount entered here',
|
||||
'in singular form' => 'in singular form',
|
||||
'in plural form' => 'in plural form',
|
||||
'Never expires' => 'Never expires',
|
||||
'This cannot be lower than #1' => 'This cannot be lower than #1',
|
||||
'-1 means that this product never expires' => '-1 means that this product never expires',
|
||||
'Quantity unit' => 'Quantity unit',
|
||||
'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Only check if a single unit is in stock (a different quantity can then be used above)',
|
||||
'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?' => 'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?',
|
||||
'Removed all ingredients of recipe "#1" from stock' => 'Removed all ingredients of recipe "#1" from stock',
|
||||
'Consume all ingredients needed by this recipe' => 'Consume all ingredients needed by this recipe',
|
||||
'Click to show technical details' => 'Click to show technical details',
|
||||
'Error while saving, probably this item already exists' => 'Error while saving, probably this item already exists',
|
||||
'Error details' => 'Error details',
|
||||
'Tasks' => 'Tasks',
|
||||
'Show done tasks' => 'Show done tasks',
|
||||
'Task' => 'Task',
|
||||
'Due' => 'Due',
|
||||
'Assigned to' => 'Assigned to',
|
||||
'Mark task "#1" as completed' => 'Mark task "#1" as completed',
|
||||
'Uncategorized' => 'Uncategorized',
|
||||
'Task categories' => 'Task categories',
|
||||
'Create task' => 'Create task',
|
||||
'A due date is required' => 'A due date is required',
|
||||
'Category' => 'Category',
|
||||
'Edit task' => 'Edit task',
|
||||
'Are you sure to delete task "#1"?' => 'Are you sure to delete task "#1"?',
|
||||
'#1 task is due to be done within the next #2 days' => '#1 task is due to be done within the next #2 days',
|
||||
'#1 tasks are due to be done within the next #2 days' => '#1 tasks are due to be done within the next #2 days',
|
||||
'#1 task is overdue to be done' => '#1 task is overdue to be done',
|
||||
'#1 tasks are overdue to be done' => '#1 tasks are overdue to be done',
|
||||
'Edit task category' => 'Edit task category',
|
||||
'Create task category' => 'Create task category',
|
||||
'Product groups' => 'Product groups',
|
||||
'Ungrouped' => 'Ungrouped',
|
||||
'Create product group' => 'Create product group',
|
||||
'Edit product group' => 'Edit product group',
|
||||
'Product group' => 'Product group',
|
||||
'Are you sure to delete product group "#1"?' => 'Are you sure to delete product group "#1"?',
|
||||
'Stay logged in permanently' => 'Stay logged in permanently',
|
||||
'When not set, you will get logged out at latest after 30 days' => 'When not set, you will get logged out at latest after 30 days',
|
||||
'Filter by status' => 'Filter by status',
|
||||
'Below min. stock amount' => 'Below min. stock amount',
|
||||
'Expiring soon' => 'Expiring soon',
|
||||
'Already expired' => 'Already expired',
|
||||
'Due soon' => 'Due soon',
|
||||
'Overdue' => 'Overdue',
|
||||
'View settings' => 'View settings',
|
||||
'Auto reload on external changes' => 'Auto reload on external changes',
|
||||
'Enable night mode' => 'Enable night mode',
|
||||
'Auto enable in time range' => 'Auto enable in time range',
|
||||
'From' => 'From',
|
||||
'in format' => 'in format',
|
||||
'To' => 'To',
|
||||
'Time range goes over midnight' => 'Time range goes over midnight',
|
||||
'Product picture' => 'Product picture',
|
||||
'No file selected' => 'No file selected',
|
||||
'If you don\'t select a file, the current picture will not be altered' => 'If you don\'t select a file, the current picture will not be altered',
|
||||
'Current picture' => 'Current picture',
|
||||
'Delete' => 'Delete',
|
||||
'The current picture will be deleted when you save the product' => 'The current picture will be deleted when you save the product',
|
||||
'Select file' => 'Select file',
|
||||
'Image of product #1' => 'Image of product #1',
|
||||
'This product cannot be deleted because it is in stock, please remove the stock amount first.' => 'This product cannot be deleted because it is in stock, please remove the stock amount first.',
|
||||
'Delete not possible' => 'Delete not possible',
|
||||
'Equipment' => 'Equipment',
|
||||
'Instruction manual' => 'Instruction manual',
|
||||
'The selected equipment has no instruction manual' => 'The selected equipment has no instruction manual',
|
||||
'Notes' => 'Notes',
|
||||
'Edit equipment' => 'Edit equipment',
|
||||
'Create equipment' => 'Create equipment',
|
||||
'If you don\'t select a file, the current instruction manual will not be altered' => 'If you don\'t select a file, the current instruction manual will not be altered',
|
||||
'Current instruction manual' => 'Current instruction manual',
|
||||
'No instruction manual available' => 'No instruction manual available',
|
||||
'The current instruction manual will be deleted when you save the equipment' => 'The current instruction manual will be deleted when you save the equipment',
|
||||
'No picture available' => 'No picture available',
|
||||
'Filter by product group' => 'Filter by product group',
|
||||
'Presets for new products' => 'Presets for new products',
|
||||
'Included recipes' => 'Included recipes',
|
||||
'A recipe is required' => 'A recipe is required',
|
||||
'Add included recipe' => 'Add included recipe',
|
||||
'Edit included recipe' => 'Edit included recipe',
|
||||
'Group' => 'Group',
|
||||
'This will be used as a headline to group ingredients together' => 'This will be used as a headline to group ingredients together',
|
||||
'Journal' => 'Journal',
|
||||
'Stock journal' => 'Stock journal',
|
||||
'Filter by product' => 'Filter by product',
|
||||
'Booking time' => 'Booking time',
|
||||
'Booking type' => 'Booking type',
|
||||
'Undo booking' => 'Undo booking',
|
||||
'Undone on' => 'Undone on',
|
||||
'Batteries journal' => 'Batteries journal',
|
||||
'Filter by battery' => 'Filter by battery',
|
||||
'Undo charge cycle' => 'Undo charge cycle',
|
||||
'Undo chore execution' => 'Undo chore execution',
|
||||
'Chore execution successfully undone' => 'Chore execution successfully undone',
|
||||
'Undo' => 'Undo',
|
||||
'Booking successfully undone' => 'Booking successfully undone',
|
||||
'Charge cycle successfully undone' => 'Charge cycle successfully undone',
|
||||
'This cannot be negative and must be an integral number' => 'This cannot be negative and must be an integral number',
|
||||
'Disable stock fulfillment checking for this ingredient' => 'Disable stock fulfillment checking for this ingredient',
|
||||
'Add all list items to stock' => 'Add all list items to stock',
|
||||
'Add #3 #1 of #2 to stock' => 'Add #3 #1 of #2 to stock',
|
||||
'Adding shopping list item #1 of #2' => 'Adding shopping list item #1 of #2',
|
||||
'Use a specific stock item' => 'Use a specific stock item',
|
||||
'The first item in this list would be picked by the default rule which is "First expiring first, then first in first out"' => 'The first item in this list would be picked by the default rule which is "First expiring first, then first in first out"',
|
||||
'Mark #3 #1 of #2 as open' => 'Mark #3 #1 of #2 as open',
|
||||
'When a product was marked as opened, the best before date will be replaced by today + this amount of days (a value of 0 disables this)' => 'When a product was marked as opened, the best before date will be replaced by today + this amount of days (a value of 0 disables this)',
|
||||
'Default best before days after opened' => 'Default best before days after opened',
|
||||
'Marked #1 #2 of #3 as opened' => 'Marked #1 #2 of #3 as opened',
|
||||
'Mark as opened' => 'Mark as opened',
|
||||
'Expires on #1; Bought on #2' => 'Expires on #1; Bought on #2',
|
||||
'Not opened' => 'Not opened',
|
||||
'Opened' => 'Opened',
|
||||
'Mark #3 #1 of #2 as open' => 'Mark #3 #1 of #2 as open',
|
||||
'#1 opened' => '#1 opened',
|
||||
'Product expires' => 'Product expires',
|
||||
'Task due' => 'Task due',
|
||||
'Chore due' => 'Chore due',
|
||||
'Battery charge cycle due' => 'Battery charge cycle due',
|
||||
'Show clock in header' => 'Show clock in header',
|
||||
'Stock settings' => 'Stock settings',
|
||||
'Shopping list to stock workflow' => 'Shopping list to stock workflow',
|
||||
'Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default best before days" set' => 'Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default best before days" set',
|
||||
'Skip' => 'Skip'
|
||||
);
|
6
localization/fr/chore_types.php
Normal file
6
localization/fr/chore_types.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'manually' => 'Manuelle',
|
||||
'dynamic-regular' => 'Régulière-dynamique'
|
||||
);
|
10
localization/fr/component_translations.php
Normal file
10
localization/fr/component_translations.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'timeago_locale' => 'fr',
|
||||
'timeago_nan' => 'Il y a NaN années',
|
||||
'moment_locale' => 'fr',
|
||||
'datatables_localization' => '{"sProcessing":"Traitement en cours...","sSearch":"Rechercher :","sLengthMenu":"Afficher _MENU_ éléments","sInfo":"Affichage de l\'élément _START_ à _END_ sur _TOTAL_ éléments","sInfoEmpty":"Affichage de l\'élément 0 à 0 sur 0 élément","sInfoFiltered":"(filtré de _MAX_ éléments au total)","sInfoPostFix":"","sLoadingRecords":"Chargement en cours...","sZeroRecords":"Aucun élément à afficher","sEmptyTable":"Aucune donnée disponible dans le tableau","oPaginate":{"sFirst":"Premier","sPrevious":"Précédent","sNext":"Suivant","sLast":"Dernier"},"oAria":{"sSortAscending":": activer pour trier la colonne par ordre croissant","sSortDescending":": activer pour trier la colonne par ordre décroissant"}}',
|
||||
'summernote_locale' => 'fr-FR',
|
||||
'fullcalendar_locale' => 'fr'
|
||||
);
|
87
localization/fr/demo_data.php
Normal file
87
localization/fr/demo_data.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Cookies' => 'Cookies',
|
||||
'Chocolate' => 'Chocolat',
|
||||
'Pantry' => 'Garde-manger',
|
||||
'Candy cupboard' => 'Boîte de bonbons',
|
||||
'Tinned food cupboard' => 'Conserve de nourriture',
|
||||
'Fridge' => 'Réfrigérateur',
|
||||
'Piece' => 'Pièce',
|
||||
'Pieces' => 'Pièces',
|
||||
'Pack' => 'Pack',
|
||||
'Packs' => 'Packs',
|
||||
'Glass' => 'Verre',
|
||||
'Glasses' => 'Verres',
|
||||
'Tin' => 'Pot',
|
||||
'Tins' => 'Pots',
|
||||
'Can' => 'Canette',
|
||||
'Cans' => 'Canettes',
|
||||
'Bunch' => 'Brunch',
|
||||
'Bunches' => 'Brunchs',
|
||||
'Gummy bears' => 'Oursons en gélatine',
|
||||
'Crisps' => 'Chips',
|
||||
'Eggs' => 'Oeufs',
|
||||
'Noodles' => 'Nouilles',
|
||||
'Pickles' => 'Cornichons',
|
||||
'Gulash soup' => 'Soupe de goulache',
|
||||
'Yogurt' => 'Yaourt',
|
||||
'Cheese' => 'Fromage',
|
||||
'Cold cuts' => 'Charcuterie',
|
||||
'Paprika' => 'Paprika',
|
||||
'Cucumber' => 'Concombre',
|
||||
'Radish' => 'Radis',
|
||||
'Tomato' => 'Tomate',
|
||||
'Changed towels in the bathroom' => 'Changement des serviettes dans la salle de bain',
|
||||
'Cleaned the kitchen floor' => 'Nettoyage du sol de la cuisine',
|
||||
'Warranty ends' => 'Fin de garantie',
|
||||
'TV remote control' => 'Télécommande de la TV',
|
||||
'Alarm clock' => 'Réveil',
|
||||
'Heat remote control' => 'Télécommande du chauffage',
|
||||
'Lawn mowed in the garden' => 'Jardin tondu',
|
||||
'Some good snacks' => 'Quelques bons snacks',
|
||||
'Pizza dough' => 'Pâte à pizza',
|
||||
'Sieved tomatoes' => 'Sauce tomate',
|
||||
'Salami' => 'Salami',
|
||||
'Toast' => 'Pain grillé',
|
||||
'Minced meat' => 'Viande hachée',
|
||||
'Pizza' => 'PIzza',
|
||||
'Spaghetti bolognese' => 'Spaghetti bolognaise',
|
||||
'Sandwiches' => 'Sandwiches',
|
||||
'English' => 'Anglais',
|
||||
'German' => 'Allemand',
|
||||
'Italian' => 'Italien',
|
||||
'Demo in different language' => 'Démo dans une langue différente',
|
||||
'This is the note content of the recipe ingredient' => 'Ceci est le contenu de la note concernant l\'ingrédient de la recette',
|
||||
'Demo User' => 'Utilisateur de démonstration',
|
||||
'Gram' => 'Gramme',
|
||||
'Grams' => 'Grammes',
|
||||
'Flour' => 'Farine',
|
||||
'Pancakes' => 'Crêpes',
|
||||
'Sugar' => 'Sucre',
|
||||
'Home' => 'Domicile',
|
||||
'Life' => 'Vie',
|
||||
'Projects' => 'Projets',
|
||||
'Repair the garage door' => 'Réparer la porte du garage',
|
||||
'Fork and improve grocy' => 'Forker et améliorer grocy',
|
||||
'Find a solution for what to do when I forget the door keys' => 'Trouver une solution pour savoir quoi faire quand j\'oublie les clefs de la porte',
|
||||
'Sweets' => 'Bonbons',
|
||||
'Bakery products' => 'Produits de la boulangerie',
|
||||
'Tinned food' => 'Conserve',
|
||||
'Butchery products' => 'Produits de la boucherie',
|
||||
'Vegetables/Fruits' => 'Légumes/Fruits',
|
||||
'Refrigerated products' => 'Produits réfrigérés',
|
||||
'Coffee machine' => 'Machie à café',
|
||||
'Dishwasher' => 'Lave-vaisselle',
|
||||
'Liter' => 'Litière',
|
||||
'Liters' => 'Litières',
|
||||
'Bottle' => 'Bouteille',
|
||||
'Bottles' => 'Bouteilles',
|
||||
'Milk' => 'Lait',
|
||||
'Chocolate sauce' => 'Coulis de chocolat',
|
||||
'Milliliters' => 'Millilitres',
|
||||
'Milliliter' => 'Millilitre',
|
||||
'Bottom' => 'Dessous',
|
||||
'Topping' => 'Garniture',
|
||||
'French' => 'Français'
|
||||
);
|
8
localization/fr/stock_transaction_types.php
Normal file
8
localization/fr/stock_transaction_types.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'purchase' => 'Achat',
|
||||
'consume' => 'Consommation',
|
||||
'inventory-correction' => 'Correction d\'inventaire',
|
||||
'product-opened' => 'Produit ouvert'
|
||||
);
|
330
localization/fr/strings.php
Normal file
330
localization/fr/strings.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Stock overview' => 'Aperçu du stock',
|
||||
'#1 products expiring within the next #2 days' => '#1 produits se périment dans les #2 jours',
|
||||
'#1 products are already expired' => '#1 produits sont périmés',
|
||||
'#1 products are below defined min. stock amount' => '#1 produits sont sous le seuil de stock minimum',
|
||||
'Product' => 'Produit',
|
||||
'Amount' => 'Quantité',
|
||||
'Next best before date' => 'Prochaine date de péremption',
|
||||
'Logout' => 'Se déconnecter',
|
||||
'Chores overview' => 'Aperçu des corvées',
|
||||
'Batteries overview' => 'Batteries',
|
||||
'Purchase' => 'Achat',
|
||||
'Consume' => 'Consommation',
|
||||
'Inventory' => 'Inventaire',
|
||||
'Shopping list' => 'Liste de courses',
|
||||
'Chore tracking' => 'Suivi des corvées',
|
||||
'Battery tracking' => 'Suivi des batteries',
|
||||
'Products' => 'Produits',
|
||||
'Locations' => 'Emplacements',
|
||||
'Quantity units' => 'Formats',
|
||||
'Chores' => 'Corvées',
|
||||
'Batteries' => 'Batteries',
|
||||
'Chore' => 'Corvée',
|
||||
'Next estimated tracking' => 'Prochaine occurrence estimée',
|
||||
'Last tracked' => 'Dernière réalisation',
|
||||
'Battery' => 'Batterie',
|
||||
'Last charged' => 'Dernier chargement',
|
||||
'Next planned charge cycle' => 'Prochaine charge planifiée',
|
||||
'Best before' => 'Date d\'expiration',
|
||||
'OK' => 'Ok',
|
||||
'Product overview' => 'Aperçu du produit',
|
||||
'Stock quantity unit' => 'Format de stockage',
|
||||
'Stock amount' => 'Quantité en stock',
|
||||
'Last purchased' => 'Dernier achat',
|
||||
'Last used' => 'Dernière utilisation',
|
||||
'Spoiled' => 'Périmé',
|
||||
'Barcode lookup is disabled' => 'La recherche par code barres est désactivée',
|
||||
'will be added to the list of barcodes for the selected product on submit' => 'sera ajouté à la liste des codes barres du produit sélectionné à l\'envoi',
|
||||
'New amount' => 'Nouvelle quantité',
|
||||
'Note' => 'Note',
|
||||
'Tracked time' => 'Réalisé le',
|
||||
'Chore overview' => 'Aperçu de la corvée',
|
||||
'Tracked count' => 'Nombre de réalisations',
|
||||
'Battery overview' => 'Aperçu des batteries',
|
||||
'Charge cycles count' => 'Nombre de charges',
|
||||
'Create shopping list item' => 'Créer une liste de courses',
|
||||
'Edit shopping list item' => 'Modifier une liste de courses',
|
||||
'#1 units were automatically added and will apply in addition to the amount entered here' => '#1 unités seront automatiquement ajoutées en plus de la quantité renseignée ici',
|
||||
'Save' => 'Sauvegarder',
|
||||
'Add' => 'Ajouter',
|
||||
'Name' => 'Nom',
|
||||
'Location' => 'Emplacement',
|
||||
'Min. stock amount' => 'Quantité minimum en stock',
|
||||
'QU purchase' => 'Format achat',
|
||||
'QU stock' => 'Format stock',
|
||||
'QU factor' => 'Facteur format',
|
||||
'Description' => 'Description',
|
||||
'Create product' => 'Créer un produit',
|
||||
'Barcode(s)' => 'Code(s) barres',
|
||||
'Minimum stock amount' => 'Quantité minimum en stock',
|
||||
'Default best before days' => 'Jours avant péremption par défaut',
|
||||
'Quantity unit purchase' => 'Format à l\'achat',
|
||||
'Quantity unit stock' => 'Format au stockage',
|
||||
'Factor purchase to stock quantity unit' => 'Facteur entre la quantité à l\'achat et la quantité en stock',
|
||||
'Create location' => 'Créer un emplacement',
|
||||
'Create quantity unit' => 'Créer un format',
|
||||
'Period type' => 'Type de période',
|
||||
'Period days' => 'Jours dans la période',
|
||||
'Create chore' => 'Créer une corvée',
|
||||
'Used in' => 'Utilisé dans',
|
||||
'Create battery' => 'Créer une batterie',
|
||||
'Edit battery' => 'Modifier une batterie',
|
||||
'Edit chore' => 'Modifier une corvée',
|
||||
'Edit quantity unit' => 'Modifier le format',
|
||||
'Edit product' => 'Modifier le produit',
|
||||
'Edit location' => 'Modifier l\'emplacement',
|
||||
'Record data' => 'Enregistrer les données',
|
||||
'Manage master data' => 'Gérer les données',
|
||||
'This will apply to added products' => 'Sera appliqué aux produits ajoutés',
|
||||
'never' => 'jamais',
|
||||
'Add products that are below defined min. stock amount' => 'Ajouter les produits qui sont en dessous du seuil de stock minimum',
|
||||
'For purchases this amount of days will be added to today for the best before date suggestion' => 'A l\'achat, ce nombre de jours sera ajouté à la date de péremption suggérée',
|
||||
'This means 1 #1 purchased will be converted into #2 #3 in stock' => '1 #1 acheté sera converti en #2 #3 dans le stock',
|
||||
'Login' => 'Se connecter',
|
||||
'Username' => 'Identifiant',
|
||||
'Password' => 'Mot de passe',
|
||||
'Invalid credentials, please try again' => 'Identifiants invalides, merci de réessayer',
|
||||
'Are you sure to delete battery "#1"?' => 'Êtes vous sûr de vouloir supprimer la batterie "#1" ?',
|
||||
'Yes' => 'Oui',
|
||||
'No' => 'Non',
|
||||
'Are you sure to delete chore "#1"?' => 'Voulez-vous vraiment supprimer la corvée "#1" ?',
|
||||
'"#1" could not be resolved to a product, how do you want to proceed?' => '"#1" n\'a pas été retrouvé en tant que produit, comment voulez-vous procéder ?',
|
||||
'Create or assign product' => 'Créer ou assigner à un produit',
|
||||
'Cancel' => 'Annuler',
|
||||
'Add as new product' => 'Ajouter un nouveau produit',
|
||||
'Add as barcode to existing product' => 'Ajouter en tant que code-barres à un produit existant',
|
||||
'Add as new product and prefill barcode' => 'Ajouter un nouveau produit et pré-renseigner le code-barres',
|
||||
'Are you sure to delete quantity unit "#1"?' => 'Voulez-vous vraiment supprimer le format "#1" ?',
|
||||
'Are you sure to delete product "#1"?' => 'Voulez-vous vraiment supprimer le produit "#1" ?',
|
||||
'Are you sure to delete location "#1"?' => 'Voulez-vous vraiment supprimer l\'emplacement "#1" ?',
|
||||
'Manage API keys' => 'Gérer les clefs API',
|
||||
'REST API & data model documentation' => 'Documentation sur l\'API REST & le modèle des données',
|
||||
'API keys' => 'Clefs API',
|
||||
'Create new API key' => 'Créer une nouvelle clef API',
|
||||
'API key' => 'Clef API',
|
||||
'Expires' => 'Valide jusqu\'à',
|
||||
'Created' => 'Créée',
|
||||
'This product is not in stock' => 'Ce produit n\'est pas en stock',
|
||||
'This means #1 will be added to stock' => '#1 sera ajouté au stock',
|
||||
'This means #1 will be removed from stock' => '#1 sera supprimé du stock',
|
||||
'This means it is estimated that a new execution of this chore is tracked #1 days after the last was tracked' => 'La prochaine exécution de cette corvée sera programmée #1 jours après sa dernière exécution',
|
||||
'Removed #1 #2 of #3 from stock' => '#1 #2 de #3 supprimés du stock',
|
||||
'About grocy' => 'À propos de grocy',
|
||||
'Close' => 'Fermer',
|
||||
'#1 batteries are due to be charged within the next #2 days' => '#1 batteries doivent être rechargées dans les #2 prochains jours',
|
||||
'#1 batteries are overdue to be charged' => '#1 batteries n\'ont pas été rechargées à temps',
|
||||
'#1 chores are due to be done within the next #2 days' => '#1 corvées doivent être réalisées dans les #2 prochains jours',
|
||||
'#1 chores are overdue to be done' => '#1 corvées n\'ont pas été réalisées à temps',
|
||||
'Released on' => 'Date de sortie',
|
||||
'Consume #3 #1 of #2' => 'Consommer #3 #1 de #2',
|
||||
'Added #1 #2 of #3 to stock' => '#1 #2 de #3 ajoutés au stock',
|
||||
'Stock amount of #1 is now #2 #3' => 'La quantité en stock de #1 est maintenant de #2 #3',
|
||||
'Tracked execution of chore #1 on #2' => 'La corvée "#1" a été réalisée le #2',
|
||||
'Tracked charge cycle of battery #1 on #2' => 'La batterie "#1" a été rechargée le #2',
|
||||
'Consume all #1 which are currently in stock' => 'Consommer tous les #1 actuellement en stock',
|
||||
'All' => 'Tout',
|
||||
'Track charge cycle of battery #1' => 'Indiquer le rechargement de la batterie #1',
|
||||
'Track execution of chore #1' => 'Indiquer la réalisation de la corvée #1',
|
||||
'Filter by location' => 'Filtrer par emplacement',
|
||||
'Search' => 'Recherche',
|
||||
'Not logged in' => 'Non connecté',
|
||||
'You have to select a product' => 'Vous devez sélectionner un produit',
|
||||
'You have to select a chore' => 'Vous devez sélectionner une corvée',
|
||||
'You have to select a battery' => 'Vous devez sélectionner une batterie',
|
||||
'A name is required' => 'Un nom est requis',
|
||||
'A location is required' => 'Un emplacement est requis',
|
||||
'The amount cannot be lower than #1' => 'La quantité ne peut être inférieure à #1',
|
||||
'This cannot be negative' => 'Ne peut être négatif',
|
||||
'A quantity unit is required' => 'Un format est requis',
|
||||
'A period type is required' => 'Un type de période est requis',
|
||||
'A best before date is required and must be later than today' => 'Une date de péremption est requise et doit être supérieure à la date du jour',
|
||||
'Settings' => 'Paramètres',
|
||||
'This can only be before now' => 'Ne peut être qu\'antérieur à maintenant',
|
||||
'Calendar' => 'Calendrier',
|
||||
'Recipes' => 'Recettes',
|
||||
'Edit recipe' => 'Modifier une recette',
|
||||
'New recipe' => 'Nouvelle recette',
|
||||
'Ingredients list' => 'Liste des ingrédients',
|
||||
'Add recipe ingredient' => 'Ajouter un ingrédient dans la recette',
|
||||
'Edit recipe ingredient' => 'Modifier un ingrédient dans la recette',
|
||||
'Are you sure to delete recipe "#1"?' => 'Voulez-vous vraiment supprimer la recette "#1" ?',
|
||||
'Are you sure to delete recipe ingredient "#1"?' => 'Voulez-vous vraiment supprimer l\'ingrédient "#1" de la recette ?',
|
||||
'Are you sure to empty the shopping list?' => 'Voulez-vous vraiment vider la liste de courses ?',
|
||||
'Clear list' => 'Vider la liste',
|
||||
'Requirements fulfilled' => 'Prérequis remplis',
|
||||
'Put missing products on shopping list' => 'Ajouter les produits manquants dans la liste de courses',
|
||||
'Not enough in stock, #1 ingredients missing' => 'Pas assez en stock, #1 ingrédients manquants',
|
||||
'Enough in stock' => 'Il y en a assez en stock',
|
||||
'Not enough in stock, #1 ingredients missing but already on the shopping list' => 'Pas assez en stock, #1 ingrédients manquants mais déjà dans la liste de courses',
|
||||
'Expand to fullscreen' => 'Mettre en plein écran',
|
||||
'Ingredients' => 'Ingrédients',
|
||||
'Preparation' => 'Préparation',
|
||||
'Recipe' => 'Recette',
|
||||
'Not enough in stock, #1 missing, #2 already on shopping list' => 'Pas assez en stock, #1 manquant et #2 déjà dans la liste de courses',
|
||||
'Show notes' => 'Afficher les notes',
|
||||
'Put missing amount on shopping list' => 'Ajouter la quantité manquante dans la liste de courses',
|
||||
'Are you sure to put all missing ingredients for recipe "#1" on the shopping list?' => 'Voulez-vous vraiment ajouter tous les ingrédients manquants de la recette "#1" dans la liste de courses ?',
|
||||
'Added for recipe #1' => 'Ajoutés pour la recette #1',
|
||||
'Manage users' => 'Gérer les utilisateurs',
|
||||
'User' => 'Utilisateur',
|
||||
'Users' => 'Utilisateurs',
|
||||
'Are you sure to delete user "#1"?' => 'Voulez-vous vraiment supprimer l\'utilisateur "#1" ?',
|
||||
'Create user' => 'Créer un utilisateur',
|
||||
'Edit user' => 'Modifier un utilisateur',
|
||||
'First name' => 'Prénom',
|
||||
'Last name' => 'Nom',
|
||||
'A username is required' => 'Un nom d\'utilisateur est requis',
|
||||
'Confirm password' => 'Confirmation du mot de passe',
|
||||
'Passwords do not match' => 'Les mots de passe ne sont pas identiques',
|
||||
'Change password' => 'Changer le mot de passe',
|
||||
'Done by' => 'Fait par',
|
||||
'Last done by' => 'Dernière réalisation par',
|
||||
'Unknown' => 'Inconnu',
|
||||
'Filter by chore' => 'Filtrer par corvée',
|
||||
'Chores journal' => 'Journal des corvées',
|
||||
'0 means suggestions for the next charge cycle are disabled' => '0 implique que les suggestions du prochain cycle de charge seront désactivées',
|
||||
'Charge cycle interval (days)' => 'Intervalle du cycle de charge (jours)',
|
||||
'Last price' => 'Dernier prix',
|
||||
'Price history' => 'Historique des prix',
|
||||
'No price history available' => 'Aucun historique disponible',
|
||||
'Price' => 'Prix',
|
||||
'in #1 per purchase quantity unit' => 'en #1 par quantité achetée (au format d\'achat)',
|
||||
'The price cannot be lower than #1' => 'Le prix ne peut être inférieur à #1',
|
||||
'#1 product expires within the next #2 days' => '#1 produit se périme dans les #2 prochains jours',
|
||||
'#1 product is already expired' => '#1 produit est périmé',
|
||||
'#1 product is below defined min. stock amount' => '#1 produit est sous le seuil de stock minimum',
|
||||
'Unit' => 'Unité',
|
||||
'Units' => 'Unités',
|
||||
'#1 chore is due to be done within the next #2 days' => '#1 corvée doit être réalisée dans les #2 prochains jours',
|
||||
'#1 chore is overdue to be done' => '#1 corvée n\'a pas été réalisée à temps',
|
||||
'#1 battery is due to be charged within the next #2 days' => '#1 batterie doit être rechargée dans les #2 prochains jours',
|
||||
'#1 battery is overdue to be charged' => '#1 batterie n\'a pas été rechargée à temps',
|
||||
'#1 unit was automatically added and will apply in addition to the amount entered here' => '#1 unité a automatiquement été ajoutée et sera appliquée en plus à la quantité entrée ici',
|
||||
'in singular form' => 'Au singulier',
|
||||
'in plural form' => 'Au pluriel',
|
||||
'Never expires' => 'Ne périme jamais',
|
||||
'This cannot be lower than #1' => 'Ne peut être inférieur à #1',
|
||||
'-1 means that this product never expires' => '-1 implique que ce produit ne périme jamais',
|
||||
'Quantity unit' => 'Format',
|
||||
'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Vérifier uniquement si une unité est en stock (une quantité différente peut alors être utilisée au dessus)',
|
||||
'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?' => 'Voulez-vous vraiment consommer tous les ingrédients requis par la recette "#1" (les ingrédients avec l\'option "Vérifier uniquement si une unité est en stock" seront ignorés) ?',
|
||||
'Removed all ingredients of recipe "#1" from stock' => 'Enlever tous les ingrédients de la recette "#1" du stock',
|
||||
'Consume all ingredients needed by this recipe' => 'Consommer tous les ingrédients requis par cette recette',
|
||||
'Click to show technical details' => 'Cliquer pour afficher les détails techniques',
|
||||
'Error while saving, probably this item already exists' => 'Erreur à l\'enregistrement, cet objet existe déjà',
|
||||
'Error details' => 'Détails sur l\'erreur',
|
||||
'Tasks' => 'Tâches',
|
||||
'Show done tasks' => 'Afficher les tâches terminées',
|
||||
'Task' => 'Tâche',
|
||||
'Due' => 'À faire',
|
||||
'Assigned to' => 'Assigné à',
|
||||
'Mark task "#1" as completed' => 'Indiquer la tâche "#1" comme terminée',
|
||||
'Uncategorized' => 'Sans catégorie',
|
||||
'Task categories' => 'Catégories de tâche',
|
||||
'Create task' => 'Créer une tâche',
|
||||
'A due date is required' => 'Une date de réalisation est requise',
|
||||
'Category' => 'Catégorie',
|
||||
'Edit task' => 'Modifier la tâche',
|
||||
'Are you sure to delete task "#1"?' => 'Voulez-vous vraiment supprimer la tâche "#1" ?',
|
||||
'#1 task is due to be done within the next #2 days' => '#1 tâche doit être réalisée dans les #2 prochains jours',
|
||||
'#1 tasks are due to be done within the next #2 days' => '#1 tâches doivent être réalisées dans les #2 prochains jours',
|
||||
'#1 task is overdue to be done' => '#1 tâche n\'a pas été réalisée à temps',
|
||||
'#1 tasks are overdue to be done' => '#1 tâches n\'ont pas été réalisées à temps',
|
||||
'Edit task category' => 'Modifier la catégorie de tâche',
|
||||
'Create task category' => 'Créer une catégorie de tâche',
|
||||
'Product groups' => 'Groupes de produit',
|
||||
'Ungrouped' => 'Sans groupe',
|
||||
'Create product group' => 'Créer un groupe de produit',
|
||||
'Edit product group' => 'Modifier le groupe de produit',
|
||||
'Product group' => 'Groupe de produit',
|
||||
'Are you sure to delete product group "#1"?' => 'Voulez-vous vraiment supprimer le groupe de produit "#1" ?',
|
||||
'Stay logged in permanently' => 'Rester connecté de manière permanente',
|
||||
'When not set, you will get logged out at latest after 30 days' => 'Si non défini, vous serez déconnecté après au moins 30 jours',
|
||||
'Filter by status' => 'Filtrer par statut',
|
||||
'Below min. stock amount' => 'En dessous du seuil de stock minimum',
|
||||
'Expiring soon' => 'Expire bientôt',
|
||||
'Already expired' => 'Déjà périmé',
|
||||
'Due soon' => 'À réaliser bientôt',
|
||||
'Overdue' => 'En retard',
|
||||
'View settings' => 'Voir les paramètres',
|
||||
'Auto reload on external changes' => 'Mettre à jour automatiquement lors d\'un changement externe',
|
||||
'Enable night mode' => 'Activer le mode nuit',
|
||||
'Auto enable in time range' => 'Activer automatiquement pendant la période',
|
||||
'From' => 'De',
|
||||
'in format' => 'Au format',
|
||||
'To' => 'à',
|
||||
'Time range goes over midnight' => 'La période inclus minuit',
|
||||
'Product picture' => 'Photo du produit',
|
||||
'No file selected' => 'Aucun fichier sélectionné',
|
||||
'If you don\'t select a file, the current picture will not be altered' => 'Si vous ne sélectionnez pas de photo, l\'actuelle sera conservée',
|
||||
'Current picture' => 'Photo actuelle',
|
||||
'Delete' => 'Supprimer',
|
||||
'The current picture will be deleted when you save the product' => 'La photo actuelle va être supprimée lors de la sauvegarde du produit',
|
||||
'Select file' => 'Sélectionner un fichier',
|
||||
'Image of product #1' => 'Photo du produit #1',
|
||||
'This product cannot be deleted because it is in stock, please remove the stock amount first.' => 'Ce produit ne peut être supprimé puisqu\'il est en stock. Merci d\'enlever la quantité en stock avant.',
|
||||
'Delete not possible' => 'Impossible de supprimer',
|
||||
'Equipment' => 'Équipement',
|
||||
'Instruction manual' => 'Manuel d\'utilisation',
|
||||
'The selected equipment has no instruction manual' => 'L\'équipement sélectionné n\'a pas de manuel d\'utilisation',
|
||||
'Notes' => 'Notes',
|
||||
'Edit equipment' => 'Modifier un équipement',
|
||||
'Create equipment' => 'Créer un équipement',
|
||||
'If you don\'t select a file, the current instruction manual will not be altered' => 'Si vous ne sélectionnez pas de fichier, le manuel actuel ne sera pas modifié',
|
||||
'Current instruction manual' => 'Manuel d\'utilisation actuel',
|
||||
'No instruction manual available' => 'Aucun manuel d\'utilisation disponible',
|
||||
'The current instruction manual will be deleted when you save the equipment' => 'Le manuel d\'utilisation actuel sera supprimé lors de la sauvegarde de cet équipement',
|
||||
'No picture available' => 'Aucune photo disponible',
|
||||
'Filter by product group' => 'Filtrer par groupe de produits',
|
||||
'Presets for new products' => 'Modèle pour les nouveaux produits',
|
||||
'Included recipes' => 'Recettes incluses',
|
||||
'A recipe is required' => 'Une recette est requise',
|
||||
'Add included recipe' => 'Ajouter une recette incluse',
|
||||
'Edit included recipe' => 'Supprimer une recette incluse',
|
||||
'Group' => 'Groupe',
|
||||
'This will be used as a headline to group ingredients together' => 'Cela sera utilisé comme titre pour regrouper les ingrédients ensemble',
|
||||
'Journal' => 'Journal',
|
||||
'Stock journal' => 'Journal du stock',
|
||||
'Filter by product' => 'Filtrer par produit',
|
||||
'Booking time' => 'Temps de réservation',
|
||||
'Booking type' => 'Type de réservation',
|
||||
'Undo booking' => 'Annuler la réservation',
|
||||
'Undone on' => 'Annulé le',
|
||||
'Batteries journal' => 'Journal des batteries',
|
||||
'Filter by battery' => 'Filtrer par batterie',
|
||||
'Undo charge cycle' => 'Annuler le cycle de charge',
|
||||
'Undo chore execution' => 'Annuler la réalisation de la corvée',
|
||||
'Chore execution successfully undone' => 'La réalisation de la corvée a bien été annulée',
|
||||
'Undo' => 'Annuler',
|
||||
'Booking successfully undone' => 'Réservation annulée',
|
||||
'Charge cycle successfully undone' => 'Le cycle de charge a bien été annulé',
|
||||
'This cannot be negative and must be an integral number' => 'Ne peut être négatif et doit être un nombre entier',
|
||||
'Disable stock fulfillment checking for this ingredient' => 'Désactiver la vérification du stock pour cet ingrédient',
|
||||
'Add all list items to stock' => 'Ajouter toute la liste dans le stock',
|
||||
'Add #3 #1 of #2 to stock' => 'Ajouter #3 #1 de #2 au stock',
|
||||
'Adding shopping list item #1 of #2' => 'Ajout du produit #1 sur #2 de la liste de courses',
|
||||
'Use a specific stock item' => 'Utiliser un objet spécifique du stock',
|
||||
'The first item in this list would be picked by the default rule which is "First expiring first, then first in first out"' => 'Le premier élément de cette liste sera sélectionné par la règle par défaut qui est "Le premier arrivant à péremption en premier, puis premier entré premier sorti"',
|
||||
'Mark #3 #1 of #2 as open' => 'Indiquer #3 #1 de #2 comme ouvert',
|
||||
'When a product was marked as opened, the best before date will be replaced by today + this amount of days (a value of 0 disables this)' => 'Quand un produit est marqué comme ouvert, la date de péremption sera remplacée par la date du jour + ce nombre de jours (une valeur de 0 désactive ce changement)',
|
||||
'Default best before days after opened' => 'Date de péremption en jours par défaut après ouverture',
|
||||
'Marked #1 #2 of #3 as opened' => '#1 #2 de #3 indiqués comme ouverts',
|
||||
'Mark as opened' => 'Indiquer comme ouvert',
|
||||
'Expires on #1; Bought on #2' => 'Périme le #1; Acheté le #2',
|
||||
'Not opened' => 'Non ouvert',
|
||||
'Opened' => 'Ouvert',
|
||||
'Mark #3 #1 of #2 as open' => 'Indiquer #3 #1 de #2 comme ouvert',
|
||||
'#1 opened' => '#1 ouvert',
|
||||
'Product expires' => 'Expiration du produit',
|
||||
'Task due' => 'Tâche à réaliser',
|
||||
'Chore due' => 'Corvée à réaliser',
|
||||
'Battery charge cycle due' => 'Rechargement à réaliser',
|
||||
'Show clock in header' => 'Afficher l\'horloge dans l\'en-tête',
|
||||
'Stock settings' => 'Paramètres du stock',
|
||||
'Shopping list to stock workflow' => 'Transition de la liste de courses vers le stock',
|
||||
'Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default best before days" set' => 'Réaliser automatiquement les achats en utilisant le dernier prix connu et la quantité indiquée dans la liste, si le premier a une date de péremption par défaut renseignée',
|
||||
'Skip' => 'Passer'
|
||||
);
|
@@ -1,193 +0,0 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Stock overview' => 'Dispensa',
|
||||
'#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',
|
||||
'Chores overview' => 'Riepilogo delle abitudini',
|
||||
'Batteries overview' => 'Riepilogo delle batterie',
|
||||
'Purchase' => 'Acquisti',
|
||||
'Consume' => 'Consumi',
|
||||
'Inventory' => 'Inventario',
|
||||
'Shopping list' => 'Lista della spesa',
|
||||
'Chore tracking' => 'Dati abitudini',
|
||||
'Battery tracking' => 'Dati batterie',
|
||||
'Products' => 'Prodotti',
|
||||
'Locations' => 'Posizioni',
|
||||
'Quantity units' => 'Unità di misura',
|
||||
'Chores' => 'Abitudini',
|
||||
'Batteries' => 'Batterie',
|
||||
'Chore' => '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',
|
||||
'Chore 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 chore' => 'Aggiungi abitudine',
|
||||
'Used in' => 'Usato in',
|
||||
'Create battery' => 'Aggiungi batteria',
|
||||
'Edit battery' => 'Modifica batteria',
|
||||
'Edit chore' => '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 chore "#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 chore 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 chores are due to be done within the next #2 days' => '#1 abitudini da eseguire entro #2 giorni',
|
||||
'#1 chores 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 chore #1 on #2' => 'Esecuzione dell\'abitudine #1 registrata il #2',
|
||||
'Tracked charge cycle 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 chore #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 chore' => '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',
|
||||
'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"}}',
|
||||
'summernote_locale' => 'it-IT',
|
||||
|
||||
//Demo data
|
||||
'Cookies' => 'Biscotti',
|
||||
'Chocolate' => 'Cioccolato',
|
||||
'Pantry' => 'Vorratskammer',
|
||||
'Candy cupboard' => 'Süßigkeitenschrank',
|
||||
'Tinned food cupboard' => 'Konservenschrank',
|
||||
'Fridge' => 'Kühlschrank',
|
||||
'Piece' => 'Pezzo',
|
||||
'Pieces' => 'Pezzi',
|
||||
'Pack' => 'Pacco',
|
||||
'Packs' => 'Pacchi',
|
||||
'Glass' => 'Bicchiere',
|
||||
'Glasses' => 'Bicchieri',
|
||||
'Tin' => 'Scatola',
|
||||
'Tins' => 'Scatole',
|
||||
'Can' => 'Lattina',
|
||||
'Cans' => 'Lattine',
|
||||
'Bunch' => 'Cespo',
|
||||
'Bunches' => 'Cespi',
|
||||
'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'
|
||||
);
|
6
localization/it/chore_types.php
Normal file
6
localization/it/chore_types.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'manually' => 'Manualmente',
|
||||
'dynamic-regular' => 'Regolatore dinamico'
|
||||
);
|
10
localization/it/component_translations.php
Normal file
10
localization/it/component_translations.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'timeago_locale' => 'it',
|
||||
'timeago_nan' => 'NaN anni fa',
|
||||
'moment_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"}}',
|
||||
'summernote_locale' => 'it-IT',
|
||||
'fullcalendar_locale' => 'fr'
|
||||
);
|
87
localization/it/demo_data.php
Normal file
87
localization/it/demo_data.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Cookies' => 'Biscotti',
|
||||
'Chocolate' => 'Cioccolato',
|
||||
'Pantry' => 'Vorratskammer',
|
||||
'Candy cupboard' => 'Süßigkeitenschrank',
|
||||
'Tinned food cupboard' => 'Konservenschrank',
|
||||
'Fridge' => 'Kühlschrank',
|
||||
'Piece' => 'Pezzo',
|
||||
'Pieces' => 'Pezzi',
|
||||
'Pack' => 'Pacco',
|
||||
'Packs' => 'Pacchi',
|
||||
'Glass' => 'Bicchiere',
|
||||
'Glasses' => 'Bicchieri',
|
||||
'Tin' => 'Scatola',
|
||||
'Tins' => 'Scatole',
|
||||
'Can' => 'Lattina',
|
||||
'Cans' => 'Lattine',
|
||||
'Bunch' => 'Cespo',
|
||||
'Bunches' => 'Cespi',
|
||||
'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',
|
||||
'Lawn mowed in the garden' => 'Prato falciato nel giardino',
|
||||
'Some good snacks' => 'Some good snacks',
|
||||
'Pizza dough' => 'Pizza dough',
|
||||
'Sieved tomatoes' => 'Sieved tomatoes',
|
||||
'Salami' => 'Salami',
|
||||
'Toast' => 'Toast',
|
||||
'Minced meat' => 'Minced meat',
|
||||
'Pizza' => 'Pizza',
|
||||
'Spaghetti bolognese' => 'Spaghetti bolognese',
|
||||
'Sandwiches' => 'Sandwiches',
|
||||
'English' => 'English',
|
||||
'German' => 'German',
|
||||
'Italian' => 'Italian',
|
||||
'Demo in different language' => 'Demo in different language',
|
||||
'This is the note content of the recipe ingredient' => 'This is the note content of the recipe ingredient',
|
||||
'Demo User' => 'Demo User',
|
||||
'Gram' => 'Gram',
|
||||
'Grams' => 'Grams',
|
||||
'Flour' => 'Flour',
|
||||
'Pancakes' => 'Pancakes',
|
||||
'Sugar' => 'Sugar',
|
||||
'Home' => 'Home',
|
||||
'Life' => 'Life',
|
||||
'Projects' => 'Projects',
|
||||
'Repair the garage door' => 'Repair the garage door',
|
||||
'Fork and improve grocy' => 'Fork and improve grocy',
|
||||
'Find a solution for what to do when I forget the door keys' => 'Find a solution for what to do when I forget the door keys',
|
||||
'Sweets' => 'Sweets',
|
||||
'Bakery products' => 'Bakery products',
|
||||
'Tinned food' => 'Tinned food',
|
||||
'Butchery products' => 'Butchery products',
|
||||
'Vegetables/Fruits' => 'Vegetables/Fruits',
|
||||
'Refrigerated products' => 'Refrigerated products',
|
||||
'Coffee machine' => 'Coffee machine',
|
||||
'Dishwasher' => 'Dishwasher',
|
||||
'Liter' => 'Liter',
|
||||
'Liters' => 'Litri',
|
||||
'Bottle' => 'Bottiglia',
|
||||
'Bottles' => 'Bottiglie',
|
||||
'Milk' => 'Latte',
|
||||
'Chocolate sauce' => 'Salsa al cioccolato',
|
||||
'Milliliters' => 'Millilitri',
|
||||
'Milliliter' => 'Millilitro',
|
||||
'Bottom' => 'Parte inferiore',
|
||||
'Topping' => 'Topping',
|
||||
'French' => 'French'
|
||||
);
|
8
localization/it/stock_transaction_types.php
Normal file
8
localization/it/stock_transaction_types.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'purchase' => 'Purchase',
|
||||
'consume' => 'Consume',
|
||||
'inventory-correction' => 'Inventory correction',
|
||||
'product-opened' => 'Product opened'
|
||||
);
|
330
localization/it/strings.php
Normal file
330
localization/it/strings.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Stock overview' => 'Dispensa',
|
||||
'#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',
|
||||
'Chores overview' => 'Riepilogo delle abitudini',
|
||||
'Batteries overview' => 'Riepilogo delle batterie',
|
||||
'Purchase' => 'Acquisti',
|
||||
'Consume' => 'Consumi',
|
||||
'Inventory' => 'Inventario',
|
||||
'Shopping list' => 'Lista della spesa',
|
||||
'Chore tracking' => 'Dati abitudini',
|
||||
'Battery tracking' => 'Dati batterie',
|
||||
'Products' => 'Prodotti',
|
||||
'Locations' => 'Posizioni',
|
||||
'Quantity units' => 'Unità di misura',
|
||||
'Chores' => 'Abitudini',
|
||||
'Batteries' => 'Batterie',
|
||||
'Chore' => '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',
|
||||
'Chore 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 chore' => 'Aggiungi abitudine',
|
||||
'Used in' => 'Usato in',
|
||||
'Create battery' => 'Aggiungi batteria',
|
||||
'Edit battery' => 'Modifica batteria',
|
||||
'Edit chore' => '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 chore "#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 chore 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 chores are due to be done within the next #2 days' => '#1 abitudini da eseguire entro #2 giorni',
|
||||
'#1 chores 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 chore #1 on #2' => 'Esecuzione dell\'abitudine #1 registrata il #2',
|
||||
'Tracked charge cycle 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 chore #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 chore' => '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',
|
||||
'A best before date is required and must be later than today' => 'A best before date is required and must be later than today',
|
||||
'Settings' => 'Settings',
|
||||
'This can only be before now' => 'This can only be before now',
|
||||
'Calendar' => 'Calendar',
|
||||
'Recipes' => 'Recipes',
|
||||
'Edit recipe' => 'Edit recipe',
|
||||
'New recipe' => 'New recipe',
|
||||
'Ingredients list' => 'Ingredients list',
|
||||
'Add recipe ingredient' => 'Add recipe ingredient',
|
||||
'Edit recipe ingredient' => 'Edit recipe ingredient',
|
||||
'Are you sure to delete recipe "#1"?' => 'Are you sure to delete recipe "#1"?',
|
||||
'Are you sure to delete recipe ingredient "#1"?' => 'Are you sure to delete recipe ingredient "#1"?',
|
||||
'Are you sure to empty the shopping list?' => 'Are you sure to empty the shopping list?',
|
||||
'Clear list' => 'Clear list',
|
||||
'Requirements fulfilled' => 'Requirements fulfilled',
|
||||
'Put missing products on shopping list' => 'Put missing products on shopping list',
|
||||
'Not enough in stock, #1 ingredients missing' => 'Not enough in stock, #1 ingredients missing',
|
||||
'Enough in stock' => 'Enough in stock',
|
||||
'Not enough in stock, #1 ingredients missing but already on the shopping list' => 'Not enough in stock, #1 ingredients missing but already on the shopping list',
|
||||
'Expand to fullscreen' => 'Expand to fullscreen',
|
||||
'Ingredients' => 'Ingredients',
|
||||
'Preparation' => 'Preparation',
|
||||
'Recipe' => 'Recipe',
|
||||
'Not enough in stock, #1 missing, #2 already on shopping list' => 'Not enough in stock, #1 missing, #2 already on shopping list',
|
||||
'Show notes' => 'Show notes',
|
||||
'Put missing amount on shopping list' => 'Put missing amount on shopping list',
|
||||
'Are you sure to put all missing ingredients for recipe "#1" on the shopping list?' => 'Are you sure to put all missing ingredients for recipe "#1" on the shopping list?',
|
||||
'Added for recipe #1' => 'Added for recipe #1',
|
||||
'Manage users' => 'Manage users',
|
||||
'User' => 'User',
|
||||
'Users' => 'Users',
|
||||
'Are you sure to delete user "#1"?' => 'Are you sure to delete user "#1"?',
|
||||
'Create user' => 'Create user',
|
||||
'Edit user' => 'Edit user',
|
||||
'First name' => 'First name',
|
||||
'Last name' => 'Last name',
|
||||
'A username is required' => 'A username is required',
|
||||
'Confirm password' => 'Confirm password',
|
||||
'Passwords do not match' => 'Passwords do not match',
|
||||
'Change password' => 'Change password',
|
||||
'Done by' => 'Done by',
|
||||
'Last done by' => 'Last done by',
|
||||
'Unknown' => 'Unknown',
|
||||
'Filter by chore' => 'Filter by chore',
|
||||
'Chores journal' => 'Chores journal',
|
||||
'0 means suggestions for the next charge cycle are disabled' => '0 means suggestions for the next charge cycle are disabled',
|
||||
'Charge cycle interval (days)' => 'Charge cycle interval (days)',
|
||||
'Last price' => 'Last price',
|
||||
'Price history' => 'Price history',
|
||||
'No price history available' => 'No price history available',
|
||||
'Price' => 'Price',
|
||||
'in #1 per purchase quantity unit' => 'in #1 per purchase quantity unit',
|
||||
'The price cannot be lower than #1' => 'The price cannot be lower than #1',
|
||||
'#1 product expires within the next #2 days' => '#1 product expires within the next #2 days',
|
||||
'#1 product is already expired' => '#1 product is already expired',
|
||||
'#1 product is below defined min. stock amount' => '#1 product is below defined min. stock amount',
|
||||
'Unit' => 'Unit',
|
||||
'Units' => 'Units',
|
||||
'#1 chore is due to be done within the next #2 days' => '#1 chore is due to be done within the next #2 days',
|
||||
'#1 chore is overdue to be done' => '#1 chore is overdue to be done',
|
||||
'#1 battery is due to be charged within the next #2 days' => '#1 battery is due to be charged within the next #2 days',
|
||||
'#1 battery is overdue to be charged' => '#1 battery is overdue to be charged',
|
||||
'#1 unit was automatically added and will apply in addition to the amount entered here' => '#1 unit was automatically added and will apply in addition to the amount entered here',
|
||||
'in singular form' => 'in singular form',
|
||||
'in plural form' => 'in plural form',
|
||||
'Never expires' => 'Never expires',
|
||||
'This cannot be lower than #1' => 'This cannot be lower than #1',
|
||||
'-1 means that this product never expires' => '-1 means that this product never expires',
|
||||
'Quantity unit' => 'Quantity unit',
|
||||
'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Only check if a single unit is in stock (a different quantity can then be used above)',
|
||||
'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?' => 'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?',
|
||||
'Removed all ingredients of recipe "#1" from stock' => 'Removed all ingredients of recipe "#1" from stock',
|
||||
'Consume all ingredients needed by this recipe' => 'Consume all ingredients needed by this recipe',
|
||||
'Click to show technical details' => 'Click to show technical details',
|
||||
'Error while saving, probably this item already exists' => 'Error while saving, probably this item already exists',
|
||||
'Error details' => 'Error details',
|
||||
'Tasks' => 'Tasks',
|
||||
'Show done tasks' => 'Show done tasks',
|
||||
'Task' => 'Task',
|
||||
'Due' => 'Due',
|
||||
'Assigned to' => 'Assigned to',
|
||||
'Mark task "#1" as completed' => 'Mark task "#1" as completed',
|
||||
'Uncategorized' => 'Uncategorized',
|
||||
'Task categories' => 'Task categories',
|
||||
'Create task' => 'Create task',
|
||||
'A due date is required' => 'A due date is required',
|
||||
'Category' => 'Category',
|
||||
'Edit task' => 'Edit task',
|
||||
'Are you sure to delete task "#1"?' => 'Are you sure to delete task "#1"?',
|
||||
'#1 task is due to be done within the next #2 days' => '#1 task is due to be done within the next #2 days',
|
||||
'#1 tasks are due to be done within the next #2 days' => '#1 tasks are due to be done within the next #2 days',
|
||||
'#1 task is overdue to be done' => '#1 task is overdue to be done',
|
||||
'#1 tasks are overdue to be done' => '#1 tasks are overdue to be done',
|
||||
'Edit task category' => 'Edit task category',
|
||||
'Create task category' => 'Create task category',
|
||||
'Product groups' => 'Product groups',
|
||||
'Ungrouped' => 'Ungrouped',
|
||||
'Create product group' => 'Create product group',
|
||||
'Edit product group' => 'Edit product group',
|
||||
'Product group' => 'Product group',
|
||||
'Are you sure to delete product group "#1"?' => 'Are you sure to delete product group "#1"?',
|
||||
'Stay logged in permanently' => 'Stay logged in permanently',
|
||||
'When not set, you will get logged out at latest after 30 days' => 'When not set, you will get logged out at latest after 30 days',
|
||||
'Filter by status' => 'Filter by status',
|
||||
'Below min. stock amount' => 'Below min. stock amount',
|
||||
'Expiring soon' => 'Expiring soon',
|
||||
'Already expired' => 'Already expired',
|
||||
'Due soon' => 'Due soon',
|
||||
'Overdue' => 'Overdue',
|
||||
'View settings' => 'View settings',
|
||||
'Auto reload on external changes' => 'Auto reload on external changes',
|
||||
'Enable night mode' => 'Enable night mode',
|
||||
'Auto enable in time range' => 'Auto enable in time range',
|
||||
'From' => 'From',
|
||||
'in format' => 'in format',
|
||||
'To' => 'To',
|
||||
'Time range goes over midnight' => 'Time range goes over midnight',
|
||||
'Product picture' => 'Product picture',
|
||||
'No file selected' => 'No file selected',
|
||||
'If you don\'t select a file, the current picture will not be altered' => 'If you don\'t select a file, the current picture will not be altered',
|
||||
'Current picture' => 'Current picture',
|
||||
'Delete' => 'Delete',
|
||||
'The current picture will be deleted when you save the product' => 'The current picture will be deleted when you save the product',
|
||||
'Select file' => 'Select file',
|
||||
'Image of product #1' => 'Image of product #1',
|
||||
'This product cannot be deleted because it is in stock, please remove the stock amount first.' => 'This product cannot be deleted because it is in stock, please remove the stock amount first.',
|
||||
'Delete not possible' => 'Delete not possible',
|
||||
'Equipment' => 'Equipment',
|
||||
'Instruction manual' => 'Instruction manual',
|
||||
'The selected equipment has no instruction manual' => 'The selected equipment has no instruction manual',
|
||||
'Notes' => 'Notes',
|
||||
'Edit equipment' => 'Edit equipment',
|
||||
'Create equipment' => 'Create equipment',
|
||||
'If you don\'t select a file, the current instruction manual will not be altered' => 'If you don\'t select a file, the current instruction manual will not be altered',
|
||||
'Current instruction manual' => 'Current instruction manual',
|
||||
'No instruction manual available' => 'No instruction manual available',
|
||||
'The current instruction manual will be deleted when you save the equipment' => 'The current instruction manual will be deleted when you save the equipment',
|
||||
'No picture available' => 'No picture available',
|
||||
'Filter by product group' => 'Filter by product group',
|
||||
'Presets for new products' => 'Presets for new products',
|
||||
'Included recipes' => 'Included recipes',
|
||||
'A recipe is required' => 'A recipe is required',
|
||||
'Add included recipe' => 'Add included recipe',
|
||||
'Edit included recipe' => 'Edit included recipe',
|
||||
'Group' => 'Group',
|
||||
'This will be used as a headline to group ingredients together' => 'This will be used as a headline to group ingredients together',
|
||||
'Journal' => 'Journal',
|
||||
'Stock journal' => 'Stock journal',
|
||||
'Filter by product' => 'Filter by product',
|
||||
'Booking time' => 'Booking time',
|
||||
'Booking type' => 'Booking type',
|
||||
'Undo booking' => 'Undo booking',
|
||||
'Undone on' => 'Undone on',
|
||||
'Batteries journal' => 'Batteries journal',
|
||||
'Filter by battery' => 'Filter by battery',
|
||||
'Undo charge cycle' => 'Undo charge cycle',
|
||||
'Undo chore execution' => 'Undo chore execution',
|
||||
'Chore execution successfully undone' => 'Chore execution successfully undone',
|
||||
'Undo' => 'Undo',
|
||||
'Booking successfully undone' => 'Booking successfully undone',
|
||||
'Charge cycle successfully undone' => 'Charge cycle successfully undone',
|
||||
'This cannot be negative and must be an integral number' => 'This cannot be negative and must be an integral number',
|
||||
'Disable stock fulfillment checking for this ingredient' => 'Disable stock fulfillment checking for this ingredient',
|
||||
'Add all list items to stock' => 'Add all list items to stock',
|
||||
'Add #3 #1 of #2 to stock' => 'Add #3 #1 of #2 to stock',
|
||||
'Adding shopping list item #1 of #2' => 'Adding shopping list item #1 of #2',
|
||||
'Use a specific stock item' => 'Use a specific stock item',
|
||||
'The first item in this list would be picked by the default rule which is "First expiring first, then first in first out"' => 'The first item in this list would be picked by the default rule which is "First expiring first, then first in first out"',
|
||||
'Mark #3 #1 of #2 as open' => 'Mark #3 #1 of #2 as open',
|
||||
'When a product was marked as opened, the best before date will be replaced by today + this amount of days (a value of 0 disables this)' => 'When a product was marked as opened, the best before date will be replaced by today + this amount of days (a value of 0 disables this)',
|
||||
'Default best before days after opened' => 'Default best before days after opened',
|
||||
'Marked #1 #2 of #3 as opened' => 'Marked #1 #2 of #3 as opened',
|
||||
'Mark as opened' => 'Mark as opened',
|
||||
'Expires on #1; Bought on #2' => 'Expires on #1; Bought on #2',
|
||||
'Not opened' => 'Not opened',
|
||||
'Opened' => 'Opened',
|
||||
'Mark #3 #1 of #2 as open' => 'Mark #3 #1 of #2 as open',
|
||||
'#1 opened' => '#1 opened',
|
||||
'Product expires' => 'Product expires',
|
||||
'Task due' => 'Task due',
|
||||
'Chore due' => 'Chore due',
|
||||
'Battery charge cycle due' => 'Battery charge cycle due',
|
||||
'Show clock in header' => 'Show clock in header',
|
||||
'Stock settings' => 'Stock settings',
|
||||
'Shopping list to stock workflow' => 'Shopping list to stock workflow',
|
||||
'Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default best before days" set' => 'Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default best before days" set',
|
||||
'Skip' => 'Skip'
|
||||
);
|
6
localization/no/chore_types.php
Normal file
6
localization/no/chore_types.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'manually' => 'Manuel',
|
||||
'dynamic-regular' => 'Automatisk'
|
||||
);
|
10
localization/no/component_translations.php
Normal file
10
localization/no/component_translations.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'timeago_locale' => 'no',
|
||||
'timeago_nan' => 'for NaN År',
|
||||
'moment_locale' => 'nb',
|
||||
'datatables_localization' => '{"sEmptyTable":"Det finnes ingen data i tabellen","sInfo":"_START_ fra _END_ til _TOTAL_ skriv","sInfoEmpty":"Ingen data tilgjengelign","sInfoFiltered":"(filtrert fra _MAX_ skriv)","sInfoPostFix":"","sInfoThousands":".","sLengthMenu":"_MENU_ registrer deg","sLoadingRecords":"Laster ..","sProcessing":"Vennligst vent ..","sSearch":"Søk","sZeroRecords":"Ingen oppføringer tilgjengelig","oPaginate":{"sFirst":"Første","sPrevious":"Bakover","sNext":"Neste","sLast":"Siste"},"oAria":{"sSortAscending":": Sortér stigende","sSortDescending":": Sortér synkende"},"select":{"rows":{"0":"klikk på en linje for å velge","1":"1 linje valgt","_":"%d linger valgt"}},"buttons":{"print":"Print","colvis":"Søyle","copy":"Kopi","copyTitle":"Kopier til utklippstavlen","copyKeys":"Trykk <i>ctrl</i> eller <i>⌘</i> + <i>C</i> for å kopiere tabell<br> til utklipptavlen.<br><br>For å avbryte, klikke på meldingen eller trykk på ESC.","copySuccess":{"1":"1 Kolonne kopiert","_":"%d kolonne kopiert"}}}',
|
||||
'summernote_locale' => 'nb-NO',
|
||||
'fullcalendar_locale' => 'nb'
|
||||
);
|
87
localization/no/demo_data.php
Normal file
87
localization/no/demo_data.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Cookies' => 'Cookies',
|
||||
'Chocolate' => 'Sjokolade',
|
||||
'Pantry' => 'Spiskammers',
|
||||
'Candy cupboard' => 'Godteriskapet',
|
||||
'Tinned food cupboard' => 'Boksematskapet',
|
||||
'Fridge' => 'Kjøleskapet',
|
||||
'Piece' => 'Ett',
|
||||
'Pieces' => 'Flere',
|
||||
'Pack' => 'Pakke',
|
||||
'Packs' => 'Pakker',
|
||||
'Glass' => 'Glass',
|
||||
'Glasses' => 'Glass',
|
||||
'Tin' => 'Hermetikkboks',
|
||||
'Tins' => 'Hermetikkbokser',
|
||||
'Can' => 'Boks',
|
||||
'Cans' => 'Bokser',
|
||||
'Bunch' => 'Klase',
|
||||
'Bunches' => 'Klaser',
|
||||
'Gummy bears' => 'Vingummibjørner',
|
||||
'Crisps' => 'Chips',
|
||||
'Eggs' => 'Egg',
|
||||
'Noodles' => 'Nuddler',
|
||||
'Pickles' => 'Sur agurk',
|
||||
'Gulash soup' => 'Gulasj suppe',
|
||||
'Yogurt' => 'Yoghurt',
|
||||
'Cheese' => 'Ost',
|
||||
'Cold cuts' => 'Kjøttpålegg',
|
||||
'Paprika' => 'Paprika',
|
||||
'Cucumber' => 'Agurk',
|
||||
'Radish' => 'Reddik',
|
||||
'Tomato' => 'Tomat',
|
||||
'Changed towels in the bathroom' => 'Bytt handklær på badet',
|
||||
'Cleaned the kitchen floor' => 'Vasket kjøkkengulvet',
|
||||
'Warranty ends' => 'Garanti utgår',
|
||||
'TV remote control' => 'Fjernkontroll for TV',
|
||||
'Alarm clock' => 'Alarmklokke',
|
||||
'Heat remote control' => 'Fjernkontroll for termostat',
|
||||
'Lawn mowed in the garden' => 'Kuttet gresset i hagen',
|
||||
'Some good snacks' => 'Noen gode snacks',
|
||||
'Pizza dough' => 'Pizzadeig',
|
||||
'Sieved tomatoes' => 'Tomatpuré',
|
||||
'Salami' => 'Salami',
|
||||
'Toast' => 'Ristet brød',
|
||||
'Minced meat' => 'Kjøttdeig',
|
||||
'Pizza' => 'Pizza',
|
||||
'Spaghetti bolognese' => 'Spaghetti Bolognese',
|
||||
'Sandwiches' => 'Smørbrød',
|
||||
'English' => 'Engelsk',
|
||||
'German' => 'Tysk',
|
||||
'Italian' => 'Italiensk',
|
||||
'Demo in different language' => 'Demo i annet språk',
|
||||
'This is the note content of the recipe ingredient' => 'Dette er notisen for ingrediensen i oppskriften',
|
||||
'Demo User' => 'Demo Bruker',
|
||||
'Gram' => 'Gram',
|
||||
'Grams' => 'Gram',
|
||||
'Flour' => 'Mel',
|
||||
'Pancakes' => 'Pannekaker',
|
||||
'Sugar' => 'Sukker',
|
||||
'Home' => 'Hus',
|
||||
'Life' => 'Livstil',
|
||||
'Projects' => 'Projekter',
|
||||
'Repair the garage door' => 'Reparere garasjedøren',
|
||||
'Fork and improve grocy' => 'Fork og forbedre grocy',
|
||||
'Find a solution for what to do when I forget the door keys' => 'Finne på løsning for hva jeg skal gjøre når jeg mister dørnøklene',
|
||||
'Sweets' => 'Godteri',
|
||||
'Bakery products' => 'Bakevarer',
|
||||
'Tinned food' => 'Boksemat',
|
||||
'Butchery products' => 'Kjøtt/ Ferskvare',
|
||||
'Vegetables/Fruits' => 'Frukt/ Grønnsaker',
|
||||
'Refrigerated products' => 'Frysedisk',
|
||||
'Coffee machine' => 'Kaffetrakter',
|
||||
'Dishwasher' => 'Oppvaskmaskin',
|
||||
'Liter' => 'Liter',
|
||||
'Liters' => 'Liter',
|
||||
'Bottle' => 'Flaske',
|
||||
'Bottles' => 'Flasker',
|
||||
'Milk' => 'Melk',
|
||||
'Chocolate sauce' => 'Sjokoladesaus',
|
||||
'Milliliters' => 'Milliliter',
|
||||
'Milliliter' => 'Milliliter',
|
||||
'Bottom' => 'Bunn',
|
||||
'Topping' => 'Topping',
|
||||
'French' => 'Fransk'
|
||||
);
|
8
localization/no/stock_transaction_types.php
Normal file
8
localization/no/stock_transaction_types.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'purchase' => 'Innkjøp',
|
||||
'consume' => 'Forbruke produkt',
|
||||
'inventory-correction' => 'Korreksjon av husholdningsantall ',
|
||||
'product-opened' => 'Produkt åpnet'
|
||||
);
|
@@ -9,14 +9,14 @@ return array(
|
||||
'Amount' => 'Antall',
|
||||
'Next best before date' => 'Kommende best før dato',
|
||||
'Logout' => 'Logg ut',
|
||||
'Chores overview' => 'Oversikt Husarbeid',
|
||||
'Batteries overview' => 'Oversikt Batteri',
|
||||
'Chores overview' => 'Oversikt husarbeid',
|
||||
'Batteries overview' => 'Oversikt batteri',
|
||||
'Purchase' => 'Innkjøp',
|
||||
'Consume' => 'Forbruk produkt',
|
||||
'Inventory' => 'Endre Husholdning',
|
||||
'Inventory' => 'Endre husholdning',
|
||||
'Shopping list' => 'Handleliste',
|
||||
'Chore tracking' => 'Logge Husarbeid',
|
||||
'Battery tracking' => 'Batteri Ladesyklus',
|
||||
'Chore tracking' => 'Logge husarbeid',
|
||||
'Battery tracking' => 'Batteri ladesyklus',
|
||||
'Products' => 'Produkter',
|
||||
'Locations' => 'Lokasjoner',
|
||||
'Quantity units' => 'Forpakning',
|
||||
@@ -41,9 +41,9 @@ return array(
|
||||
'New amount' => 'Nytt antall',
|
||||
'Note' => 'Info',
|
||||
'Tracked time' => 'Tid utført/ ladet',
|
||||
'Chore overview' => 'Oversikt Husarbeid',
|
||||
'Chore overview' => 'Oversikt husarbeid',
|
||||
'Tracked count' => 'Antall utførelser/ ladninger',
|
||||
'Battery overview' => 'Batteri Oversikt',
|
||||
'Battery overview' => 'Batteri oversikt',
|
||||
'Charge cycles count' => 'Antall ladesykluser',
|
||||
'Create shopping list item' => 'Opprett handelisteoppføring',
|
||||
'Edit shopping list item' => 'Endre på handlelistoppføring',
|
||||
@@ -52,15 +52,15 @@ return array(
|
||||
'Add' => 'Legg til',
|
||||
'Name' => 'Navn',
|
||||
'Location' => 'Lokasjon',
|
||||
'Min. stock amount' => 'Minimums antall for husholdingen',
|
||||
'QU purchase' => 'FPK innkjøp',
|
||||
'QU stock' => 'FPK husholdning',
|
||||
'QU factor' => 'FPK faktor',
|
||||
'Min. stock amount' => 'Minimumsantall for husholdningen',
|
||||
'QU purchase' => 'Forpakingsfaktor innkjøp',
|
||||
'QU stock' => 'Forpakingsfaktor husholdning',
|
||||
'QU factor' => 'Forpakingsfaktor',
|
||||
'Description' => 'Beskrivelse',
|
||||
'Create product' => 'Opprett produkt',
|
||||
'Barcode(s)' => 'Strekkode(r)',
|
||||
'Minimum stock amount' => 'Minimums antall for husholdningen',
|
||||
'Default best before days' => 'Standard antall dager best før',
|
||||
'Minimum stock amount' => 'Minimumsantall for husholdningen',
|
||||
'Default best before days' => 'Standard for antall dager best før',
|
||||
'Quantity unit purchase' => 'Forpakning kjøpt',
|
||||
'Quantity unit stock' => 'Forpakning husholdning',
|
||||
'Factor purchase to stock quantity unit' => 'Innkjøpsfaktor for forpakning',
|
||||
@@ -81,32 +81,32 @@ return array(
|
||||
'This will apply to added products' => 'Dette vil gjelde for produkt som blir lagt til',
|
||||
'never' => 'aldri',
|
||||
'Add products that are below defined min. stock amount' => 'Legg til produkt som er under minimumsnivå for husholdningen',
|
||||
'For purchases this amount of days will be added to today for the best before date suggestion' => 'For innkjøp vil dette antallet dager legges til bestfør forslaget',
|
||||
'For purchases this amount of days will be added to today for the best before date suggestion' => 'Når innkjøp gjøres vil dette bli brukt som antall dager "best før"',
|
||||
'This means 1 #1 purchased will be converted into #2 #3 in stock' => 'Dette betyr at 1 #1 innkjøp vil bli omgjort til #2 #3 husholdning',
|
||||
'Login' => 'Logg inn',
|
||||
'Username' => 'Brukernavn',
|
||||
'Password' => 'Passord',
|
||||
'Invalid credentials, please try again' => 'Feil brukernavn og/eller passord, prøv igjen',
|
||||
'Are you sure to delete battery "#1"?' => 'Er du sikker du ønsker å slette Batteri "#1"?',
|
||||
'Are you sure to delete battery "#1"?' => 'Er du sikker du ønsker å slette batteri "#1"?',
|
||||
'Yes' => 'Ja',
|
||||
'No' => 'Nei',
|
||||
'Are you sure to delete chore "#1"?' => 'Er du sikker på du ønsker å slette husarbeid oppgave "#1"?',
|
||||
'"#1" could not be resolved to a product, how do you want to proceed?' => '"#1" kunne ikke bli tildelt et produkt, hvordan ønsker du å fortsette?',
|
||||
'Create or assign product' => 'Opprett eller tildel til produkt',
|
||||
'Create or assign product' => 'Opprett eller tildel til et produkt',
|
||||
'Cancel' => 'Avbryt',
|
||||
'Add as new product' => 'Legg til som nytt produkt',
|
||||
'Add as barcode to existing product' => 'Legg til strekkode til allerede eksisterende produkt',
|
||||
'Add as new product and prefill barcode' => 'Legg til som nytt produkt med forhåndsutfylt strekkode',
|
||||
'Add as new product and prefill barcode' => 'Legg til som nytt produkt med forhåndsfylt strekkode',
|
||||
'Are you sure to delete quantity unit "#1"?' => 'Er du sikker du ønsker å slette forpakning "#1"?',
|
||||
'Are you sure to delete product "#1"?' => 'Er du sikker du ønsker å slette produkt "#1"?',
|
||||
'Are you sure to delete location "#1"?' => 'Er du sikker du ønsker å slette lokasjon "#1"?',
|
||||
'Manage API keys' => 'Administrer API-Keys',
|
||||
'REST API & data model documentation' => 'REST-API & Datamodell Dokumentasjon',
|
||||
'API keys' => 'API-Keys',
|
||||
'Create new API key' => 'Opprett ny API-Key',
|
||||
'API key' => 'API-Key',
|
||||
'Expires' => 'Går ut',
|
||||
'Created' => 'Opprettet',
|
||||
'REST API & data model documentation' => 'REST-API & Datamodell Dokumentasjon',
|
||||
'API keys' => 'API-Keys',
|
||||
'Create new API key' => 'Opprett ny API-Key',
|
||||
'API key' => 'API-Key',
|
||||
'Expires' => 'Går ut',
|
||||
'Created' => 'Opprettet',
|
||||
'This product is not in stock' => 'Dette produktet er ikke i husholdningen',
|
||||
'This means #1 will be added to stock' => 'Dette betyr at #1 vil bli lagt til i husholdningen',
|
||||
'This means #1 will be removed from stock' => 'Dette betyr at #1 vil bli fjernet fra husholdningen',
|
||||
@@ -114,12 +114,12 @@ return array(
|
||||
'Removed #1 #2 of #3 from stock' => 'Fjernet #1 #2 #3 fra husholdningen',
|
||||
'About grocy' => 'Om Grocy',
|
||||
'Close' => 'Lukk',
|
||||
'#1 batteries are due to be charged within the next #2 days' => '#1 Batteri må lades innen de #2 neste dagene',
|
||||
'#1 batteries are overdue to be charged' => '#1 Batteri har gått over fristen for å bli ladet opp',
|
||||
'#1 chores are due to be done within the next #2 days' => '#1 husarbeid(s) oppgave(r) skal gjøres inne de #2 neste dagene',
|
||||
'#1 chores are overdue to be done' => '#1 husarbeid(s) oppgave(r) har gått over fristen for utførelse',
|
||||
'#1 batteries are due to be charged within the next #2 days' => '#1 batteri må lades innen de #2 neste dagene',
|
||||
'#1 batteries are overdue to be charged' => '#1 batteri har gått over fristen for å bli ladet opp',
|
||||
'#1 chores are due to be done within the next #2 days' => '#1 husarbeids oppgaver skal gjøres inne de #2 neste dagene',
|
||||
'#1 chores are overdue to be done' => '#1 husarbeids oppgaver har gått over fristen for utførelse',
|
||||
'Released on' => 'Utgitt',
|
||||
'Consume #3 #1 of #2' => 'Forbruk #3 #1 #2',
|
||||
'Consume #3 #1 of #2' => 'Forbruk #3 #1 av #2',
|
||||
'Added #1 #2 of #3 to stock' => '#1 #2 #3 lagt til i husholdningen',
|
||||
'Stock amount of #1 is now #2 #3' => 'Husholdning antall #1 er nå #2 #3',
|
||||
'Tracked execution of chore #1 on #2' => 'Utførte husarbeid oppgave "#1" den #2',
|
||||
@@ -127,12 +127,12 @@ return array(
|
||||
'Consume all #1 which are currently in stock' => 'Forbruk alle #1 som er i husholdningen',
|
||||
'All' => 'Alle',
|
||||
'Track charge cycle of battery #1' => '#1 ladet',
|
||||
'Track execution of chore #1' => 'Utfør husarbeid oppgave #1',
|
||||
'Track execution of chore #1' => 'Utfør husarbeidsoppgave "#1"',
|
||||
'Filter by location' => 'Filtrér etter lokasjon',
|
||||
'Search' => 'Søk',
|
||||
'Not logged in' => 'Ikke logget inn',
|
||||
'You have to select a product' => 'Du må velge et produkt',
|
||||
'You have to select a chore' => 'Du må velge en husarbeid oppgave',
|
||||
'You have to select a chore' => 'Du må velge en husarbeids oppgave',
|
||||
'You have to select a battery' => 'Du må velge et batteri',
|
||||
'A name is required' => 'Vennligst fyll inn et navn',
|
||||
'A location is required' => 'En lokasjon kreves',
|
||||
@@ -143,7 +143,7 @@ return array(
|
||||
'A best before date is required and must be later than today' => 'En best før dato kreves, denne må være senere enn i dag',
|
||||
'Settings' => 'Innstillinger',
|
||||
'This can only be before now' => 'Dette kan kun være før nå',
|
||||
'Calendar' => 'Kalender',
|
||||
'Calendar' => 'Kalender',
|
||||
'Recipes' => 'Oppskrifter',
|
||||
'Edit recipe' => 'Endre oppskrift',
|
||||
'New recipe' => 'Ny oppskrift',
|
||||
@@ -153,12 +153,12 @@ return array(
|
||||
'Are you sure to delete recipe "#1"?' => 'Er du sikker du ønsker å slette oppskrift "#1"?',
|
||||
'Are you sure to delete recipe ingredient "#1"?' => 'Er du sikker du ønsker å slette ingrediens "#1" fra oppskriften?',
|
||||
'Are you sure to empty the shopping list?' => 'Er du sikker du ønsker å slette handlelisten?',
|
||||
'Clear list' => 'Tøm liste',
|
||||
'Clear list' => 'Slett handleliste',
|
||||
'Requirements fulfilled' => 'Har jeg alt jeg trenger for denne oppskriften?',
|
||||
'Put missing products on shopping list' => 'Legg manglende produkter til handlelisten',
|
||||
'Not enough in stock, #1 ingredients missing' => 'Ikke nok i husholdningen, #1 ingredienser mangler',
|
||||
'Not enough in stock, #1 ingredients missing' => 'Ikke nok i husholdningen, #1 ingrediens(er) mangler',
|
||||
'Enough in stock' => 'Nok i husholdningen',
|
||||
'Not enough in stock, #1 ingredients missing but already on the shopping list' => 'Ikke nok i husholdningen, #1 ingrediens mangler, men denne er på handelisten',
|
||||
'Not enough in stock, #1 ingredients missing but already on the shopping list' => 'Ikke nok i husholdningen, #1 ingrediens(er) mangler, men denne/disse er på handlelisten',
|
||||
'Expand to fullscreen' => 'Full skjerm',
|
||||
'Ingredients' => 'Ingredienser',
|
||||
'Preparation' => 'Forberedelse / Slik gjør du',
|
||||
@@ -166,7 +166,7 @@ return array(
|
||||
'Not enough in stock, #1 missing, #2 already on shopping list' => 'Ikke nok i husholdningen, mangler #1, er #2 på handlelisten',
|
||||
'Show notes' => 'Vis notater',
|
||||
'Put missing amount on shopping list' => 'Legg manglende til handlelisten',
|
||||
'Are you sure to put all missing ingredients for recipe "#1" on the shopping list?' => 'Er du sikker du ønsker å legge alle manglende ingredienser til oppskrift "#1"?',
|
||||
'Are you sure to put all missing ingredients for recipe "#1" on the shopping list?' => 'Er du sikker du ønsker å legge alle manglende ingredienser for oppskrift "#1" i handlelisten?',
|
||||
'Added for recipe #1' => 'Lagt til fra oppskrift "#1"',
|
||||
'Manage users' => 'Administrer brukere',
|
||||
'User' => 'Bruker',
|
||||
@@ -184,12 +184,12 @@ return array(
|
||||
'Last done by' => 'Sist utført av',
|
||||
'Unknown' => 'Ukjent',
|
||||
'Filter by chore' => 'Filtrér husarbeid',
|
||||
'Chores analysis' => 'Statistikk husarbeid',
|
||||
'0 means suggestions for the next charge cycle are disabled' => '0 betyr neste ladesyklus er avslått',
|
||||
'Charge cycle interval (days)' => 'Ladesyklysintervall (Dager)',
|
||||
'Last price' => 'Siste pris',
|
||||
'Price history' => 'Prishistorikk',
|
||||
'No price history available' => 'Ingen prishistorikk tilgjengelig',
|
||||
'Chores journal' => 'Statistikk husarbeid',
|
||||
'0 means suggestions for the next charge cycle are disabled' => '0 betyr neste ladesyklus er avslått',
|
||||
'Charge cycle interval (days)' => 'Ladesyklysintervall (dager)',
|
||||
'Last price' => 'Siste pris',
|
||||
'Price history' => 'Prishistorikk',
|
||||
'No price history available' => 'Ingen prishistorikk tilgjengelig',
|
||||
'Price' => 'Pris',
|
||||
'in #1 per purchase quantity unit' => 'I #1 per kjøpt forpakning ',
|
||||
'The price cannot be lower than #1' => 'Prisen kan ikke være lavere enn #1',
|
||||
@@ -198,8 +198,8 @@ return array(
|
||||
'#1 product is below defined min. stock amount' => '#1 Produkt er under minimums husholdningsnivå',
|
||||
'Unit' => 'Enhet',
|
||||
'Units' => 'Enheter',
|
||||
'#1 chore is due to be done within the next #2 days' => '#1 husarbeid oppgave(r) skal gjøres inne de #2 neste dagene',
|
||||
'#1 chore is overdue to be done' => '#1 husarbeid(s) oppgave(r) har gått over fristen for utførelse',
|
||||
'#1 chore is due to be done within the next #2 days' => '#1 husarbeid oppgave skal gjøres inne de #2 neste dagene',
|
||||
'#1 chore is overdue to be done' => '#1 husarbeid oppgave har gått over fristen for utførelse',
|
||||
'#1 battery is due to be charged within the next #2 days' => '#1 Batteri må lades innen #2 dager',
|
||||
'#1 battery is overdue to be charged' => '#1 Batteri har gått over fristen for å lades',
|
||||
'#1 unit was automatically added and will apply in addition to the amount entered here' => '#1 enhet ble automatisk lagt til i tillegg til hva som blir skrevet inn her',
|
||||
@@ -207,10 +207,10 @@ return array(
|
||||
'in plural form' => 'I flertall',
|
||||
'Never expires' => 'Går ikke ut på dato',
|
||||
'This cannot be lower than #1' => 'Dette kan ikke være lavere enn #1',
|
||||
'-1 means that this product never expires' => '-1 Betyr at dette produktet aldri går ut på dato',
|
||||
'-1 means that this product never expires' => 'Ved å skrive -1 vil produktet ikke gå ut på dato',
|
||||
'Quantity unit' => 'Forpakning',
|
||||
'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Huk av hvis du ønsker å bruke mindre enn forpakningsstørrelse i husholdningen',
|
||||
'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?' => 'Er du sikker du ønsker å forbruke alle ingredienser for "#1" oppskriften? (Ingredienser merket med "bruke mindre enn forpakningsstørrelse i husholdningen" blir ignorert',
|
||||
'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Ønsker du å bruke mindre/større enn normal forpakningsstørrelse?',
|
||||
'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?' => 'Er du sikker du ønsker å forbruke alle ingredienser for "#1" oppskriften? (Ingredienser merket med "Ønsker du å bruke mindre/større enn normal forpakningsstørrelse??" blir ignorert',
|
||||
'Removed all ingredients of recipe "#1" from stock' => 'Fjern alle ingredienser for "#1" oppskriften fra husholdningen.',
|
||||
'Consume all ingredients needed by this recipe' => 'Forbruk alle ingredienser for denne oppskriften',
|
||||
'Click to show technical details' => 'Klikk for å vise teknisk informasjon',
|
||||
@@ -236,7 +236,7 @@ return array(
|
||||
'Edit task category' => 'Endre oppgave kategori',
|
||||
'Create task category' => 'Opprett oppgave kategori',
|
||||
'Product groups' => 'Produktgrupper',
|
||||
'Ungrouped' => 'Ikke i grupper',
|
||||
'Ungrouped' => 'Mangler gruppe',
|
||||
'Create product group' => 'Opprett produkt gruppe',
|
||||
'Edit product group' => 'Endre produkt gruppe',
|
||||
'Product group' => 'Produktgruppe',
|
||||
@@ -258,108 +258,73 @@ return array(
|
||||
'To' => 'Til',
|
||||
'Time range goes over midnight' => 'Tidsrommet går over midnatt',
|
||||
'Product picture' => 'Produktbilde',
|
||||
'No file selected' => 'Ingen fil merket',
|
||||
'If you don\'t select a file, the current picture will not be altered' => 'Hvis du ikke velger et bilde, vil nåværende bilde ikke bli endret',
|
||||
'Current picture' => 'Nåværende bilde',
|
||||
'No file selected' => 'Produktbilde ikke valgt',
|
||||
'If you don\'t select a file, the current picture will not be altered' => 'Hvis du ikke velger et bilde, vil nåværende produktbilde bli værende',
|
||||
'Current picture' => 'Nåværende produktbilde',
|
||||
'Delete' => 'Slett',
|
||||
'The current picture will be deleted when you save the product' => 'Nåværende bilde vil bli slettet når du lagrer produktet',
|
||||
'Select file' => 'Velg fil',
|
||||
'The current picture will be deleted when you save the product' => 'Nåværende produktbilde vil bli slettet når du lagrer produktet',
|
||||
'Select file' => 'Velg produktbilde',
|
||||
'Image of product #1' => 'Bilde av produkt #1',
|
||||
'This product cannot be deleted because it is in stock, please remove the stock amount first.' => 'Dette produktet kan ikke slettes fordi det er gjenværende produkter i husholdningen',
|
||||
'Delete not possible' => 'Ikke mulig å slette',
|
||||
'Equipment' => 'Utstyr',
|
||||
'Equipment' => 'Instruksjonmanualer',
|
||||
'Instruction manual' => 'Instruksjonsmanual',
|
||||
'The selected equipment has no instruction manual' => 'Merket utstyr har ingen instruksjonsmanual',
|
||||
'Notes' => 'Notater',
|
||||
'Edit equipment' => 'Endre utstyr',
|
||||
'Create equipment' => 'Opprett utstyr',
|
||||
'Edit equipment' => 'Endre instruksjonmanualer for utstyr',
|
||||
'Create equipment' => 'Opprett instruksjonmanualer for utstyr',
|
||||
'If you don\'t select a file, the current instruction manual will not be altered' => 'Hvis du ikke velger en instruksjonsmanual, vil nåværende instruksjonsmanual ikke bli endret',
|
||||
'Current instruction manual' => 'Nåværende instruksjonsmanual',
|
||||
'No instruction manual available' => 'Ingen instruksjonsmanual tilgjengelig',
|
||||
'The current instruction manual will be deleted when you save the equipment' => 'Nåværende instruksjonsmanual vil bli slettet når du lagrer utstyret',
|
||||
|
||||
//Constants
|
||||
'manually' => 'Manuel',
|
||||
'dynamic-regular' => 'Automatisk',
|
||||
|
||||
//Technical component translations
|
||||
'timeago_locale' => 'no',
|
||||
'timeago_nan' => 'for NaN År',
|
||||
'moment_locale' => 'nb',
|
||||
'datatables_localization' => '{"sEmptyTable":"Det finnes ingen data i tabellen","sInfo":"_START_ fra _END_ til _TOTAL_ skriv","sInfoEmpty":"Ingen data tilgjengelign","sInfoFiltered":"(filtrert fra _MAX_ skriv)","sInfoPostFix":"","sInfoThousands":".","sLengthMenu":"_MENU_ registrer deg","sLoadingRecords":"Laster ..","sProcessing":"Vennligst vent ..","sSearch":"Søk","sZeroRecords":"Ingen oppføringer tilgjengelig","oPaginate":{"sFirst":"Første","sPrevious":"Bakover","sNext":"Neste","sLast":"Siste"},"oAria":{"sSortAscending":": Sortér stigende","sSortDescending":": Sortér synkende"},"select":{"rows":{"0":"klikk på en linje for å velge","1":"1 linje valgt","_":"%d linger valgt"}},"buttons":{"print":"Print","colvis":"Søyle","copy":"Kopi","copyTitle":"Kopier til utklippstavlen","copyKeys":"Trykk <i>ctrl</i> eller <i>⌘</i> + <i>C</i> for å kopiere tabell<br> til utklipptavlen.<br><br>For å avbryte, klikke på meldingen eller trykk på ESC.","copySuccess":{"1":"1 Kolonne kopiert","_":"%d kolonne kopiert"}}}',
|
||||
'summernote_locale' => 'nb-NO',
|
||||
|
||||
//Demo data
|
||||
'Cookies' => 'Cookies',
|
||||
'Chocolate' => 'Sjokolade',
|
||||
'Pantry' => 'Spiskammers',
|
||||
'Candy cupboard' => 'Godteriskapet',
|
||||
'Tinned food cupboard' => 'Boksematskapet',
|
||||
'Fridge' => 'Kjøleskapet',
|
||||
'Piece' => 'Ett',
|
||||
'Pieces' => 'Flere',
|
||||
'Pack' => 'Pakke',
|
||||
'Packs' => 'Pakker',
|
||||
'Glass' => 'Glass',
|
||||
'Glasses' => 'Glass',
|
||||
'Tin' => 'Hermetikkboks',
|
||||
'Tins' => 'Hermetikkbokser',
|
||||
'Can' => 'Boks',
|
||||
'Cans' => 'Bokser',
|
||||
'Bunch' => 'Klase',
|
||||
'Bunches' => 'Klaser',
|
||||
'Gummy bears' => 'Vingummibjørner',
|
||||
'Crisps' => 'Chips',
|
||||
'Eggs' => 'Egg',
|
||||
'Noodles' => 'Nuddler',
|
||||
'Pickles' => 'Sur agurk',
|
||||
'Gulash soup' => 'Gulasj suppe',
|
||||
'Yogurt' => 'Yoghurt',
|
||||
'Cheese' => 'Ost',
|
||||
'Cold cuts' => 'Kjøttpålegg',
|
||||
'Paprika' => 'Paprika',
|
||||
'Cucumber' => 'Agurk',
|
||||
'Radish' => 'Reddik',
|
||||
'Tomato' => 'Tomat',
|
||||
'Changed towels in the bathroom' => 'Bytt handklær på badet',
|
||||
'Cleaned the kitchen floor' => 'Vasket kjøkkengulvet',
|
||||
'Warranty ends' => 'Garanti utgår',
|
||||
'TV remote control' => 'Fjernkontroll for TV',
|
||||
'Alarm clock' => 'Alarmklokke',
|
||||
'Heat remote control' => 'Fjernkontroll for termostat',
|
||||
'Lawn mowed in the garden' => 'Kuttet gresset i hagen',
|
||||
'Some good snacks' => 'Noen gode snacks',
|
||||
'Pizza dough' => 'Pizzadeig',
|
||||
'Sieved tomatoes' => 'Tomatpuré',
|
||||
'Salami' => 'Salami',
|
||||
'Toast' => 'Ristet brød',
|
||||
'Minced meat' => 'Kjøttdeig',
|
||||
'Pizza' => 'Pizza',
|
||||
'Spaghetti bolognese' => 'Spaghetti Bolognese',
|
||||
'Sandwiches' => 'Smørbrød',
|
||||
'English' => 'Engelsk',
|
||||
'German' => 'Tysk',
|
||||
'Italian' => 'Italiensk',
|
||||
'Demo in different language' => 'Demo i annet språk',
|
||||
'This is the note content of the recipe ingredient' => 'Dette er notisen for ingrediensen i oppskriften',
|
||||
'Demo User' => 'Demo Bruker',
|
||||
'Gram' => 'Gram',
|
||||
'Grams' => 'Gram',
|
||||
'Flour' => 'Mel',
|
||||
'Pancakes' => 'Pannekaker',
|
||||
'Sugar' => 'Sukker',
|
||||
'Home' => 'Hus',
|
||||
'Life' => 'Livstil',
|
||||
'Projects' => 'Projekter',
|
||||
'Repair the garage door' => 'Reparere garasjedøren',
|
||||
'Fork and improve grocy' => 'Fork og forbedre grocy',
|
||||
'Find a solution for what to do when I forget the door keys' => 'Finne på løsning for hva jeg skal gjøre når jeg mister dørnøklene',
|
||||
'Sweets' => 'Godteri',
|
||||
'Bakery products' => 'Produkt fra bakeren ',
|
||||
'Tinned food' => 'Boksemat',
|
||||
'Butchery products' => 'Produkt fra slakteren',
|
||||
'Vegetables/Fruits' => 'Frukt/ Grønnsaker',
|
||||
'Refrigerated products' => 'Kjølte produkter'
|
||||
'Coffee machine' => 'Kaffetrakter',
|
||||
'Dishwasher' => 'Oppvaskmaskin'
|
||||
'No picture available' => 'Ingen bilde tilgjengelig',
|
||||
'Filter by product group' => 'Filtrér etter produktgruppe',
|
||||
'Presets for new products' => 'Standard for nye produkter',
|
||||
'Included recipes' => 'Inkludert oppskrift',
|
||||
'A recipe is required' => 'En oppskrift kreves',
|
||||
'Add included recipe' => 'Legg til inkludert oppskrift',
|
||||
'Edit included recipe' => 'Endre inkludert oppskrift',
|
||||
'Group' => 'Gruppe',
|
||||
'This will be used as a headline to group ingredients together' => 'Dette vil bli brukt som overskrift for gruppering av ingredienser',
|
||||
'Journal' => 'Logg',
|
||||
'Stock journal' => 'Husholdningslogg',
|
||||
'Filter by product' => 'Filtrér etter produkt',
|
||||
'Booking time' => 'Tid logget',
|
||||
'Booking type' => 'Booking type',
|
||||
'Undo booking' => 'Angre booking',
|
||||
'Undone on' => 'Angret den',
|
||||
'Batteries journal' => 'Batterilogg',
|
||||
'Filter by battery' => 'Filtrér etter batteri',
|
||||
'Undo charge cycle' => 'Angre ladesyklus',
|
||||
'Undo chore execution' => 'Fjerne utførelse av husarbeidsoppgave',
|
||||
'Chore execution successfully undone' => 'Husarbeid fjernet',
|
||||
'Undo' => 'Angre',
|
||||
'Booking successfully undone' => 'Booking fjernet',
|
||||
'Charge cycle successfully undone' => 'Ladesyklus fjernet',
|
||||
'This cannot be negative and must be an integral number' => 'Tallet kan ikke være negativ og må være et helt tall',
|
||||
'Disable stock fulfillment checking for this ingredient' => 'Ikke bruk husholdningsjekk for denne ingrediensen ',
|
||||
'Add all list items to stock' => 'Legg alle produktene i listen til husholdningen',
|
||||
'Add #3 #1 of #2 to stock' => 'Legg til #3 #1 av #2 til husholdningen',
|
||||
'Adding shopping list item #1 of #2' => 'Legger til produkt #1 av #2 fra handlelisten',
|
||||
'Use a specific stock item' => 'Velg et bestemt produkt',
|
||||
'The first item in this list would be picked by the default rule which is "First expiring first, then first in first out"' => 'Første produkt på listen vil bli konsumert først i henhold til standard regelen. "Går ut på dato først. Deretter først inn, først ut".',
|
||||
'Mark #3 #1 of #2 as open' => 'Merk #3 #1 av #2 som åpnet',
|
||||
'When a product was marked as opened, the best before date will be replaced by today + this amount of days (a value of 0 disables this)' => 'Når et produkt blir merket som åpnet endres best før datoen fra i dag + dette antallet av dager. (Et 0 vil deaktivere dette)',
|
||||
'Default best before days after opened' => 'Standard best før dager etter åpnet',
|
||||
'Marked #1 #2 of #3 as opened' => 'Merket #1 #2 av #3 som åpnet',
|
||||
'Mark as opened' => 'Merk som åpnet',
|
||||
'Expires on #1; Bought on #2' => 'Går ut på dato #1; Kjøpt #2',
|
||||
'Not opened' => 'Ikke åpnet',
|
||||
'Opened' => 'Åpnet',
|
||||
'Mark #3 #1 of #2 as open' => 'Merk #3 #1 av #2 som åpnet',
|
||||
'#1 opened' => '#1 åpnet',
|
||||
'Product expires' => 'Produkt går ut på dato',
|
||||
'Task due' => 'Tidsfrist for oppgave',
|
||||
'Chore due' => 'Tidsfrist for husarbeid',
|
||||
'Battery charge cycle due' => 'Batteri må lades',
|
||||
'Show clock in header' => 'Vis klokken på toppen av siden',
|
||||
'Stock settings' => 'Husholdningsinnstillinger',
|
||||
'Shopping list to stock workflow' => 'Arbeidsflyt fra handleliste til husholding',
|
||||
'Automatically do the booking using the last price and the amount of the shopping list item, if the product has "Default best before days" set' => 'Legg produkter automatisk til fra handlelisten. Dette vil bruke sist innkjøpspris og forutsetter at "Standard for antall dager best før" er satt',
|
||||
'Skip' => 'Hopp'
|
||||
);
|
7
migrations/0042.sql
Normal file
7
migrations/0042.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TRIGGER cascade_change_qu_id_stock AFTER UPDATE ON products
|
||||
BEGIN
|
||||
UPDATE recipes_pos
|
||||
SET qu_id = (SELECT qu_id_stock FROM products WHERE id = NEW.id)
|
||||
WHERE product_id IN (SELECT id FROM products WHERE id = NEW.id)
|
||||
AND only_check_single_unit_in_stock = 0;
|
||||
END;
|
43
migrations/0043.sql
Normal file
43
migrations/0043.sql
Normal file
@@ -0,0 +1,43 @@
|
||||
CREATE TABLE recipes_nestings (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
recipe_id INTEGER NOT NULL,
|
||||
includes_recipe_id INTEGER NOT NULL,
|
||||
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')),
|
||||
|
||||
UNIQUE(recipe_id, includes_recipe_id)
|
||||
);
|
||||
|
||||
CREATE VIEW recipes_nestings_resolved
|
||||
AS
|
||||
WITH RECURSIVE r1(recipe_id, includes_recipe_id)
|
||||
AS (
|
||||
SELECT id, id
|
||||
FROM recipes
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT rn.recipe_id, r1.includes_recipe_id
|
||||
FROM recipes_nestings rn, r1 r1
|
||||
WHERE rn.includes_recipe_id = r1.recipe_id
|
||||
LIMIT 100 -- This is just a safety limit to prevent infinite loops due to infinite nested recipes
|
||||
)
|
||||
SELECT *
|
||||
FROM r1;
|
||||
|
||||
DROP VIEW recipes_fulfillment_sum;
|
||||
CREATE VIEW recipes_fulfillment_sum
|
||||
AS
|
||||
SELECT
|
||||
r.id AS recipe_id,
|
||||
IFNULL(MIN(rf.need_fulfilled), 1) AS need_fulfilled,
|
||||
IFNULL(MIN(rf.need_fulfilled_with_shopping_list), 1) AS need_fulfilled_with_shopping_list,
|
||||
(SELECT COUNT(*) FROM recipes_fulfillment WHERE recipe_id IN (SELECT includes_recipe_id FROM recipes_nestings_resolved rnr2 WHERE rnr2.recipe_id = r.id) AND need_fulfilled = 0 AND recipe_pos_id IS NOT NULL) AS missing_products_count
|
||||
FROM recipes r
|
||||
LEFT JOIN recipes_nestings_resolved rnr
|
||||
ON r.id = rnr.recipe_id
|
||||
LEFT JOIN recipes_fulfillment rf
|
||||
ON rnr.includes_recipe_id = rf.recipe_id
|
||||
GROUP BY r.id;
|
||||
|
||||
ALTER TABLE recipes_pos
|
||||
ADD ingredient_group TEXT;
|
26
migrations/0044.sql
Normal file
26
migrations/0044.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
ALTER TABLE stock_log
|
||||
ADD undone TINYINT NOT NULL DEFAULT 0 CHECK(undone IN (0, 1));
|
||||
|
||||
UPDATE stock_log
|
||||
SET undone = 0;
|
||||
|
||||
ALTER TABLE stock_log
|
||||
ADD undone_timestamp DATETIME;
|
||||
|
||||
ALTER TABLE chores_log
|
||||
ADD undone TINYINT NOT NULL DEFAULT 0 CHECK(undone IN (0, 1));
|
||||
|
||||
UPDATE chores_log
|
||||
SET undone = 0;
|
||||
|
||||
ALTER TABLE chores_log
|
||||
ADD undone_timestamp DATETIME;
|
||||
|
||||
ALTER TABLE battery_charge_cycles
|
||||
ADD undone TINYINT NOT NULL DEFAULT 0 CHECK(undone IN (0, 1));
|
||||
|
||||
UPDATE battery_charge_cycles
|
||||
SET undone = 0;
|
||||
|
||||
ALTER TABLE battery_charge_cycles
|
||||
ADD undone_timestamp DATETIME;
|
83
migrations/0045.sql
Normal file
83
migrations/0045.sql
Normal file
@@ -0,0 +1,83 @@
|
||||
ALTER TABLE recipes_pos RENAME TO recipes_pos_old;
|
||||
|
||||
CREATE TABLE recipes_pos (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
recipe_id INTEGER NOT NULL,
|
||||
product_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL DEFAULT 0,
|
||||
note TEXT,
|
||||
qu_id INTEGER,
|
||||
only_check_single_unit_in_stock TINYINT NOT NULL DEFAULT 0,
|
||||
ingredient_group TEXT,
|
||||
not_check_stock_fulfillment TINYINT NOT NULL DEFAULT 0,
|
||||
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
|
||||
);
|
||||
|
||||
DROP TRIGGER recipes_pos_qu_id_default;
|
||||
CREATE TRIGGER recipes_pos_qu_id_default AFTER INSERT ON recipes_pos
|
||||
BEGIN
|
||||
UPDATE recipes_pos
|
||||
SET qu_id = (SELECT qu_id_stock FROM products where id = product_id)
|
||||
WHERE qu_id IS NULL
|
||||
AND id = NEW.id;
|
||||
END;
|
||||
|
||||
INSERT INTO recipes_pos
|
||||
(recipe_id, product_id, amount, note, qu_id, only_check_single_unit_in_stock, ingredient_group, row_created_timestamp)
|
||||
SELECT recipe_id, product_id, amount, note, qu_id, only_check_single_unit_in_stock, ingredient_group, row_created_timestamp
|
||||
FROM recipes_pos_old;
|
||||
|
||||
DROP TABLE recipes_pos_old;
|
||||
|
||||
DROP VIEW recipes_fulfillment;
|
||||
CREATE VIEW recipes_fulfillment
|
||||
AS
|
||||
SELECT
|
||||
r.id AS recipe_id,
|
||||
rp.id AS recipe_pos_id,
|
||||
rp.product_id AS product_id,
|
||||
rp.amount AS recipe_amount,
|
||||
IFNULL(sc.amount, 0) AS stock_amount,
|
||||
CASE WHEN IFNULL(sc.amount, 0) >= CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE IFNULL(rp.amount, 0) END THEN 1 ELSE 0 END AS need_fulfilled,
|
||||
CASE WHEN IFNULL(sc.amount, 0) - CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE IFNULL(rp.amount, 0) END < 0 THEN ABS(IFNULL(sc.amount, 0) - CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE IFNULL(rp.amount, 0) END) ELSE 0 END AS missing_amount,
|
||||
IFNULL(sl.amount, 0) AS amount_on_shopping_list,
|
||||
CASE WHEN IFNULL(sc.amount, 0) + IFNULL(sl.amount, 0) >= CASE WHEN rp.only_check_single_unit_in_stock = 1 THEN 1 ELSE IFNULL(rp.amount, 0) END THEN 1 ELSE 0 END AS need_fulfilled_with_shopping_list,
|
||||
rp.qu_id
|
||||
FROM recipes r
|
||||
JOIN recipes_pos rp
|
||||
ON r.id = rp.recipe_id
|
||||
LEFT JOIN (
|
||||
SELECT product_id, SUM(amount + amount_autoadded) AS amount
|
||||
FROM shopping_list
|
||||
GROUP BY product_id) sl
|
||||
ON rp.product_id = sl.product_id
|
||||
LEFT JOIN stock_current sc
|
||||
ON rp.product_id = sc.product_id
|
||||
WHERE rp.not_check_stock_fulfillment = 0
|
||||
|
||||
UNION
|
||||
|
||||
-- Just add all recipe positions which should not be checked against stock with fulfilled need
|
||||
|
||||
SELECT
|
||||
r.id AS recipe_id,
|
||||
rp.id AS recipe_pos_id,
|
||||
rp.product_id AS product_id,
|
||||
rp.amount AS recipe_amount,
|
||||
IFNULL(sc.amount, 0) AS stock_amount,
|
||||
1 AS need_fulfilled,
|
||||
0 AS missing_amount,
|
||||
IFNULL(sl.amount, 0) AS amount_on_shopping_list,
|
||||
1 AS need_fulfilled_with_shopping_list,
|
||||
rp.qu_id
|
||||
FROM recipes r
|
||||
JOIN recipes_pos rp
|
||||
ON r.id = rp.recipe_id
|
||||
LEFT JOIN (
|
||||
SELECT product_id, SUM(amount + amount_autoadded) AS amount
|
||||
FROM shopping_list
|
||||
GROUP BY product_id) sl
|
||||
ON rp.product_id = sl.product_id
|
||||
LEFT JOIN stock_current sc
|
||||
ON rp.product_id = sc.product_id
|
||||
WHERE rp.not_check_stock_fulfillment = 1;
|
38
migrations/0046.sql
Normal file
38
migrations/0046.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
ALTER TABLE stock
|
||||
ADD opened_date DATETIME;
|
||||
|
||||
ALTER TABLE stock_log
|
||||
ADD opened_date DATETIME;
|
||||
|
||||
ALTER TABLE stock
|
||||
ADD open TINYINT NOT NULL DEFAULT 0 CHECK(open IN (0, 1));
|
||||
|
||||
UPDATE stock
|
||||
SET open = 0;
|
||||
|
||||
ALTER TABLE products
|
||||
ADD default_best_before_days_after_open INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
UPDATE products
|
||||
SET default_best_before_days_after_open = 0;
|
||||
|
||||
DROP VIEW stock_current;
|
||||
CREATE VIEW stock_current
|
||||
AS
|
||||
SELECT
|
||||
s.product_id,
|
||||
SUM(s.amount) AS amount,
|
||||
MIN(s.best_before_date) AS best_before_date,
|
||||
IFNULL((SELECT SUM(amount) FROM stock WHERE product_id = s.product_id AND open = 1), 0) AS amount_opened
|
||||
FROM stock s
|
||||
GROUP BY s.product_id
|
||||
|
||||
UNION
|
||||
|
||||
SELECT
|
||||
id,
|
||||
0,
|
||||
null,
|
||||
0
|
||||
FROM stock_missing_products
|
||||
WHERE is_partly_in_stock = 0;
|
@@ -18,6 +18,7 @@
|
||||
"datatables.net-rowgroup-bs4": "^1.0.4",
|
||||
"datatables.net-select": "^1.2.7",
|
||||
"datatables.net-select-bs4": "^1.2.7",
|
||||
"fullcalendar": "^3.9.0",
|
||||
"jquery": "^3.3.1",
|
||||
"jquery-serializejson": "^2.8.1",
|
||||
"jquery-ui-dist": "^1.12.1",
|
||||
@@ -26,7 +27,7 @@
|
||||
"summernote": "^0.8.10",
|
||||
"swagger-ui-dist": "^3.17.3",
|
||||
"tagmanager": "https://github.com/max-favilli/tagmanager.git#3.0.2",
|
||||
"tempusdominus-bootstrap-4": "^5.0.1",
|
||||
"tempusdominus-bootstrap-4": "^5.1.2",
|
||||
"timeago": "^1.6.3",
|
||||
"toastr": "^2.1.4"
|
||||
}
|
||||
|
@@ -72,6 +72,20 @@ button.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.embedded .hide-when-embedded {
|
||||
display: none;
|
||||
}
|
||||
body.embedded.fixed-nav {
|
||||
padding-top: 0;
|
||||
}
|
||||
.embedded .content-wrapper {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Hide the default up/down arrow buttons for number inputs because we use our own buttons in numberpicker */
|
||||
input[type='number'] {
|
||||
-moz-appearance: textfield;
|
||||
@@ -81,12 +95,6 @@ input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.centered-dialog .modal-title,
|
||||
.centered-dialog .modal-body {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* Navigation style customizations */
|
||||
#mainNav {
|
||||
background-color: #e5e5e5 !important;
|
||||
@@ -95,7 +103,8 @@ input::-webkit-inner-spin-button {
|
||||
}
|
||||
|
||||
.navbar-sidenav {
|
||||
overflow: hidden;
|
||||
overflow-x: hidden;
|
||||
overflow-y: overlay;
|
||||
border-top: 2px solid !important;
|
||||
}
|
||||
|
||||
@@ -147,6 +156,18 @@ input::-webkit-inner-spin-button {
|
||||
background-color: #d6d6d6 !important;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.cursor-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cursor-busy {
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
/* Third party component customizations - DataTables */
|
||||
td {
|
||||
vertical-align: middle !important;
|
||||
@@ -194,6 +215,10 @@ td {
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: inherit;
|
||||
}
|
||||
|
||||
/* Third party component customizations - Tempus Dominus */
|
||||
.date-only-datetimepicker .bootstrap-datetimepicker-widget.dropdown-menu {
|
||||
width: auto !important;
|
||||
|
@@ -255,6 +255,26 @@ Grocy.FrontendHelpers.ValidateForm = function(formId)
|
||||
$(form).addClass('was-validated');
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy = function(formId = null)
|
||||
{
|
||||
$("body").addClass("cursor-busy");
|
||||
|
||||
if (formId !== null)
|
||||
{
|
||||
$("#" + formId + " :input").attr("disabled", true);
|
||||
}
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy = function(formId = null)
|
||||
{
|
||||
$("body").removeClass("cursor-busy");
|
||||
|
||||
if (formId !== null)
|
||||
{
|
||||
$("#" + formId + " :input").attr("disabled", false);
|
||||
}
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.ShowGenericError = function(message, exception)
|
||||
{
|
||||
toastr.error(L(message) + '<br><br>' + L('Click to show technical details'), '', {
|
||||
@@ -283,8 +303,13 @@ $("form").on("click", "select", function()
|
||||
$(".user-setting-control").on("change", function()
|
||||
{
|
||||
var element = $(this);
|
||||
var inputType = element.attr("type").toLowerCase();
|
||||
var settingKey = element.attr("data-setting-key");
|
||||
|
||||
var inputType = "unknown";
|
||||
if (typeof element.attr("type") !== typeof undefined && element.attr("type") !== false)
|
||||
{
|
||||
inputType = element.attr("type").toLowerCase();
|
||||
}
|
||||
|
||||
if (inputType === "checkbox")
|
||||
{
|
||||
@@ -338,6 +363,23 @@ ResizeResponsiveEmbeds = function(fillEntireViewport = false)
|
||||
}
|
||||
$(window).on('resize', function()
|
||||
{
|
||||
console.log($("body").hasClass("fullscreen-responsive-embed-active"));
|
||||
ResizeResponsiveEmbeds($("body").hasClass("fullscreen-responsive-embed-active"));
|
||||
ResizeResponsiveEmbeds($("body").hasClass("fullscreen-card"));
|
||||
});
|
||||
$("iframe").on("load", function()
|
||||
{
|
||||
ResizeResponsiveEmbeds($("body").hasClass("fullscreen-card"));
|
||||
});
|
||||
|
||||
function WindowMessageBag(message, payload = null)
|
||||
{
|
||||
var obj = { };
|
||||
obj.Message = message;
|
||||
obj.Payload = payload;
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Add border around anchor link section
|
||||
if (window.location.hash)
|
||||
{
|
||||
$(window.location.hash).addClass("p-2 border border-info rounded");
|
||||
}
|
||||
|
42
public/js/grocy_clock.js
Normal file
42
public/js/grocy_clock.js
Normal file
@@ -0,0 +1,42 @@
|
||||
$("#show-clock-in-header").on("change", function ()
|
||||
{
|
||||
CheckHeaderClockEnabled();
|
||||
});
|
||||
|
||||
function RefreshHeaderClock()
|
||||
{
|
||||
$("#clock-small").text(moment().format("l LT"));
|
||||
$("#clock-big").text(moment().format("LLLL"));
|
||||
}
|
||||
|
||||
Grocy.HeaderClockInterval = null;
|
||||
function CheckHeaderClockEnabled()
|
||||
{
|
||||
// Refresh the clock in the header every second when enabled
|
||||
if (BoolVal(Grocy.UserSettings.show_clock_in_header))
|
||||
{
|
||||
RefreshHeaderClock();
|
||||
$("#clock-container").removeClass("d-none");
|
||||
|
||||
Grocy.HeaderClockInterval = setInterval(function()
|
||||
{
|
||||
RefreshHeaderClock();
|
||||
}, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Grocy.HeaderClockInterval !== null)
|
||||
{
|
||||
clearInterval(Grocy.HeaderClockInterval);
|
||||
Grocy.HeaderClockInterval = null;
|
||||
}
|
||||
|
||||
$("#clock-container").addClass("d-none");
|
||||
}
|
||||
}
|
||||
CheckHeaderClockEnabled();
|
||||
|
||||
if (BoolVal(Grocy.UserSettings.show_clock_in_header))
|
||||
{
|
||||
$("#show-clock-in-header").prop("checked", true);
|
||||
}
|
@@ -22,7 +22,7 @@ setInterval(function()
|
||||
{
|
||||
if (Grocy.IdleTime >= 50)
|
||||
{
|
||||
if (BoolVal(Grocy.UserSettings.auto_reload_on_db_change) && $("form.is-dirty").length === 0)
|
||||
if (BoolVal(Grocy.UserSettings.auto_reload_on_db_change) && $("form.is-dirty").length === 0 && !$("body").hasClass("fullscreen-card"))
|
||||
{
|
||||
window.location.reload();
|
||||
}
|
||||
|
72
public/viewjs/batteriesjournal.js
Normal file
72
public/viewjs/batteriesjournal.js
Normal file
@@ -0,0 +1,72 @@
|
||||
var batteriesJournalTable = $('#batteries-journal-table').DataTable({
|
||||
'paginate': true,
|
||||
'order': [[1, 'desc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false,
|
||||
'colReorder': true,
|
||||
'stateSave': true,
|
||||
'stateSaveParams': function(settings, data)
|
||||
{
|
||||
data.search.search = "";
|
||||
|
||||
data.columns.forEach(column =>
|
||||
{
|
||||
column.search.search = "";
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#battery-filter").on("change", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
var text = $("#battery-filter option:selected").text();
|
||||
if (value === "all")
|
||||
{
|
||||
text = "";
|
||||
}
|
||||
|
||||
batteriesJournalTable.column(1).search(text).draw();
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
batteriesJournalTable.search(value).draw();
|
||||
});
|
||||
|
||||
if (typeof GetUriParam("battery") !== "undefined")
|
||||
{
|
||||
$("#battery-filter").val(GetUriParam("battery"));
|
||||
$("#battery-filter").trigger("change");
|
||||
}
|
||||
|
||||
$(document).on('click', '.undo-battery-execution-button', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var element = $(e.currentTarget);
|
||||
var chargeCycleId = $(e.currentTarget).attr('data-charge-cycle-id');
|
||||
|
||||
Grocy.Api.Get('batteries/undo-charge-cycle/' + chargeCycleId.toString(),
|
||||
function(result)
|
||||
{
|
||||
element.closest("tr").addClass("text-muted");
|
||||
element.parent().siblings().find("span.name-anchor").addClass("text-strike-through").after("<br>" + L("Undone on") + " " + moment().format("YYYY-MM-DD HH:mm:ss") + " <time class='timeago timeago-contextual' datetime='" + moment().format("YYYY-MM-DD HH:mm:ss") + "'></time>");
|
||||
element.closest(".undo-stock-booking-button").addClass("disabled");
|
||||
RefreshContextualTimeago();
|
||||
toastr.success(L("Charge cycle successfully undone"));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
@@ -58,6 +58,8 @@ $(document).on('click', '.track-charge-cycle-button', function(e)
|
||||
// Remove the focus from the current button
|
||||
// to prevent that the tooltip stays until clicked anywhere else
|
||||
document.activeElement.blur();
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
var batteryId = $(e.currentTarget).attr('data-battery-id');
|
||||
var batteryName = $(e.currentTarget).attr('data-battery-name');
|
||||
@@ -102,18 +104,21 @@ $(document).on('click', '.track-charge-cycle-button', function(e)
|
||||
$('#battery-' + batteryId + '-next-charge-time-timeago').attr('datetime', result.next_estimated_charge_time);
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
toastr.success(L('Tracked charge cycle of battery #1 on #2', batteryName, trackedTime));
|
||||
RefreshContextualTimeago();
|
||||
RefreshStatistics();
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
|
@@ -2,28 +2,33 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#battery-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("battery-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/batteries', $('#battery-form').serializeJSON(),
|
||||
Grocy.Api.Post('add-object/batteries', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/batteries');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("battery-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Post('edit-object/batteries/' + Grocy.EditObjectId, $('#battery-form').serializeJSON(),
|
||||
Grocy.Api.Post('edit-object/batteries/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/batteries');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("battery-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
|
@@ -3,6 +3,7 @@
|
||||
e.preventDefault();
|
||||
|
||||
var jsonForm = $('#batterytracking-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("batterytracking-form");
|
||||
|
||||
Grocy.Api.Get('batteries/get-battery-details/' + jsonForm.battery_id,
|
||||
function (batteryDetails)
|
||||
@@ -10,7 +11,8 @@
|
||||
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').find('input').val()));
|
||||
Grocy.FrontendHelpers.EndUiBusy("batterytracking-form");
|
||||
toastr.success(L('Tracked charge cycle of battery #1 on #2', batteryDetails.battery.name, $('#tracked_time').find('input').val()) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoChargeCycle(' + result.charge_cycle_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||
|
||||
$('#battery_id').val('');
|
||||
$('#battery_id_text_input').focus();
|
||||
@@ -22,12 +24,14 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("batterytracking-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("batterytracking-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -86,3 +90,16 @@ $('#tracked_time').find('input').on('keypress', function (e)
|
||||
Grocy.FrontendHelpers.ValidateForm('batterytracking-form');
|
||||
});
|
||||
|
||||
function UndoChargeCycle(chargeCycleId)
|
||||
{
|
||||
Grocy.Api.Get('batteries/undo-charge-cycle/' + chargeCycleId.toString(),
|
||||
function(result)
|
||||
{
|
||||
toastr.success(L("Charge cycle successfully undone"));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
11
public/viewjs/calendar.js
Normal file
11
public/viewjs/calendar.js
Normal file
@@ -0,0 +1,11 @@
|
||||
$("#calendar").fullCalendar({
|
||||
"themeSystem": "bootstrap4",
|
||||
"header": {
|
||||
"left": "month,basicWeek,listWeek",
|
||||
"center": "title",
|
||||
"right": "prev,next"
|
||||
},
|
||||
"weekNumbers": true,
|
||||
"eventLimit": true,
|
||||
"eventSources": fullcalendarEventSources
|
||||
});
|
@@ -2,28 +2,33 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#chore-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("chore-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/chores', $('#chore-form').serializeJSON(),
|
||||
Grocy.Api.Post('add-object/chores', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/chores');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("chore-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Post('edit-object/chores/' + Grocy.EditObjectId, $('#chore-form').serializeJSON(),
|
||||
Grocy.Api.Post('edit-object/chores/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/chores');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("chore-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
|
@@ -1,46 +0,0 @@
|
||||
var choresAnalysisTable = $('#chores-analysis-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'desc']],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false,
|
||||
'colReorder': true,
|
||||
'stateSave': true,
|
||||
'stateSaveParams': function(settings, data)
|
||||
{
|
||||
data.search.search = "";
|
||||
|
||||
data.columns.forEach(column =>
|
||||
{
|
||||
column.search.search = "";
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#chore-filter").on("change", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
var text = $("#chore-filter option:selected").text();
|
||||
if (value === "all")
|
||||
{
|
||||
text = "";
|
||||
}
|
||||
|
||||
choresAnalysisTable.column(0).search(text).draw();
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
choresAnalysisTable.search(value).draw();
|
||||
});
|
||||
|
||||
if (typeof GetUriParam("chore") !== "undefined")
|
||||
{
|
||||
$("#chore-filter").val(GetUriParam("chore"));
|
||||
$("#chore-filter").trigger("change");
|
||||
}
|
72
public/viewjs/choresjournal.js
Normal file
72
public/viewjs/choresjournal.js
Normal file
@@ -0,0 +1,72 @@
|
||||
var choresJournalTable = $('#chores-journal-table').DataTable({
|
||||
'paginate': true,
|
||||
'order': [[1, 'desc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false,
|
||||
'colReorder': true,
|
||||
'stateSave': true,
|
||||
'stateSaveParams': function(settings, data)
|
||||
{
|
||||
data.search.search = "";
|
||||
|
||||
data.columns.forEach(column =>
|
||||
{
|
||||
column.search.search = "";
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#chore-filter").on("change", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
var text = $("#chore-filter option:selected").text();
|
||||
if (value === "all")
|
||||
{
|
||||
text = "";
|
||||
}
|
||||
|
||||
choresJournalTable.column(1).search(text).draw();
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
choresJournalTable.search(value).draw();
|
||||
});
|
||||
|
||||
if (typeof GetUriParam("chore") !== "undefined")
|
||||
{
|
||||
$("#chore-filter").val(GetUriParam("chore"));
|
||||
$("#chore-filter").trigger("change");
|
||||
}
|
||||
|
||||
$(document).on('click', '.undo-chore-execution-button', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var element = $(e.currentTarget);
|
||||
var executionId = $(e.currentTarget).attr('data-execution-id');
|
||||
|
||||
Grocy.Api.Get('chores/undo-chore-execution/' + executionId.toString(),
|
||||
function(result)
|
||||
{
|
||||
element.closest("tr").addClass("text-muted");
|
||||
element.parent().siblings().find("span.name-anchor").addClass("text-strike-through").after("<br>" + L("Undone on") + " " + moment().format("YYYY-MM-DD HH:mm:ss") + " <time class='timeago timeago-contextual' datetime='" + moment().format("YYYY-MM-DD HH:mm:ss") + "'></time>");
|
||||
element.closest(".undo-stock-booking-button").addClass("disabled");
|
||||
RefreshContextualTimeago();
|
||||
toastr.success(L("Chore execution successfully undone"));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
@@ -58,6 +58,8 @@ $(document).on('click', '.track-chore-button', function(e)
|
||||
// Remove the focus from the current button
|
||||
// to prevent that the tooltip stays until clicked anywhere else
|
||||
document.activeElement.blur();
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
var choreId = $(e.currentTarget).attr('data-chore-id');
|
||||
var choreName = $(e.currentTarget).attr('data-chore-name');
|
||||
@@ -102,18 +104,21 @@ $(document).on('click', '.track-chore-button', function(e)
|
||||
$('#chore-' + choreId + '-next-execution-time-timeago').attr('datetime', result.next_estimated_execution_time);
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
toastr.success(L('Tracked execution of chore #1 on #2', choreName, trackedTime));
|
||||
RefreshContextualTimeago();
|
||||
RefreshStatistics();
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
|
@@ -3,6 +3,7 @@
|
||||
e.preventDefault();
|
||||
|
||||
var jsonForm = $('#choretracking-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("choretracking-form");
|
||||
|
||||
Grocy.Api.Get('chores/get-chore-details/' + jsonForm.chore_id,
|
||||
function (choreDetails)
|
||||
@@ -10,7 +11,8 @@
|
||||
Grocy.Api.Get('chores/track-chore-execution/' + jsonForm.chore_id + '?tracked_time=' + Grocy.Components.DateTimePicker.GetValue() + "&done_by=" + Grocy.Components.UserPicker.GetValue(),
|
||||
function(result)
|
||||
{
|
||||
toastr.success(L('Tracked execution of chore #1 on #2', choreDetails.chore.name, Grocy.Components.DateTimePicker.GetValue()));
|
||||
Grocy.FrontendHelpers.EndUiBusy("choretracking-form");
|
||||
toastr.success(L('Tracked execution of chore #1 on #2', choreDetails.chore.name, Grocy.Components.DateTimePicker.GetValue()) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoChoreExecution(' + result.chore_execution_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||
|
||||
$('#chore_id').val('');
|
||||
$('#chore_id_text_input').focus();
|
||||
@@ -21,12 +23,14 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("choretracking-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("choretracking-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -82,3 +86,17 @@ Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e)
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm('choretracking-form');
|
||||
});
|
||||
|
||||
function UndoChoreExecution(executionId)
|
||||
{
|
||||
Grocy.Api.Get('chores/undo-chore-execution/' + executionId.toString(),
|
||||
function(result)
|
||||
{
|
||||
toastr.success(L("Chore execution successfully undone"));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@@ -10,6 +10,9 @@ Grocy.Components.BatteryCard.Refresh = function(batteryId)
|
||||
$('#batterycard-battery-last-charged').text((batteryDetails.last_charged || L('never')));
|
||||
$('#batterycard-battery-last-charged-timeago').text($.timeago(batteryDetails.last_charged || ''));
|
||||
$('#batterycard-battery-charge-cycles-count').text((batteryDetails.charge_cycles_count || '0'));
|
||||
|
||||
$('#batterycard-battery-edit-button').attr("href", U("/battery/" + batteryDetails.battery.id.toString()));
|
||||
$('#batterycard-battery-edit-button').removeClass("disabled");
|
||||
|
||||
EmptyElementWhenMatches('#batterycard-battery-last-charged-timeago', L('timeago_nan'));
|
||||
},
|
||||
|
@@ -10,6 +10,9 @@ Grocy.Components.ChoreCard.Refresh = function(choreId)
|
||||
$('#chorecard-chore-last-tracked-timeago').text($.timeago(choreDetails.last_tracked || ''));
|
||||
$('#chorecard-chore-tracked-count').text((choreDetails.tracked_count || '0'));
|
||||
$('#chorecard-chore-last-done-by').text((choreDetails.last_done_by.display_name || L('Unknown')));
|
||||
|
||||
$('#chorecard-chore-edit-button').attr("href", U("/chore/" + choreDetails.chore.id.toString()));
|
||||
$('#chorecard-chore-edit-button').removeClass("disabled");
|
||||
|
||||
EmptyElementWhenMatches('#chorecard-chore-last-tracked-timeago', L('timeago_nan'));
|
||||
},
|
||||
|
@@ -24,6 +24,23 @@ Grocy.Components.DateTimePicker.SetValue = function(value)
|
||||
}
|
||||
}
|
||||
|
||||
Grocy.Components.DateTimePicker.Clear = function()
|
||||
{
|
||||
$(".datetimepicker").datetimepicker("destroy");
|
||||
Grocy.Components.DateTimePicker.Init();
|
||||
|
||||
Grocy.Components.DateTimePicker.GetInputElement().val("");
|
||||
|
||||
// "Click" the shortcut checkbox when the desired value is
|
||||
// not the shortcut value and it is currently set
|
||||
value = "";
|
||||
var shortcutValue = $("#datetimepicker-shortcut").data("datetimepicker-shortcut-value");
|
||||
if (value != shortcutValue && $("#datetimepicker-shortcut").is(":checked"))
|
||||
{
|
||||
$("#datetimepicker-shortcut").click();
|
||||
}
|
||||
}
|
||||
|
||||
var startDate = null;
|
||||
if (Grocy.Components.DateTimePicker.GetInputElement().data('init-with-now') === true)
|
||||
{
|
||||
@@ -40,46 +57,50 @@ if (Grocy.Components.DateTimePicker.GetInputElement().data('limit-end-to-now') =
|
||||
limitDate = moment();
|
||||
}
|
||||
|
||||
$('.datetimepicker').datetimepicker(
|
||||
Grocy.Components.DateTimePicker.Init = function()
|
||||
{
|
||||
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) { }
|
||||
}
|
||||
});
|
||||
$('.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.Init();
|
||||
|
||||
Grocy.Components.DateTimePicker.GetInputElement().on('keyup', function(e)
|
||||
{
|
||||
@@ -189,7 +210,15 @@ Grocy.Components.DateTimePicker.GetInputElement().on('input', function(e)
|
||||
|
||||
$('.datetimepicker').on('update.datetimepicker', function(e)
|
||||
{
|
||||
console.log("update");
|
||||
Grocy.Components.DateTimePicker.GetInputElement().trigger('input');
|
||||
Grocy.Components.DateTimePicker.GetInputElement().trigger('change');
|
||||
});
|
||||
|
||||
$('.datetimepicker').on('hide.datetimepicker', function(e)
|
||||
{
|
||||
Grocy.Components.DateTimePicker.GetInputElement().trigger('input');
|
||||
Grocy.Components.DateTimePicker.GetInputElement().trigger('change');
|
||||
});
|
||||
|
||||
$("#datetimepicker-shortcut").on("click", function()
|
||||
|
@@ -6,6 +6,7 @@ Grocy.Components.ProductCard.Refresh = function(productId)
|
||||
function(productDetails)
|
||||
{
|
||||
var stockAmount = productDetails.stock_amount || '0';
|
||||
var stockAmountOpened = productDetails.stock_amount_opened || '0';
|
||||
$('#productcard-product-name').text(productDetails.product.name);
|
||||
$('#productcard-product-stock-amount').text(stockAmount);
|
||||
$('#productcard-product-stock-qu-name').text(productDetails.quantity_unit_stock.name);
|
||||
@@ -15,6 +16,18 @@ Grocy.Components.ProductCard.Refresh = function(productId)
|
||||
$('#productcard-product-last-used').text((productDetails.last_used || L('never')).substring(0, 10));
|
||||
$('#productcard-product-last-used-timeago').text($.timeago(productDetails.last_used || ''));
|
||||
|
||||
if (stockAmountOpened > 0)
|
||||
{
|
||||
$('#productcard-product-stock-opened-amount').text(L('#1 opened', stockAmountOpened));
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#productcard-product-stock-opened-amount').text("");
|
||||
}
|
||||
|
||||
$('#productcard-product-edit-button').attr("href", U("/product/" + productDetails.product.id.toString()));
|
||||
$('#productcard-product-edit-button').removeClass("disabled");
|
||||
|
||||
if (productDetails.last_price !== null)
|
||||
{
|
||||
$('#productcard-product-last-price').text(Number.parseFloat(productDetails.last_price).toLocaleString() + ' ' + Grocy.Currency);
|
||||
|
@@ -23,7 +23,7 @@ Grocy.Components.ProductPicker.SetValue = function(value)
|
||||
|
||||
Grocy.Components.ProductPicker.InProductAddWorkflow = function()
|
||||
{
|
||||
return typeof GetUriParam('createdproduct') !== "undefined";
|
||||
return typeof GetUriParam('createdproduct') !== "undefined" || typeof GetUriParam('product') !== "undefined";
|
||||
}
|
||||
|
||||
Grocy.Components.ProductPicker.InProductModifyWorkflow = function()
|
||||
@@ -74,6 +74,22 @@ if (typeof prefillProduct !== "undefined")
|
||||
}
|
||||
}
|
||||
|
||||
var prefillProductId = GetUriParam("product");
|
||||
var prefillProductId2 = Grocy.Components.ProductPicker.GetPicker().parent().data('prefill-by-id').toString();
|
||||
if (!prefillProductId2.isEmpty())
|
||||
{
|
||||
prefillProductId = prefillProductId2;
|
||||
}
|
||||
if (typeof prefillProductId !== "undefined")
|
||||
{
|
||||
$('#product_id').val(prefillProductId);
|
||||
$('#product_id').data('combobox').refresh();
|
||||
$('#product_id').trigger('change');
|
||||
|
||||
var nextInputElement = $(Grocy.Components.ProductPicker.GetPicker().parent().data('next-input-selector').toString());
|
||||
nextInputElement.focus();
|
||||
}
|
||||
|
||||
var addBarcode = GetUriParam('addbarcodetoselection');
|
||||
if (addBarcode !== undefined)
|
||||
{
|
||||
|
@@ -3,6 +3,12 @@
|
||||
e.preventDefault();
|
||||
|
||||
var jsonForm = $('#consume-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("consume-form");
|
||||
|
||||
if ($("#use_specific_stock_entry").is(":checked"))
|
||||
{
|
||||
jsonForm.amount = 1;
|
||||
}
|
||||
|
||||
var spoiled = 0;
|
||||
if ($('#spoiled').is(':checked'))
|
||||
@@ -10,13 +16,27 @@
|
||||
spoiled = 1;
|
||||
}
|
||||
|
||||
var apiUrl = 'stock/consume-product/' + jsonForm.product_id + '/' + jsonForm.amount + '?spoiled=' + spoiled;
|
||||
|
||||
if ($("#use_specific_stock_entry").is(":checked"))
|
||||
{
|
||||
apiUrl += "&stock_entry_id=" + jsonForm.specific_stock_entry;
|
||||
}
|
||||
|
||||
Grocy.Api.Get('stock/get-product-details/' + jsonForm.product_id,
|
||||
function (productDetails)
|
||||
function(productDetails)
|
||||
{
|
||||
Grocy.Api.Get('stock/consume-product/' + jsonForm.product_id + '/' + jsonForm.amount + '?spoiled=' + spoiled,
|
||||
Grocy.Api.Get(apiUrl,
|
||||
function(result)
|
||||
{
|
||||
toastr.success(L('Removed #1 #2 of #3 from stock', jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.product.name));
|
||||
$("#specific_stock_entry").find("option").remove().end().append("<option></option>");
|
||||
if ($("#use_specific_stock_entry").is(":checked"))
|
||||
{
|
||||
$("#use_specific_stock_entry").click();
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy("consume-form");
|
||||
toastr.success(L('Removed #1 #2 of #3 from stock', jsonForm.amount, Pluralize(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + result.booking_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||
|
||||
$('#amount').val(1);
|
||||
Grocy.Components.ProductPicker.SetValue('');
|
||||
@@ -25,12 +45,68 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("consume-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("consume-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$('#save-mark-as-open-button').on('click', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonForm = $('#consume-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("consume-form");
|
||||
|
||||
if ($("#use_specific_stock_entry").is(":checked"))
|
||||
{
|
||||
jsonForm.amount = 1;
|
||||
}
|
||||
|
||||
var apiUrl = 'stock/open-product/' + jsonForm.product_id + '/' + jsonForm.amount;
|
||||
|
||||
if ($("#use_specific_stock_entry").is(":checked"))
|
||||
{
|
||||
apiUrl += "&stock_entry_id=" + jsonForm.specific_stock_entry;
|
||||
}
|
||||
|
||||
Grocy.Api.Get('stock/get-product-details/' + jsonForm.product_id,
|
||||
function(productDetails)
|
||||
{
|
||||
Grocy.Api.Get(apiUrl,
|
||||
function(result)
|
||||
{
|
||||
$("#specific_stock_entry").find("option").remove().end().append("<option></option>");
|
||||
if ($("#use_specific_stock_entry").is(":checked"))
|
||||
{
|
||||
$("#use_specific_stock_entry").click();
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy("consume-form");
|
||||
toastr.success(L('Marked #1 #2 of #3 as opened', jsonForm.amount, Pluralize(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + result.booking_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||
|
||||
$('#amount').val(1);
|
||||
Grocy.Components.ProductPicker.SetValue('');
|
||||
Grocy.Components.ProductPicker.GetInputElement().focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('consume-form');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("consume-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("consume-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -38,14 +114,20 @@
|
||||
|
||||
Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
|
||||
{
|
||||
var productId = $(e.target).val();
|
||||
$("#specific_stock_entry").find("option").remove().end().append("<option></option>");
|
||||
if ($("#use_specific_stock_entry").is(":checked"))
|
||||
{
|
||||
$("#use_specific_stock_entry").click();
|
||||
}
|
||||
|
||||
var productId = $(e.target).val();
|
||||
|
||||
if (productId)
|
||||
{
|
||||
Grocy.Components.ProductCard.Refresh(productId);
|
||||
|
||||
Grocy.Api.Get('stock/get-product-details/' + productId,
|
||||
function (productDetails)
|
||||
function(productDetails)
|
||||
{
|
||||
$('#amount').attr('max', productDetails.stock_amount);
|
||||
$('#amount_qu_unit').text(productDetails.quantity_unit_stock.name);
|
||||
@@ -63,6 +145,41 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
|
||||
Grocy.FrontendHelpers.ValidateForm('consume-form');
|
||||
$('#amount').focus();
|
||||
}
|
||||
|
||||
if (productDetails.stock_amount == productDetails.stock_amount_opened)
|
||||
{
|
||||
$("#save-mark-as-open-button").addClass("disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#save-mark-as-open-button").removeClass("disabled");
|
||||
}
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
|
||||
Grocy.Api.Get("stock/get-product-stock-entries/" + productId,
|
||||
function (stockEntries)
|
||||
{
|
||||
stockEntries.forEach(stockEntry =>
|
||||
{
|
||||
var openTxt = L("Not opened");
|
||||
if (stockEntry.open == 1)
|
||||
{
|
||||
openTxt = L("Opened");
|
||||
}
|
||||
|
||||
for (i = 0; i < stockEntry.amount; i++)
|
||||
{
|
||||
$("#specific_stock_entry").append($("<option>", {
|
||||
value: stockEntry.stock_id,
|
||||
text: L("Expires on #1; Bought on #2", moment(stockEntry.best_before_date).format("YYYY-MM-DD"), moment(stockEntry.purchased_date).format("YYYY-MM-DD")) + "; " + openTxt
|
||||
}));
|
||||
}
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -81,7 +198,12 @@ $('#amount').on('focus', function(e)
|
||||
$(this).select();
|
||||
});
|
||||
|
||||
$('#consume-form input').keyup(function (event)
|
||||
$('#consume-form input').keyup(function(event)
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm('consume-form');
|
||||
});
|
||||
|
||||
$('#consume-form select').change(function(event)
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm('consume-form');
|
||||
});
|
||||
@@ -102,3 +224,39 @@ $('#consume-form input').keydown(function(event)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#use_specific_stock_entry").on("change", function()
|
||||
{
|
||||
var value = $(this).is(":checked");
|
||||
if (value)
|
||||
{
|
||||
$("#specific_stock_entry").removeAttr("disabled");
|
||||
$("#amount").attr("disabled", "");
|
||||
$("#amount").val(1);
|
||||
$("#amount").removeAttr("required");
|
||||
$("#specific_stock_entry").attr("required", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#specific_stock_entry").attr("disabled", "");
|
||||
$("#amount").removeAttr("disabled");
|
||||
$("#amount").attr("required", "");
|
||||
$("#specific_stock_entry").removeAttr("required");
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.ValidateForm("consume-form");
|
||||
});
|
||||
|
||||
function UndoStockBooking(bookingId)
|
||||
{
|
||||
Grocy.Api.Get('stock/undo-booking/' + bookingId.toString(),
|
||||
function(result)
|
||||
{
|
||||
toastr.success(L("Booking successfully undone"));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@@ -38,6 +38,7 @@ function DisplayEquipment(id)
|
||||
{
|
||||
$(".selected-equipment-name").text(equipmentItem.name);
|
||||
$("#description-tab-content").html(equipmentItem.description);
|
||||
$(".equipment-edit-button").attr("href", U("/equipment/" + equipmentItem.id.toString()));
|
||||
|
||||
if (equipmentItem.instruction_manual_file_name !== null && !equipmentItem.instruction_manual_file_name.isEmpty())
|
||||
{
|
||||
@@ -116,7 +117,7 @@ $("#selectedEquipmentInstructionManualToggleFullscreenButton").on('click', funct
|
||||
$("#selectedEquipmentInstructionManualCard").toggleClass("fullscreen");
|
||||
$("#selectedEquipmentInstructionManualCard .card-header").toggleClass("fixed-top");
|
||||
$("#selectedEquipmentInstructionManualCard .card-body").toggleClass("mt-5");
|
||||
$("body").toggleClass("fullscreen-responsive-embed-active");
|
||||
$("body").toggleClass("fullscreen-card");
|
||||
ResizeResponsiveEmbeds(true);
|
||||
});
|
||||
|
||||
|
@@ -3,6 +3,8 @@
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#equipment-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("equipment-form");
|
||||
|
||||
if ($("#instruction-manual")[0].files.length > 0)
|
||||
{
|
||||
var someRandomStuff = Math.random().toString(36).substring(2, 100) + Math.random().toString(36).substring(2, 100);
|
||||
@@ -28,6 +30,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("equipment-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -39,6 +42,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("equipment-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -54,6 +58,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("equipment-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -71,6 +76,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("equipment-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -82,6 +88,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("equipment-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
|
@@ -3,6 +3,7 @@
|
||||
e.preventDefault();
|
||||
|
||||
var jsonForm = $('#inventory-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("inventory-form");
|
||||
|
||||
Grocy.Api.Get('stock/get-product-details/' + jsonForm.product_id,
|
||||
function (productDetails)
|
||||
@@ -32,7 +33,8 @@
|
||||
);
|
||||
}
|
||||
|
||||
toastr.success(L('Stock amount of #1 is now #2 #3', productDetails.product.name, jsonForm.new_amount, productDetails.quantity_unit_stock.name));
|
||||
Grocy.FrontendHelpers.EndUiBusy("inventory-form");
|
||||
toastr.success(L('Stock amount of #1 is now #2 #3', productDetails.product.name, jsonForm.new_amount, Pluralize(jsonForm.new_amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural)) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + result.booking_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||
|
||||
if (addBarcode !== undefined)
|
||||
{
|
||||
@@ -42,7 +44,7 @@
|
||||
{
|
||||
$('#inventory-change-info').addClass('d-none');
|
||||
$('#new_amount').val('');
|
||||
Grocy.Components.DateTimePicker.SetValue('');
|
||||
Grocy.Components.DateTimePicker.Clear();
|
||||
Grocy.Components.ProductPicker.SetValue('');
|
||||
Grocy.Components.ProductPicker.GetInputElement().focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('inventory-form');
|
||||
@@ -50,12 +52,14 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("inventory-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("inventory-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -186,3 +190,17 @@ $('#new_amount').on('keyup', function(e)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
function UndoStockBooking(bookingId)
|
||||
{
|
||||
Grocy.Api.Get('stock/undo-booking/' + bookingId.toString(),
|
||||
function(result)
|
||||
{
|
||||
toastr.success(L("Booking successfully undone"));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@@ -2,15 +2,19 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#location-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("location-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/locations', $('#location-form').serializeJSON(),
|
||||
Grocy.Api.Post('add-object/locations', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/locations');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("location-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -24,6 +28,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("location-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
|
@@ -10,6 +10,8 @@
|
||||
}
|
||||
|
||||
var jsonData = $('#product-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("product-form");
|
||||
|
||||
if ($("#product-picture")[0].files.length > 0)
|
||||
{
|
||||
var someRandomStuff = Math.random().toString(36).substring(2, 100) + Math.random().toString(36).substring(2, 100);
|
||||
@@ -35,6 +37,7 @@
|
||||
},
|
||||
function (xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("product-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -46,6 +49,7 @@
|
||||
},
|
||||
function (xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("product-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -61,6 +65,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("product-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -78,6 +83,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("product-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -89,6 +95,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("product-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -196,6 +203,24 @@ $('#delete-current-product-picture-button').on('click', function (e)
|
||||
$("#delete-current-product-picture-button").addClass("disabled");
|
||||
});
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
if (Grocy.UserSettings.product_presets_location_id.toString() !== '-1')
|
||||
{
|
||||
$("#location_id").val(Grocy.UserSettings.product_presets_location_id);
|
||||
}
|
||||
|
||||
if (Grocy.UserSettings.product_presets_product_group_id.toString() !== '-1')
|
||||
{
|
||||
$("#product_group_id").val(Grocy.UserSettings.product_presets_product_group_id);
|
||||
}
|
||||
|
||||
if (Grocy.UserSettings.product_presets_qu_id.toString() !== '-1')
|
||||
{
|
||||
$("select.input-group-qu").val(Grocy.UserSettings.product_presets_qu_id);
|
||||
}
|
||||
}
|
||||
|
||||
$('#name').focus();
|
||||
$('.input-group-qu').trigger('change');
|
||||
Grocy.FrontendHelpers.ValidateForm('product-form');
|
||||
|
@@ -2,28 +2,33 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#product-group-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("product-group-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/product_groups', $('#product-group-form').serializeJSON(),
|
||||
Grocy.Api.Post('add-object/product_groups', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/productgroups');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("product-group-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Post('edit-object/product_groups/' + Grocy.EditObjectId, $('#product-group-form').serializeJSON(),
|
||||
Grocy.Api.Post('edit-object/product_groups/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/productgroups');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("product-group-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
|
@@ -3,9 +3,10 @@
|
||||
e.preventDefault();
|
||||
|
||||
var jsonForm = $('#purchase-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("purchase-form");
|
||||
|
||||
Grocy.Api.Get('stock/get-product-details/' + jsonForm.product_id,
|
||||
function (productDetails)
|
||||
function(productDetails)
|
||||
{
|
||||
var amount = jsonForm.amount * productDetails.product.qu_factor_purchase_to_stock;
|
||||
|
||||
@@ -35,22 +36,31 @@
|
||||
function (result) { },
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
toastr.success(L('Added #1 #2 of #3 to stock', amount, productDetails.quantity_unit_stock.name, productDetails.product.name));
|
||||
var successMessage = L('Added #1 #2 of #3 to stock', amount, Pluralize(amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + result.booking_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>';
|
||||
|
||||
if (addBarcode !== undefined)
|
||||
{
|
||||
window.location.href = U('/purchase');
|
||||
}
|
||||
else if (GetUriParam("flow") === "shoppinglistitemtostock" && typeof GetUriParam("embedded") !== undefined)
|
||||
{
|
||||
window.parent.postMessage(WindowMessageBag("AfterItemAdded", GetUriParam("listitemid")), Grocy.BaseUrl);
|
||||
window.parent.postMessage(WindowMessageBag("ShowSuccessMessage", successMessage), Grocy.BaseUrl);
|
||||
window.parent.postMessage(WindowMessageBag("Ready"), Grocy.BaseUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
|
||||
toastr.success(successMessage);
|
||||
$('#amount').val(0);
|
||||
$('#price').val('');
|
||||
Grocy.Components.DateTimePicker.SetValue('');
|
||||
Grocy.Components.DateTimePicker.Clear();
|
||||
Grocy.Components.ProductPicker.SetValue('');
|
||||
Grocy.Components.ProductPicker.GetInputElement().focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||
@@ -58,12 +68,14 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("purchase-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -97,6 +109,12 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
|
||||
Grocy.Components.DateTimePicker.SetValue(moment().add(productDetails.product.default_best_before_days, 'days').format('YYYY-MM-DD'));
|
||||
}
|
||||
$('#amount').focus();
|
||||
|
||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||
if (GetUriParam("flow") === "shoppinglistitemtostock" && BoolVal(Grocy.UserSettings.shopping_list_to_stock_workflow_auto_submit_when_prefilled) && document.getElementById("purchase-form").checkValidity() === true)
|
||||
{
|
||||
$("#save-purchase-button").click();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -167,7 +185,26 @@ Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e)
|
||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||
});
|
||||
|
||||
$('#amount').on('change', function (e)
|
||||
$('#amount').on('change', function(e)
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||
});
|
||||
|
||||
if (GetUriParam("flow") === "shoppinglistitemtostock")
|
||||
{
|
||||
$('#amount').val(GetUriParam("amount"));
|
||||
}
|
||||
|
||||
function UndoStockBooking(bookingId)
|
||||
{
|
||||
Grocy.Api.Get('stock/undo-booking/' + bookingId.toString(),
|
||||
function(result)
|
||||
{
|
||||
toastr.success(L("Booking successfully undone"));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@@ -2,28 +2,33 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#quantityunit-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("quantityunit-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/quantity_units', $('#quantityunit-form').serializeJSON(),
|
||||
Grocy.Api.Post('add-object/quantity_units', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/quantityunits');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("quantityunit-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Post('edit-object/quantity_units/' + Grocy.EditObjectId, $('#quantityunit-form').serializeJSON(),
|
||||
Grocy.Api.Post('edit-object/quantity_units/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/quantityunits');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("quantityunit-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
|
@@ -2,13 +2,17 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
||||
var jsonData = $('#recipe-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("recipe-form");
|
||||
|
||||
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/recipes');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("recipe-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -17,8 +21,10 @@
|
||||
var recipesPosTables = $('#recipes-pos-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
"orderFixed": [[4, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
{ 'orderable': false, 'targets': 0 },
|
||||
{ 'visible': false, 'targets': 4 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false,
|
||||
@@ -32,18 +38,31 @@ var recipesPosTables = $('#recipes-pos-table').DataTable({
|
||||
{
|
||||
column.search.search = "";
|
||||
});
|
||||
},
|
||||
'rowGroup': {
|
||||
dataSrc: 4
|
||||
}
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function ()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
var recipesIncludesTables = $('#recipes-includes-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false,
|
||||
'colReorder': true,
|
||||
'stateSave': true,
|
||||
'stateSaveParams': function (settings, data)
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
data.search.search = "";
|
||||
|
||||
recipesPosTables.search(value).draw();
|
||||
data.columns.forEach(column =>
|
||||
{
|
||||
column.search.search = "";
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.FrontendHelpers.ValidateForm('recipe-form');
|
||||
@@ -108,6 +127,43 @@ $(document).on('click', '.recipe-pos-delete-button', function(e)
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.recipe-include-delete-button', function(e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-recipe-include-name');
|
||||
var objectId = $(e.currentTarget).attr('data-recipe-include-id');
|
||||
|
||||
bootbox.confirm({
|
||||
message: L('Are you sure to remove included recipe "#1"?', objectName),
|
||||
buttons: {
|
||||
confirm: {
|
||||
label: L('Yes'),
|
||||
className: 'btn-success'
|
||||
},
|
||||
cancel: {
|
||||
label: L('No'),
|
||||
className: 'btn-danger'
|
||||
}
|
||||
},
|
||||
callback: function(result)
|
||||
{
|
||||
if (result === true)
|
||||
{
|
||||
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(), function() { }, function() { });
|
||||
Grocy.Api.Get('delete-object/recipes_nestings/' + objectId,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/recipe/' + Grocy.EditObjectId);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.recipe-pos-order-missing-button', function(e)
|
||||
{
|
||||
var productName = $(e.currentTarget).attr('data-product-name');
|
||||
@@ -156,6 +212,28 @@ $(document).on('click', '.recipe-pos-edit-button', function (e)
|
||||
);
|
||||
});
|
||||
|
||||
$(document).on('click', '.recipe-include-edit-button', function (e)
|
||||
{
|
||||
var id = $(e.currentTarget).attr('data-recipe-include-id');
|
||||
var recipeId = $(e.currentTarget).attr('data-recipe-included-recipe-id');
|
||||
console.log(recipeId);
|
||||
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
||||
function(result)
|
||||
{
|
||||
$("#recipe-include-editform-title").text(L("Edit included recipe"));
|
||||
$("#recipe-include-form").data("edit-mode", "edit");
|
||||
$("#recipe-include-form").data("recipe-nesting-id", id);
|
||||
$("#includes_recipe_id").val(recipeId);
|
||||
$("#recipe-include-editform-modal").modal("show");
|
||||
Grocy.FrontendHelpers.ValidateForm("recipe-include-form");
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$("#recipe-pos-add-button").on("click", function(e)
|
||||
{
|
||||
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
||||
@@ -170,6 +248,62 @@ $("#recipe-pos-add-button").on("click", function(e)
|
||||
);
|
||||
});
|
||||
|
||||
$("#recipe-include-add-button").on("click", function(e)
|
||||
{
|
||||
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
||||
function(result)
|
||||
{
|
||||
$("#recipe-include-editform-title").text(L("Add included recipe"));
|
||||
$("#recipe-include-form").data("edit-mode", "create");
|
||||
$("#includes_recipe_id").val("");
|
||||
$("#recipe-include-editform-modal").modal("show");
|
||||
Grocy.FrontendHelpers.ValidateForm("recipe-include-form");
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$('#save-recipe-include-button').on('click', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var nestingId = $("#recipe-include-form").data("recipe-nesting-id");
|
||||
var editMode = $("#recipe-include-form").data("edit-mode");
|
||||
|
||||
var jsonData = $('#recipe-include-form').serializeJSON();
|
||||
jsonData.recipe_id = Grocy.EditObjectId;
|
||||
|
||||
if (editMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/recipes_nestings', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/recipe/' + Grocy.EditObjectId);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Post('edit-object/recipes_nestings/' + nestingId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/recipe/' + Grocy.EditObjectId);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$('#description').summernote({
|
||||
minHeight: '300px',
|
||||
lang: L('summernote_locale')
|
||||
|
@@ -4,6 +4,9 @@
|
||||
|
||||
var jsonData = $('#recipe-pos-form').serializeJSON({ checkboxUncheckedValue: "0" });
|
||||
jsonData.recipe_id = Grocy.EditObjectParentId;
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy("recipe-pos-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/recipes_pos', jsonData,
|
||||
@@ -13,6 +16,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("recipe-pos-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -26,6 +30,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("recipe-pos-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -105,10 +110,22 @@ $("#only_check_single_unit_in_stock").on("click", function()
|
||||
if (this.checked)
|
||||
{
|
||||
$("#qu_id").removeAttr("disabled");
|
||||
$("#amount").attr("min", "0.01");
|
||||
$("#amount").attr("step", "0.01");
|
||||
$("#amount").parent().find(".invalid-feedback").text(L("This cannot be negative"));
|
||||
Grocy.FrontendHelpers.ValidateForm("recipe-pos-form");
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#qu_id").attr("disabled", "");
|
||||
Grocy.Components.ProductPicker.GetPicker().trigger("change");
|
||||
$("#amount").attr("min", "0");
|
||||
$("#amount").attr("step", "1");
|
||||
Grocy.Components.ProductPicker.GetPicker().trigger("change"); // Selects the default quantity unit of the selected product
|
||||
$("#amount").parent().find(".invalid-feedback").text(L("This cannot be negative and must be an integral number"));
|
||||
Grocy.FrontendHelpers.ValidateForm("recipe-pos-form");
|
||||
}
|
||||
});
|
||||
|
||||
// Click twice to trigger on-click but not change the actual checked state
|
||||
$("#only_check_single_unit_in_stock").click();
|
||||
$("#only_check_single_unit_in_stock").click();
|
||||
|
@@ -1,6 +1,9 @@
|
||||
var recipesTables = $('#recipes-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[0, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderData': 2, 'targets': 1 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false,
|
||||
'colReorder': true,
|
||||
@@ -95,6 +98,8 @@ $(document).on('click', '.recipe-order-missing-button', function(e)
|
||||
{
|
||||
if (result === true)
|
||||
{
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
Grocy.Api.Get('recipes/add-not-fulfilled-products-to-shopping-list/' + objectId,
|
||||
function(result)
|
||||
{
|
||||
@@ -102,6 +107,7 @@ $(document).on('click', '.recipe-order-missing-button', function(e)
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -131,13 +137,17 @@ $("#selectedRecipeConsumeButton").on('click', function(e)
|
||||
{
|
||||
if (result === true)
|
||||
{
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
Grocy.Api.Get('recipes/consume-recipe/' + objectId,
|
||||
function(result)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
toastr.success(L('Removed all ingredients of recipe "#1" from stock', objectName));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -158,6 +168,7 @@ recipesTables.on('select', function(e, dt, type, indexes)
|
||||
$("#selectedRecipeToggleFullscreenButton").on('click', function(e)
|
||||
{
|
||||
$("#selectedRecipeCard").toggleClass("fullscreen");
|
||||
$("body").toggleClass("fullscreen-card");
|
||||
$("#selectedRecipeCard .card-header").toggleClass("fixed-top");
|
||||
$("#selectedRecipeCard .card-body").toggleClass("mt-5");
|
||||
});
|
||||
|
@@ -61,17 +61,21 @@ $(document).on('click', '.shoppinglist-delete-button', function (e)
|
||||
e.preventDefault();
|
||||
|
||||
var shoppingListItemId = $(e.currentTarget).attr('data-shoppinglist-id');
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
Grocy.Api.Get('delete-object/shopping_list/' + shoppingListItemId,
|
||||
function(result)
|
||||
{
|
||||
$('#shoppinglistitem-' + shoppingListItemId + '-row').fadeOut(500, function()
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
$(this).remove();
|
||||
OnListItemRemoved();
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -109,16 +113,21 @@ $(document).on('click', '#clear-shopping-list', function(e)
|
||||
{
|
||||
if (result === true)
|
||||
{
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
Grocy.Api.Get('stock/clear-shopping-list',
|
||||
function(result)
|
||||
{
|
||||
$('#shoppinglist-table tbody tr').fadeOut(500, function()
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
$(this).remove();
|
||||
OnListItemRemoved();
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -126,3 +135,91 @@ $(document).on('click', '#clear-shopping-list', function(e)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.shopping-list-stock-add-workflow-list-item-button', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var href = $(e.currentTarget).attr('href');
|
||||
|
||||
$("#shopping-list-stock-add-workflow-purchase-form-frame").attr("src", href);
|
||||
$("#shopping-list-stock-add-workflow-modal").modal("show");
|
||||
|
||||
if (Grocy.ShoppingListToStockWorkflowAll)
|
||||
{
|
||||
$("#shopping-list-stock-add-workflow-purchase-item-count").removeClass("d-none");
|
||||
$("#shopping-list-stock-add-workflow-purchase-item-count").text(L("Adding shopping list item #1 of #2", Grocy.ShoppingListToStockWorkflowCurrent, Grocy.ShoppingListToStockWorkflowCount));
|
||||
$("#shopping-list-stock-add-workflow-skip-button").removeClass("d-none");
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#shopping-list-stock-add-workflow-skip-button").addClass("d-none");
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.ShoppingListToStockWorkflowAll = false;
|
||||
Grocy.ShoppingListToStockWorkflowCount = 0;
|
||||
Grocy.ShoppingListToStockWorkflowCurrent = 0;
|
||||
$(document).on('click', '#add-all-items-to-stock-button', function(e)
|
||||
{
|
||||
Grocy.ShoppingListToStockWorkflowAll = true;
|
||||
Grocy.ShoppingListToStockWorkflowCount = $(".shopping-list-stock-add-workflow-list-item-button").length;
|
||||
Grocy.ShoppingListToStockWorkflowCurrent++;
|
||||
$(".shopping-list-stock-add-workflow-list-item-button").first().click();
|
||||
});
|
||||
|
||||
$("#shopping-list-stock-add-workflow-modal").on("hidden.bs.modal", function(e)
|
||||
{
|
||||
Grocy.ShoppingListToStockWorkflowAll = false;
|
||||
Grocy.ShoppingListToStockWorkflowCount = 0;
|
||||
Grocy.ShoppingListToStockWorkflowCurrent = 0;
|
||||
})
|
||||
|
||||
$(window).on("message", function(e)
|
||||
{
|
||||
var data = e.originalEvent.data;
|
||||
|
||||
if (data.Message === "AfterItemAdded")
|
||||
{
|
||||
$(".shoppinglist-delete-button[data-shoppinglist-id='" + data.Payload + "']").click();
|
||||
}
|
||||
else if (data.Message === "Ready")
|
||||
{
|
||||
if (!Grocy.ShoppingListToStockWorkflowAll)
|
||||
{
|
||||
$("#shopping-list-stock-add-workflow-modal").modal("hide");
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.ShoppingListToStockWorkflowCurrent++;
|
||||
if (Grocy.ShoppingListToStockWorkflowCurrent <= Grocy.ShoppingListToStockWorkflowCount)
|
||||
{
|
||||
$(".shopping-list-stock-add-workflow-list-item-button")[1].click();
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#shopping-list-stock-add-workflow-modal").modal("hide");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data.Message === "ShowSuccessMessage")
|
||||
{
|
||||
toastr.success(data.Payload);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '#shopping-list-stock-add-workflow-skip-button', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
window.postMessage(WindowMessageBag("Ready"), Grocy.BaseUrl);
|
||||
});
|
||||
|
||||
function OnListItemRemoved()
|
||||
{
|
||||
if ($(".shopping-list-stock-add-workflow-list-item-button").length === 0)
|
||||
{
|
||||
$("#add-all-items-to-stock-button").addClass("disabled");
|
||||
}
|
||||
}
|
||||
OnListItemRemoved();
|
||||
|
@@ -2,28 +2,33 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#shoppinglist-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("shoppinglist-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/shopping_list', $('#shoppinglist-form').serializeJSON(),
|
||||
Grocy.Api.Post('add-object/shopping_list', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/shoppinglist');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("shoppinglist-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Post('edit-object/shopping_list/' + Grocy.EditObjectId, $('#shoppinglist-form').serializeJSON(),
|
||||
Grocy.Api.Post('edit-object/shopping_list/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/shoppinglist');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("shoppinglist-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -54,14 +59,11 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
|
||||
});
|
||||
|
||||
Grocy.FrontendHelpers.ValidateForm('shoppinglist-form');
|
||||
Grocy.Components.ProductPicker.GetInputElement().focus();
|
||||
|
||||
if (Grocy.Components.ProductPicker.InProductAddWorkflow() === false)
|
||||
if (Grocy.EditMode === "edit")
|
||||
{
|
||||
Grocy.Components.ProductPicker.GetInputElement().focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Components.ProductPicker.GetPicker().trigger('change');
|
||||
Grocy.Components.ProductPicker.GetPicker().trigger('change');
|
||||
}
|
||||
|
||||
$('#amount').on('focus', function(e)
|
||||
|
72
public/viewjs/stockjournal.js
Normal file
72
public/viewjs/stockjournal.js
Normal file
@@ -0,0 +1,72 @@
|
||||
var stockJournalTable = $('#stock-journal-table').DataTable({
|
||||
'paginate': true,
|
||||
'order': [[3, 'desc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false,
|
||||
'colReorder': true,
|
||||
'stateSave': true,
|
||||
'stateSaveParams': function(settings, data)
|
||||
{
|
||||
data.search.search = "";
|
||||
|
||||
data.columns.forEach(column =>
|
||||
{
|
||||
column.search.search = "";
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#product-filter").on("change", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
var text = $("#product-filter option:selected").text();
|
||||
if (value === "all")
|
||||
{
|
||||
text = "";
|
||||
}
|
||||
|
||||
stockJournalTable.column(1).search(text).draw();
|
||||
});
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
stockJournalTable.search(value).draw();
|
||||
});
|
||||
|
||||
if (typeof GetUriParam("product") !== "undefined")
|
||||
{
|
||||
$("#product-filter").val(GetUriParam("product"));
|
||||
$("#product-filter").trigger("change");
|
||||
}
|
||||
|
||||
$(document).on('click', '.undo-stock-booking-button', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var element = $(e.currentTarget);
|
||||
var bookingId = $(e.currentTarget).attr('data-booking-id');
|
||||
|
||||
Grocy.Api.Get('stock/undo-booking/' + bookingId.toString(),
|
||||
function(result)
|
||||
{
|
||||
element.closest("tr").addClass("text-muted");
|
||||
element.parent().siblings().find("span.name-anchor").addClass("text-strike-through").after("<br>" + L("Undone on") + " " + moment().format("YYYY-MM-DD HH:mm:ss") + " <time class='timeago timeago-contextual' datetime='" + moment().format("YYYY-MM-DD HH:mm:ss") + "'></time>");
|
||||
element.closest(".undo-stock-booking-button").addClass("disabled");
|
||||
RefreshContextualTimeago();
|
||||
toastr.success(L("Booking successfully undone"));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
@@ -31,6 +31,17 @@ $("#location-filter").on("change", function()
|
||||
stockOverviewTable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
$("#product-group-filter").on("change", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
stockOverviewTable.column(6).search(value).draw();
|
||||
});
|
||||
|
||||
$("#status-filter").on("change", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
@@ -70,6 +81,8 @@ $(document).on('click', '.product-consume-button', function(e)
|
||||
// Remove the focus from the current button
|
||||
// to prevent that the tooltip stays until clicked anywhere else
|
||||
document.activeElement.blur();
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
var productId = $(e.currentTarget).attr('data-product-id');
|
||||
var productName = $(e.currentTarget).attr('data-product-name');
|
||||
@@ -122,20 +135,112 @@ $(document).on('click', '.product-consume-button', function(e)
|
||||
$(this).text(result.next_best_before_date).fadeIn(500);
|
||||
});
|
||||
$('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date);
|
||||
}
|
||||
|
||||
var openedAmount = result.stock_amount_opened || 0;
|
||||
$('#product-' + productId + '-opened-amount').parent().effect('highlight', {}, 500);
|
||||
$('#product-' + productId + '-opened-amount').fadeOut(500, function ()
|
||||
{
|
||||
if (openedAmount > 0)
|
||||
{
|
||||
$(this).text(L('#1 opened', openedAmount)).fadeIn(500);
|
||||
}
|
||||
else
|
||||
{
|
||||
$(this).text("").fadeIn(500);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
toastr.success(L('Removed #1 #2 of #3 from stock', consumeAmount, productQuName, productName));
|
||||
RefreshContextualTimeago();
|
||||
RefreshStatistics();
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$(document).on('click', '.product-open-button', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
// Remove the focus from the current button
|
||||
// to prevent that the tooltip stays until clicked anywhere else
|
||||
document.activeElement.blur();
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
var productId = $(e.currentTarget).attr('data-product-id');
|
||||
var productName = $(e.currentTarget).attr('data-product-name');
|
||||
var productQuName = $(e.currentTarget).attr('data-product-qu-name');
|
||||
var button = $(e.currentTarget);
|
||||
|
||||
Grocy.Api.Get('stock/open-product/' + productId + '/1',
|
||||
function()
|
||||
{
|
||||
Grocy.Api.Get('stock/get-product-details/' + productId,
|
||||
function(result)
|
||||
{
|
||||
var productRow = $('#product-' + productId + '-row');
|
||||
var expiringThreshold = moment().add("-" + $("#info-expiring-products").data("next-x-days"), "days");
|
||||
var now = moment();
|
||||
var nextBestBeforeDate = moment(result.next_best_before_date);
|
||||
|
||||
productRow.removeClass("table-warning");
|
||||
productRow.removeClass("table-danger");
|
||||
if (now.isAfter(nextBestBeforeDate))
|
||||
{
|
||||
productRow.addClass("table-danger");
|
||||
}
|
||||
if (expiringThreshold.isAfter(nextBestBeforeDate))
|
||||
{
|
||||
productRow.addClass("table-warning");
|
||||
}
|
||||
|
||||
$('#product-' + productId + '-next-best-before-date').parent().effect('highlight', {}, 500);
|
||||
$('#product-' + productId + '-next-best-before-date').fadeOut(500, function ()
|
||||
{
|
||||
$(this).text(result.next_best_before_date).fadeIn(500);
|
||||
});
|
||||
$('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date);
|
||||
|
||||
$('#product-' + productId + '-opened-amount').parent().effect('highlight', {}, 500);
|
||||
$('#product-' + productId + '-opened-amount').fadeOut(500, function ()
|
||||
{
|
||||
$(this).text(L('#1 opened', result.stock_amount_opened)).fadeIn(500);
|
||||
});
|
||||
|
||||
if (result.stock_amount == result.stock_amount_opened)
|
||||
{
|
||||
button.addClass("disabled");
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
toastr.success(L('Marked #1 #2 of #3 as opened', 1, productQuName, productName));
|
||||
RefreshContextualTimeago();
|
||||
RefreshStatistics();
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
@@ -143,41 +248,8 @@ $(document).on('click', '.product-consume-button', function(e)
|
||||
|
||||
$(document).on("click", ".product-name-cell", function(e)
|
||||
{
|
||||
var productHasPicture = BoolVal($(e.currentTarget).attr("data-product-has-picture"));
|
||||
|
||||
if (productHasPicture)
|
||||
{
|
||||
var pictureUrl = $(e.currentTarget).attr("data-picture-url");
|
||||
var productName = $(e.currentTarget).attr("data-product-name");
|
||||
var productId = $(e.currentTarget).attr("data-product-id");
|
||||
|
||||
bootbox.dialog({
|
||||
title: L("Image of product #1", productName),
|
||||
message: "<img src='" + pictureUrl + "' class='img-fluid img-thumbnail'>",
|
||||
backdrop: false,
|
||||
onEscape: true,
|
||||
closeButton: false,
|
||||
className: 'centered-dialog',
|
||||
buttons: {
|
||||
editproduct: {
|
||||
label: '<i class="fas fa-edit"></i> ' + L('Edit product'),
|
||||
className: 'btn-info responsive-button',
|
||||
callback: function ()
|
||||
{
|
||||
window.location.href = U('/product/' + productId + '?returnto=' + encodeURIComponent(window.location.pathname) + '#product-picture');
|
||||
}
|
||||
},
|
||||
close: {
|
||||
label: L('Close'),
|
||||
className: 'btn-default responsive-button',
|
||||
callback: function()
|
||||
{
|
||||
bootbox.hideAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Grocy.Components.ProductCard.Refresh($(e.currentTarget).attr("data-product-id"));
|
||||
$("#stockoverview-productcard-modal").modal("show");
|
||||
});
|
||||
|
||||
function RefreshStatistics()
|
||||
|
8
public/viewjs/stocksettings.js
Normal file
8
public/viewjs/stocksettings.js
Normal file
@@ -0,0 +1,8 @@
|
||||
$("#product_presets_location_id").val(Grocy.UserSettings.product_presets_location_id);
|
||||
$("#product_presets_product_group_id").val(Grocy.UserSettings.product_presets_product_group_id);
|
||||
$("#product_presets_qu_id").val(Grocy.UserSettings.product_presets_qu_id);
|
||||
|
||||
if (BoolVal(Grocy.UserSettings.shopping_list_to_stock_workflow_auto_submit_when_prefilled))
|
||||
{
|
||||
$("#shopping-list-to-stock-workflow-auto-submit-when-prefilled").prop("checked", true);
|
||||
}
|
@@ -2,28 +2,33 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#task-category-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("task-category-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/task_categories', $('#task-category-form').serializeJSON(),
|
||||
Grocy.Api.Post('add-object/task_categories', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/taskcategories');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("task-category-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Post('edit-object/task_categories/' + Grocy.EditObjectId, $('#task-category-form').serializeJSON(),
|
||||
Grocy.Api.Post('edit-object/task_categories/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/taskcategories');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("task-category-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
|
@@ -7,6 +7,8 @@
|
||||
delete jsonData.user_id;
|
||||
jsonData.due_date = Grocy.Components.DateTimePicker.GetValue();
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy("task-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('add-object/tasks', jsonData,
|
||||
@@ -16,6 +18,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("task-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
@@ -29,6 +32,7 @@
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("task-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
|
@@ -62,6 +62,8 @@ $(document).on('click', '.do-task-button', function(e)
|
||||
// Remove the focus from the current button
|
||||
// to prevent that the tooltip stays until clicked anywhere else
|
||||
document.activeElement.blur();
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
var taskId = $(e.currentTarget).attr('data-task-id');
|
||||
var taskName = $(e.currentTarget).attr('data-task-name');
|
||||
@@ -84,12 +86,14 @@ $(document).on('click', '.do-task-button', function(e)
|
||||
$('.do-task-button[data-task-id="' + taskId + '"]').addClass("disabled");
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
toastr.success(L('Marked task #1 as completed on #2', taskName, doneTime));
|
||||
RefreshContextualTimeago();
|
||||
RefreshStatistics();
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
|
@@ -2,28 +2,33 @@
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#user-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("user-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('users/create', $('#user-form').serializeJSON(),
|
||||
Grocy.Api.Post('users/create', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/users');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("user-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Post('users/edit/' + Grocy.EditObjectId, $('#user-form').serializeJSON(),
|
||||
Grocy.Api.Post('users/edit/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/users');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("user-form");
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 129 KiB |
Binary file not shown.
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 106 KiB |
Binary file not shown.
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 166 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user