Compare commits

..

103 Commits
1.5.2 ... 1.5.5

Author SHA1 Message Date
Miha Perpar
ba361a8a27 Translated using Weblate (Slovenian)
Currently translated at 59.0% (307 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sl/
2023-08-13 08:19:59 +00:00
Miha Perpar
fc2ce6e488 Translated using Weblate (Slovenian)
Currently translated at 15.9% (81 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/sl/
2023-08-13 08:19:59 +00:00
Tomasz Klimczak
d7f77a572a Translated using Weblate (Polish)
Currently translated at 100.0% (520 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2023-08-13 08:19:58 +00:00
Fabian Flodman
64e28fd01a Translated using Weblate (German)
Currently translated at 97.3% (506 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-08-13 08:19:58 +00:00
Thomas
714d5e5184 Translated using Weblate (German)
Currently translated at 97.3% (506 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-08-13 08:19:58 +00:00
Fabian Flodman
640500c82d Translated using Weblate (German)
Currently translated at 100.0% (490 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2023-08-13 08:19:58 +00:00
vabene1111
4b14a099df better logging 2023-08-05 12:00:03 +02:00
vabene1111
dae7cbfb85 version script updates and system page fix 2023-08-05 10:56:27 +02:00
vabene1111
0c62b80e3a Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2023-08-05 10:28:44 +02:00
vabene1111
678963e6dd more debug in version script 2023-08-05 10:28:39 +02:00
vabene1111
b8e1ed8967 Merge pull request #2570 from TandoorRecipes/dependabot/pip/cryptography-41.0.3
Bump cryptography from 41.0.2 to 41.0.3
2023-08-05 09:45:13 +02:00
Chen
d87633433a Translated using Weblate (Hebrew)
Currently translated at 90.5% (471 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/he/
2023-08-03 22:19:55 +00:00
Chen
fe33adbba0 Translated using Weblate (Hebrew)
Currently translated at 25.7% (134 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/he/
2023-08-02 15:51:50 +00:00
Chen
baa84cf481 Added translation using Weblate (Hebrew) 2023-08-02 15:26:57 +00:00
dependabot[bot]
2b8c607b78 Bump cryptography from 41.0.2 to 41.0.3
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.3.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.3)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-02 02:23:22 +00:00
Mára Štěpánek
eac059ca85 Translated using Weblate (Czech)
Currently translated at 100.0% (362 of 362 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/cs/
2023-07-31 14:19:56 +00:00
vabene1111
782dd4cb17 build stuff 2023-07-29 11:24:11 +02:00
vabene1111
f7b60f2c52 version script improvements 2023-07-29 10:55:18 +02:00
vabene1111
ca28e52698 keep git installed 2023-07-29 10:06:51 +02:00
vabene1111
0c2c12d536 improved version script 2023-07-29 08:43:17 +02:00
vabene1111
113c40c243 changed version command order 2023-07-29 08:38:13 +02:00
vabene1111
0688f46d8b new version script 2023-07-29 08:32:10 +02:00
vabene1111
2fdcdba889 base pasth pdf viewer 2023-07-29 07:48:27 +02:00
vabene1111
6a39148e5f fixed try catch and added git to permanent dependency 2023-07-28 15:59:48 +02:00
vabene1111
22dfb40fd5 improved system info even more 2023-07-27 20:48:51 +02:00
vabene1111
2b5a86ce53 improved system page 2023-07-27 20:40:25 +02:00
vabene1111
e77016ea9b playing around 2023-07-27 18:49:39 +02:00
vabene1111
9988a61da7 added version number to system screen 2023-07-27 18:39:21 +02:00
vabene1111
f34fb8eec3 Merge pull request #2563 from smilerz/test_fixes
fixed rating sort order and updated tests
2023-07-26 06:21:54 +02:00
smilerz
7853357065 fix error when filtering on rating in saved filters 2023-07-25 17:48:19 -05:00
smilerz
6f1befc43c fixed rating sort order and updated tests 2023-07-25 11:37:48 -05:00
vabene1111
c18386b9b5 fixed copied ingredients being linked together 2023-07-22 12:59:31 +02:00
vabene1111
d5ba2e6716 improved multi url import 2023-07-22 11:18:06 +02:00
vabene1111
b30f8c245e added option to set URL on food 2023-07-22 09:12:45 +02:00
vabene1111
74c86f1b6b Merge pull request #2541 from titilambert/patch-1
Expose food description in food form
2023-07-22 08:28:39 +02:00
smilerz
cf9d599536 fixed sort by rating so that unrated are always last 2023-07-20 15:39:35 -05:00
vabene1111
14a67fd6c2 improved spinner rendering 2023-07-20 16:24:25 +02:00
vabene1111
413da01c5c Merge pull request #2554 from TandoorRecipes/dependabot/npm_and_yarn/vue/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /vue
2023-07-19 09:05:55 +02:00
dependabot[bot]
a73d231bd4 Bump word-wrap from 1.2.3 to 1.2.4 in /vue
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 07:05:07 +00:00
vabene1111
4f2392faac updated pyyaml to be compatible with cython 3 2023-07-19 09:04:01 +02:00
vabene1111
2321dcec6c Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-07-18 16:40:42 +02:00
vabene1111
c2cf7ba758 fixed test 2023-07-18 16:40:38 +02:00
vabene1111
239dd4aa60 Merge pull request #2481 from TandoorRecipes/dependabot/pip/pytube-15.0.0
Bump pytube from 12.1.0 to 15.0.0
2023-07-18 15:35:04 +02:00
vabene1111
a653b2e777 Merge pull request #2525 from TandoorRecipes/dependabot/pip/whitenoise-6.5.0
Bump whitenoise from 6.2.0 to 6.5.0
2023-07-18 15:34:52 +02:00
vabene1111
d8faee7e93 Merge pull request #2545 from TandoorRecipes/dependabot/pip/cryptography-41.0.2
Bump cryptography from 41.0.0 to 41.0.2
2023-07-18 15:32:29 +02:00
vabene1111
69417425e9 Merge branch 'develop' into dependabot/pip/cryptography-41.0.2 2023-07-18 15:32:23 +02:00
vabene1111
e8574a49a7 Merge pull request #2544 from TandoorRecipes/dependabot/npm_and_yarn/vue/semver-5.7.2
Bump semver from 5.7.1 to 5.7.2 in /vue
2023-07-18 15:31:59 +02:00
vabene1111
fe624cd218 Merge pull request #2536 from TandoorRecipes/dependabot/pip/django-4.1.10
Bump django from 4.1.9 to 4.1.10
2023-07-18 15:31:34 +02:00
vabene1111
1f10a66c74 added base unit to unit editor 2023-07-18 13:54:35 +02:00
vabene1111
a8f1cd26cd change guest recipe permission 2023-07-18 10:54:20 +02:00
vabene1111
a497a6b7f5 space api read for all users in space 2023-07-15 13:57:25 +02:00
dependabot[bot]
9dc144f2b5 Bump cryptography from 41.0.0 to 41.0.2
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.0 to 41.0.2.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.0...41.0.2)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-15 01:23:46 +00:00
Eirik Skarding
7d50f3cf21 Translated using Weblate (Norwegian Bokmål)
Currently translated at 68.9% (344 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nb_NO/
2023-07-12 21:19:57 +00:00
dependabot[bot]
315af4911c Bump semver from 5.7.1 to 5.7.2 in /vue
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-11 17:57:36 +00:00
vabene1111
35704c69c7 added option to pass recipe to recipe view 2023-07-11 17:50:48 +02:00
vabene1111
a24628c771 fixed userspace tetsts 2023-07-11 17:25:43 +02:00
vabene1111
e9748a160a addded paginated user space endpoint 2023-07-11 17:01:56 +02:00
Thibault Cohen
7bc78e104f Expose food description in food form 2023-07-10 21:26:26 -04:00
Mára Štěpánek
6f0dccfec9 Translated using Weblate (Czech)
Currently translated at 97.5% (487 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2023-07-06 21:19:59 +00:00
Rubens
76d6981dab Translated using Weblate (Catalan)
Currently translated at 85.1% (417 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ca/
2023-07-06 21:19:59 +00:00
dependabot[bot]
5df37c52dd Bump django from 4.1.9 to 4.1.10
Bumps [django](https://github.com/django/django) from 4.1.9 to 4.1.10.
- [Commits](https://github.com/django/django/compare/4.1.9...4.1.10)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-06 00:10:14 +00:00
vabene1111
7a2ccc075c improved shopping entry api endpoint performance 2023-07-04 16:49:56 +02:00
vabene1111
237054c23e improved commonly used administrative admin fields 2023-07-03 22:30:27 +02:00
vabene1111
ac1d641bd5 added RO DRF permission and internal_note filters for invite/userspace 2023-07-03 21:59:15 +02:00
vabene1111
3545b6e98a plugin loader improvements 2023-07-03 17:56:05 +02:00
vabene1111
d3a56e00ea allow disabling plugins 2023-07-03 07:41:56 +02:00
vabene1111
e9f8578c25 re added path to plugin check 2023-07-03 07:02:56 +02:00
vabene1111
dccfc436be Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-07-03 05:55:17 +02:00
vabene1111
1e85c8587b fixed plugin error message 2023-07-03 05:55:12 +02:00
vabene1111
b8f92ab054 Merge pull request #2531 from michael-genson/feature/add-source-url-to-recipe-export
Add source URL to recipe export
2023-07-03 05:47:31 +02:00
Mára Štěpánek
766ed31f8e Translated using Weblate (Czech)
Currently translated at 79.7% (398 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2023-07-02 21:19:57 +00:00
Michael Genson
cad78e115d added source url to recipe export 2023-07-02 10:42:41 -05:00
dependabot[bot]
ad7ebf1cd5 Bump whitenoise from 6.2.0 to 6.5.0
Bumps [whitenoise](https://github.com/evansd/whitenoise) from 6.2.0 to 6.5.0.
- [Changelog](https://github.com/evansd/whitenoise/blob/main/docs/changelog.rst)
- [Commits](https://github.com/evansd/whitenoise/compare/6.2.0...6.5.0)

---
updated-dependencies:
- dependency-name: whitenoise
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-01 00:03:23 +00:00
vabene1111
b599c4f6a9 added internal notes and improved invite link form 2023-06-30 23:09:22 +02:00
vabene1111
439539f56d show optional fields in generic forms 2023-06-30 23:09:01 +02:00
vabene1111
237bcb92c9 fixed food editor default properties unit 2023-06-29 17:26:49 +02:00
vabene1111
ce02a23dbb fixed quick ingredient import in recipe editor 2023-06-29 17:13:53 +02:00
vabene1111
8e81512735 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-06-29 17:05:37 +02:00
vabene1111
c69f0394a8 possibly fixed bug with food editor ingredient delete page reload 2023-06-29 17:05:32 +02:00
vabene1111
d7ca9e05de Merge pull request #2521 from gloriousDan/improve-docs
add note to docker-compose files and update postgres tag
2023-06-29 17:04:31 +02:00
vabene1111
64534ff810 fixed navbar color for non logged in users 2023-06-29 17:03:05 +02:00
vabene1111
d0164a6c28 Merge pull request #2522 from gloriousDan/fix-raspi
Fix Raspi build and consolidate with normal build and image
2023-06-27 16:10:39 +02:00
Daniel Schulz
0f898ddf4a unify raspi and normal build again 2023-06-27 00:51:55 +02:00
Daniel Schulz
e903382034 update alpine to v3.18 2023-06-27 00:51:22 +02:00
Daniel Schulz
0d225450da add note to docker-compose files and update postgres tag 2023-06-27 00:33:29 +02:00
vabene1111
c077a64484 further improvements 2023-06-26 20:57:51 +02:00
vabene1111
6c16094b42 added initial version of tandoor dark theme 2023-06-26 20:43:50 +02:00
vabene1111
5aa80746f9 Merge branch 'develop' 2023-06-26 20:25:58 +02:00
vabene1111
cc64717818 auto add schema attrs in json importer 2023-06-26 20:22:59 +02:00
vabene1111
6acd892116 fixed broken image would fail default importer 2023-06-26 20:18:36 +02:00
vabene1111
3955408aa4 dont show properties view if no properties are present in DB 2023-06-26 20:03:25 +02:00
vabene1111
3de2468df3 fixed to light nav color in some themes 2023-06-26 19:57:38 +02:00
vabene1111
b1d983fbc3 fixed required field in food 2023-06-26 17:08:45 +02:00
vabene1111
5f443d2593 fixed issue when creating food with properties 2023-06-26 16:48:50 +02:00
vabene1111
436158f596 fixed allow decimals in food property amount 2023-06-26 15:47:44 +02:00
vabene1111
dcc56fc138 added new docs entry to nav 2023-06-26 15:21:05 +02:00
vabene1111
0eef10079b Merge pull request #2517 from 16cdlogan/patch-1
Create Truenas-Portainer
2023-06-26 15:19:03 +02:00
16cdlogan
2b839dfb19 Create Truenas-Portainer
Install Tandoor Recipes on TrueNAS Core and Portainer
2023-06-25 21:32:54 -04:00
sweeney
491b678d6e Translated using Weblate (Greek)
Currently translated at 1.4% (7 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/el/
2023-06-25 14:19:55 +00:00
sweeney
151dce006d Translated using Weblate (Greek)
Currently translated at 54.7% (287 of 524 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/el/
2023-06-25 14:19:55 +00:00
sweeney
d4f538b4aa Translated using Weblate (Greek)
Currently translated at 35.4% (186 of 524 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/el/
2023-06-24 13:32:57 +00:00
sweeney
a727439c57 Added translation using Weblate (Greek) 2023-06-24 13:32:57 +00:00
dependabot[bot]
991a51d55e Bump pytube from 12.1.0 to 15.0.0
Bumps [pytube](https://github.com/pytube/pytube) from 12.1.0 to 15.0.0.
- [Release notes](https://github.com/pytube/pytube/releases)
- [Commits](https://github.com/pytube/pytube/compare/v12.1.0...v15.0.0)

---
updated-dependencies:
- dependency-name: pytube
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-01 00:57:43 +00:00
76 changed files with 17073 additions and 1060 deletions

View File

@@ -3,7 +3,6 @@ npm-debug.log
Dockerfile*
docker-compose*
.dockerignore
.git
.gitignore
README.md
LICENSE

View File

@@ -34,16 +34,6 @@ jobs:
echo VERSION=develop >> $GITHUB_OUTPUT
fi
# Update Version number
- name: Update version file
uses: DamianReeves/write-file-action@v1.2
with:
path: recipes/version.py
contents: |
VERSION_NUMBER = '${{ steps.get_version.outputs.VERSION }}-open-data'
BUILD_REF = '${{ github.sha }}'
write-mode: overwrite
# clone open data plugin
- name: clone open data plugin repo
uses: actions/checkout@master

View File

@@ -17,15 +17,9 @@ jobs:
# Standard build config
- name: Standard
dockerfile: Dockerfile
platforms: linux/amd64,linux/arm64
platforms: linux/amd64,linux/arm64,linux/arm/v7
suffix: ""
continue-on-error: false
# Raspi build config
- name: Raspi
dockerfile: Dockerfile-raspi
platforms: linux/arm/v7
suffix: "-raspi"
continue-on-error: true
steps:
- uses: actions/checkout@v3
@@ -40,16 +34,6 @@ jobs:
echo VERSION=develop >> $GITHUB_OUTPUT
fi
# Update Version number
- name: Update version file
uses: DamianReeves/write-file-action@v1.2
with:
path: recipes/version.py
contents: |
VERSION_NUMBER = '${{ steps.get_version.outputs.VERSION }}'
BUILD_REF = '${{ github.sha }}'
write-mode: overwrite
# Build Vue frontend
- uses: actions/setup-node@v3
with:

View File

@@ -1,7 +1,7 @@
FROM python:3.10-alpine3.15
FROM python:3.10-alpine3.18
#Install all dependencies.
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography openldap
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev openldap git
#Print all logs without buffering it.
ENV PYTHONUNBUFFERED 1
@@ -15,7 +15,11 @@ WORKDIR /opt/recipes
COPY requirements.txt ./
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev git && \
RUN \
if [ `apk --print-arch` = "armv7" ]; then \
printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \
fi
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev && \
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
python -m venv venv && \
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
@@ -26,5 +30,11 @@ RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-de
#Copy project and execute it.
COPY . ./
# collect information from git repositories
RUN /opt/recipes/venv/bin/python version.py
# delete git repositories to reduce image size
RUN find . -type d -name ".git" | xargs rm -rf
RUN chmod +x boot.sh
ENTRYPOINT ["/opt/recipes/boot.sh"]

View File

@@ -1,33 +0,0 @@
# builds of cryptography for raspberry pi (or better arm v7) fail for some
FROM python:3.9-alpine3.15
#Install all dependencies.
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography openldap gcompat
#Print all logs without buffering it.
ENV PYTHONUNBUFFERED 1
#This port will be used by gunicorn.
EXPOSE 8080
#Create app dir and install requirements.
RUN mkdir /opt/recipes
WORKDIR /opt/recipes
COPY requirements.txt ./
RUN \
if [ `apk --print-arch` = "armv7" ]; then \
printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \
fi
RUN apk add --no-cache --virtual .build-deps gcc musl-dev zlib-dev jpeg-dev libwebp-dev python3-dev git && \
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
python -m venv venv && \
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
venv/bin/pip install wheel==0.37.1 && \
venv/bin/pip install -r requirements.txt --no-cache-dir --no-binary=Pillow && \
apk --purge del .build-deps
#Copy project and execute it.
COPY . ./
RUN chmod +x boot.sh
ENTRYPOINT ["/opt/recipes/boot.sh"]

View File

@@ -39,6 +39,8 @@ def delete_space_action(modeladmin, request, queryset):
class SpaceAdmin(admin.ModelAdmin):
list_display = ('name', 'created_by', 'max_recipes', 'max_users', 'max_file_storage_mb', 'allow_sharing')
search_fields = ('name', 'created_by__username')
autocomplete_fields = ('created_by',)
filter_horizontal = ('food_inherit',)
list_filter = ('max_recipes', 'max_users', 'max_file_storage_mb', 'allow_sharing')
date_hierarchy = 'created_at'
actions = [delete_space_action]
@@ -50,6 +52,8 @@ admin.site.register(Space, SpaceAdmin)
class UserSpaceAdmin(admin.ModelAdmin):
list_display = ('user', 'space',)
search_fields = ('user__username', 'space__name',)
filter_horizontal = ('groups',)
autocomplete_fields = ('user', 'space',)
admin.site.register(UserSpace, UserSpaceAdmin)
@@ -60,6 +64,7 @@ class UserPreferenceAdmin(admin.ModelAdmin):
search_fields = ('user__username',)
list_filter = ('theme', 'nav_color', 'default_page',)
date_hierarchy = 'created_at'
filter_horizontal = ('plan_share', 'shopping_share',)
@staticmethod
def name(obj):
@@ -309,6 +314,7 @@ admin.site.register(InviteLink, InviteLinkAdmin)
class CookLogAdmin(admin.ModelAdmin):
list_display = ('recipe', 'created_by', 'created_at', 'rating', 'servings')
search_fields = ('recipe__name', 'space__name',)
admin.site.register(CookLog, CookLogAdmin)

View File

@@ -322,7 +322,7 @@ class CustomRecipePermission(permissions.BasePermission):
def has_permission(self, request, view): # user is either at least a guest or a share link is given and the request is safe
share = request.query_params.get('share', None)
return has_group_permission(request.user, ['guest']) or (share and request.method in SAFE_METHODS and 'pk' in view.kwargs)
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS) or has_group_permission(request.user, ['user'])) or (share and request.method in SAFE_METHODS and 'pk' in view.kwargs)
def has_object_permission(self, request, view, obj):
share = request.query_params.get('share', None)
@@ -332,7 +332,7 @@ class CustomRecipePermission(permissions.BasePermission):
if obj.private:
return ((obj.created_by == request.user) or (request.user in obj.shared.all())) and obj.space == request.space
else:
return has_group_permission(request.user, ['guest']) and obj.space == request.space
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS) or has_group_permission(request.user, ['user'])) and obj.space == request.space
class CustomUserPermission(permissions.BasePermission):
@@ -434,3 +434,10 @@ def switch_user_active_space(user, space):
return us
except ObjectDoesNotExist:
return None
class IsReadOnlyDRF(permissions.BasePermission):
message = 'You cannot interact with this object as it is not owned by you!'
def has_permission(self, request, view):
return request.method in SAFE_METHODS

View File

@@ -32,6 +32,9 @@ class RecipeSearch():
if custom_filter:
self._params = {**json.loads(custom_filter.search)}
self._original_params = {**(params or {})}
# json.loads casts rating as an integer, expecting string
if isinstance(self._params.get('rating', None), int):
self._params['rating'] = str(self._params['rating'])
else:
self._params = {**(params or {})}
else:
@@ -85,9 +88,9 @@ class RecipeSearch():
self._viewedon = self._params.get('viewedon', None)
self._makenow = self._params.get('makenow', None)
# this supports hidden feature to find recipes missing X ingredients
if type(self._makenow) == bool and self._makenow == True:
if isinstance(self._makenow, bool) and self._makenow == True:
self._makenow = 0
elif type(self._makenow) == str and self._makenow in ["yes", "true"]:
elif isinstance(self._makenow, str) and self._makenow in ["yes", "true"]:
self._makenow = 0
else:
try:
@@ -150,7 +153,7 @@ class RecipeSearch():
self.unit_filters(units=self._units)
self._makenow_filter(missing=self._makenow)
self.string_filters(string=self._string)
return self._queryset.filter(space=self._request.space).distinct().order_by(*self.orderby)
return self._queryset.filter(space=self._request.space).order_by(*self.orderby)
def _sort_includes(self, *args):
for x in args:
@@ -434,22 +437,21 @@ class RecipeSearch():
def rating_filter(self, rating=None):
if rating or self._sort_includes('rating'):
lessthan = self._sort_includes('-rating') or '-' in (rating or [])
if lessthan:
lessthan = '-' in (rating or [])
reverse = 'rating' in (self._sort_order or []) and '-rating' not in (self._sort_order or [])
if lessthan or reverse:
default = 100
else:
default = 0
# TODO make ratings a settings user-only vs all-users
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(
cooklog__created_by=self._request.user, then='cooklog__rating'), default=default))))
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(cooklog__created_by=self._request.user, then='cooklog__rating'), default=default))))
if rating is None:
return
if rating == '0':
self._queryset = self._queryset.filter(rating=0)
elif lessthan:
self._queryset = self._queryset.filter(
rating__lte=int(rating[1:])).exclude(rating=0)
self._queryset = self._queryset.filter(rating__lte=int(rating[1:])).exclude(rating=0)
else:
self._queryset = self._queryset.filter(rating__gte=int(rating))
@@ -560,7 +562,7 @@ class RecipeSearch():
self._filters += [Q(pk__in=self._fuzzy_match.values('pk'))]
def _makenow_filter(self, missing=None):
if missing is None or (type(missing) == bool and missing == False):
if missing is None or (isinstance(missing, bool) and missing == False):
return
shopping_users = [
*self._request.user.get_shopping_share(), self._request.user]

View File

@@ -1,4 +1,5 @@
import json
import traceback
from io import BytesIO, StringIO
from re import match
from zipfile import ZipFile
@@ -19,7 +20,10 @@ class Default(Integration):
recipe = self.decode_recipe(recipe_string)
images = list(filter(lambda v: match('image.*', v), recipe_zip.namelist()))
if images:
self.import_recipe_image(recipe, BytesIO(recipe_zip.read(images[0])), filetype=get_filetype(images[0]))
try:
self.import_recipe_image(recipe, BytesIO(recipe_zip.read(images[0])), filetype=get_filetype(images[0]))
except AttributeError as e:
traceback.print_exc()
return recipe
def decode_recipe(self, string):

View File

@@ -13,8 +13,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"PO-Revision-Date: 2023-07-06 21:19+0000\n"
"Last-Translator: Rubens <rubenixnagios@gmail.com>\n"
"Language-Team: Catalan <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/ca/>\n"
"Language: ca\n"
@@ -421,7 +421,7 @@ msgstr "Compartir Llista de la Compra"
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "Autosync"
msgstr "Autosinc"
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
@@ -477,7 +477,7 @@ msgstr "Mostra el recompte de receptes als filtres de cerca"
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""
msgstr "Empra el plural d'aquestes unitats i menjars dins de l'espai."
#: .\cookbook\helper\AllAuthCustomAdapter.py:39
msgid ""

View File

@@ -11,8 +11,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
"PO-Revision-Date: 2023-03-25 11:32+0000\n"
"Last-Translator: Matěj Kubla <matykubla@gmail.com>\n"
"PO-Revision-Date: 2023-07-31 14:19+0000\n"
"Last-Translator: Mára Štěpánek <stepanekm7@gmail.com>\n"
"Language-Team: Czech <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/cs/>\n"
"Language: cs\n"
@@ -36,7 +36,7 @@ msgid ""
"try them out!"
msgstr ""
"Barva horního navigačního menu. Některé barvy neladí se všemi tématy a je "
"třeba je vyzkoušet."
"třeba je vyzkoušet!"
#: .\cookbook\forms.py:45
msgid "Default Unit to be used when inserting a new ingredient into a recipe."
@@ -50,7 +50,7 @@ msgid ""
"to fractions automatically)"
msgstr ""
"Povolit podporu zlomků u množství ingrediencí (desetinná čísla budou "
"automaticky převedena na zlomky)."
"automaticky převedena na zlomky)"
#: .\cookbook\forms.py:47
msgid ""

View File

@@ -15,8 +15,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-06-21 14:19+0000\n"
"Last-Translator: Tobias Huppertz <tobias.huppertz@mail.de>\n"
"PO-Revision-Date: 2023-08-13 08:19+0000\n"
"Last-Translator: Fabian Flodman <fabian@flodman.de>\n"
"Language-Team: German <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/de/>\n"
"Language: de\n"
@@ -1436,11 +1436,11 @@ msgid ""
" "
msgstr ""
"\n"
" <b>Password und Token</b> werden im <b>Klartext</b> in der Datenbank "
" <b>Passwort und Token</b> werden im <b>Klartext</b> in der Datenbank "
"gespeichert.\n"
" Dies ist notwendig da Passwort oder Token benötigt werden, um API-"
"Anfragen zu stellen, bringt jedoch auch ein Sicherheitsrisiko mit sich. <br/"
">\n"
"Anfragen zu stellen, bringt jedoch auch ein Sicherheitsrisiko mit sich. <br/>"
"\n"
" Um das Risiko zu minimieren sollten, wenn möglich, Tokens oder "
"Accounts mit limitiertem Zugriff verwendet werden.\n"
" "
@@ -2600,7 +2600,7 @@ msgstr "Ungültiges URL Schema."
#: .\cookbook\views\api.py:1233
msgid "No usable data could be found."
msgstr "Es konnten keine nutzbaren Daten gefunden werden."
msgstr "Es konnten keine passenden Daten gefunden werden."
#: .\cookbook\views\api.py:1326 .\cookbook\views\import_export.py:117
msgid "Importing is not implemented for this provider"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-12 19:20+0200\n"
"PO-Revision-Date: 2023-06-23 09:19+0000\n"
"PO-Revision-Date: 2023-06-25 14:19+0000\n"
"Last-Translator: sweeney <sweeneytodd91@protonmail.com>\n"
"Language-Team: Greek <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/el/>\n"
@@ -262,6 +262,8 @@ msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
msgstr ""
"Μπορείτε να χρησιμοποιήσετε τη μορφοποίηση Markdown για να διαμορφώσετε αυτό "
"το πεδίο. Δείτε τα <a href=\"/docs/markdown/\">έγγραφα εδώ</a>"
#: .\cookbook\forms.py:366
msgid "Maximum number of users for this space reached."
@@ -309,6 +311,8 @@ msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
msgstr ""
"Χρησιμοποιήστε ασαφείς (fuzzy) αντιστοιχίες σε μονάδες μέτρησης, λέξεις-"
"κλειδιά και συστατικά κατά την επεξεργασία και εισαγωγή συνταγών."
#: .\cookbook\forms.py:451
msgid ""
@@ -323,6 +327,8 @@ msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
msgstr ""
"Πεδία για αναζήτηση μερικών αντιστοιχιών. (π.χ. αναζήτηση για 'πίτα' τα "
"'τυρόπιτα' και 'απιτα' θα βρίσκονται στα αποτελέσματα)"
#: .\cookbook\forms.py:455
msgid ""
@@ -420,7 +426,7 @@ msgstr ""
#: .\cookbook\forms.py:506
msgid "Delimiter to use for CSV exports."
msgstr ""
msgstr "Το σημείο στίξης διαχωρισμού δεκαδικών για τις εξαγωγές σε αρχεία CSV."
#: .\cookbook\forms.py:507
msgid "Prefix to add when copying list to the clipboard."
@@ -454,7 +460,7 @@ msgstr "Προεπιλεγμένες ώρες καθυστέρησης"
#: .\cookbook\forms.py:517
msgid "Filter to Supermarket"
msgstr ""
msgstr "Ταξινόμηση ανά Supermarket"
#: .\cookbook\forms.py:518
msgid "Recent Days"
@@ -462,7 +468,7 @@ msgstr "Πρόσφατες ημέρες"
#: .\cookbook\forms.py:519
msgid "CSV Delimiter"
msgstr ""
msgstr "CSV σημείο στίξης διαχωρισμού δεκαδικών"
#: .\cookbook\forms.py:520
msgid "List Prefix"
@@ -474,7 +480,7 @@ msgstr "Αυτόματα διαθέσιμο"
#: .\cookbook\forms.py:531
msgid "Reset Food Inheritance"
msgstr ""
msgstr "Επαναφορά κληρονομιάς φαγητών"
#: .\cookbook\forms.py:532
msgid "Reset all food to inherit the fields configured."
@@ -531,7 +537,7 @@ msgstr "Έχετε περισσότερους χρήστες από το επι
#: .\cookbook\helper\recipe_search.py:565
msgid "One of queryset or hash_key must be provided"
msgstr ""
msgstr "Πρέπει να παρέχετε είτε το queryset είτε το hash_key"
#: .\cookbook\helper\shopping_helper.py:152
msgid "You must supply a servings size"
@@ -619,6 +625,8 @@ msgstr "Αναδόμηση πλήρους ευρετηρίου αναζήτησ
#: .\cookbook\management\commands\rebuildindex.py:18
msgid "Only Postgresql databases use full text search, no index to rebuild"
msgstr ""
"Μόνο οι βάσεις δεδομένων Postgresql χρησιμοποιούν αναζήτηση πλήρους "
"κειμένου, δεν υπάρχει ανάγκη ανασύνθεσης των ευρετηρίων"
#: .\cookbook\management\commands\rebuildindex.py:29
msgid "Recipe index rebuild complete."
@@ -780,13 +788,15 @@ msgstr "Πρόσκληση στο Tandoor Recipes"
#: .\cookbook\serializer.py:1209
msgid "Existing shopping list to update"
msgstr ""
msgstr "Υπάρχουσα λίστα αγορών για ενημέρωση"
#: .\cookbook\serializer.py:1211
msgid ""
"List of ingredient IDs from the recipe to add, if not provided all "
"ingredients will be added."
msgstr ""
"Λίστα αναγνωριστικών συστατικών (ID) από τη συνταγή προς προσθήκη. Εάν δεν "
"παρέχονται όλα τα συστατικά θα προστεθούν."
#: .\cookbook\serializer.py:1213
msgid ""
@@ -795,21 +805,23 @@ msgstr ""
#: .\cookbook\serializer.py:1222
msgid "Amount of food to add to the shopping list"
msgstr ""
msgstr "Ποσότητα του φαγητού που θα προστεθεί στη λίστα αγορών"
#: .\cookbook\serializer.py:1224
msgid "ID of unit to use for the shopping list"
msgstr ""
msgstr "Το ID της μονάδας μέτρησης που θα χρησιμοποιείται στη λίστα αγορών"
#: .\cookbook\serializer.py:1226
msgid "When set to true will delete all food from active shopping lists."
msgstr ""
"Όταν οριστεί σε true, θα διαγραφούν όλα τα τρόφιμα από τις ενεργές λίστες "
"αγορών."
#: .\cookbook\tables.py:36 .\cookbook\templates\generic\edit_template.html:6
#: .\cookbook\templates\generic\edit_template.html:14
#: .\cookbook\templates\recipes_table.html:82
msgid "Edit"
msgstr ""
msgstr "Τροποποίηση"
#: .\cookbook\tables.py:116 .\cookbook\tables.py:131
#: .\cookbook\templates\generic\delete_template.html:7
@@ -817,28 +829,28 @@ msgstr ""
#: .\cookbook\templates\generic\edit_template.html:28
#: .\cookbook\templates\recipes_table.html:90
msgid "Delete"
msgstr ""
msgstr "Διαγραφή"
#: .\cookbook\templates\404.html:5
msgid "404 Error"
msgstr ""
msgstr "404 Error"
#: .\cookbook\templates\404.html:18
msgid "The page you are looking for could not be found."
msgstr ""
msgstr "Η σελίδα που αναζητάτε δεν μπορεί να βρεθεί."
#: .\cookbook\templates\404.html:33
msgid "Take me Home"
msgstr ""
msgstr "Πήγαινε με στη αρχική σελίδα"
#: .\cookbook\templates\404.html:35
msgid "Report a Bug"
msgstr ""
msgstr "Αναφορά σφάλματος"
#: .\cookbook\templates\account\email.html:6
#: .\cookbook\templates\account\email.html:17
msgid "E-mail Addresses"
msgstr ""
msgstr "Διευθύνσεις e-mail"
#: .\cookbook\templates\account\email.html:12
#: .\cookbook\templates\account\password_change.html:11
@@ -847,68 +859,71 @@ msgstr ""
#: .\cookbook\templates\settings.html:17
#: .\cookbook\templates\socialaccount\connections.html:10
msgid "Settings"
msgstr ""
msgstr "Ρυθμίσεις"
#: .\cookbook\templates\account\email.html:13
msgid "Email"
msgstr ""
msgstr "Email"
#: .\cookbook\templates\account\email.html:19
msgid "The following e-mail addresses are associated with your account:"
msgstr ""
msgstr "Οι παρακάτω διευθύνσεις e-mail συνδέονται με τον λογαριασμό σας:"
#: .\cookbook\templates\account\email.html:36
msgid "Verified"
msgstr ""
msgstr "Πιστοποιημένο"
#: .\cookbook\templates\account\email.html:38
msgid "Unverified"
msgstr ""
msgstr "Μη πιστοποιημένο"
#: .\cookbook\templates\account\email.html:40
msgid "Primary"
msgstr ""
msgstr "Κύριο"
#: .\cookbook\templates\account\email.html:47
msgid "Make Primary"
msgstr ""
msgstr "Μετατροπή σε κύριο"
#: .\cookbook\templates\account\email.html:49
msgid "Re-send Verification"
msgstr ""
msgstr "Επαναποστολή της επαλήθευσης"
#: .\cookbook\templates\account\email.html:50
#: .\cookbook\templates\generic\delete_template.html:57
#: .\cookbook\templates\socialaccount\connections.html:44
msgid "Remove"
msgstr ""
msgstr "Αφαίρεση"
#: .\cookbook\templates\account\email.html:58
msgid "Warning:"
msgstr ""
msgstr "Προειδοποίηση:"
#: .\cookbook\templates\account\email.html:58
msgid ""
"You currently do not have any e-mail address set up. You should really add "
"an e-mail address so you can receive notifications, reset your password, etc."
msgstr ""
"Προς το παρόν, δεν έχετε καμία διεύθυνση e-mail καταχωρημένη. Θα πρέπει να "
"προσθέσετε μια διεύθυνση ηλεκτρονικού ταχυδρομείου, ώστε να μπορείτε να "
"λαμβάνετε ειδοποιήσεις, να επαναφέρετε τον κωδικό πρόσβασης, κ.λπ."
#: .\cookbook\templates\account\email.html:64
msgid "Add E-mail Address"
msgstr ""
msgstr "Προσθήκη διεύθυνσης e-mail"
#: .\cookbook\templates\account\email.html:69
msgid "Add E-mail"
msgstr ""
msgstr "Προσθήκη e-mail"
#: .\cookbook\templates\account\email.html:79
msgid "Do you really want to remove the selected e-mail address?"
msgstr ""
msgstr "Θέλετε πραγματικά να αφαιρέσετε την επιλεγμένη διεύθυνση e-mail;"
#: .\cookbook\templates\account\email_confirm.html:6
#: .\cookbook\templates\account\email_confirm.html:10
msgid "Confirm E-mail Address"
msgstr ""
msgstr "Επιβεβαίωση διεύθυνσης e-mail"
#: .\cookbook\templates\account\email_confirm.html:16
#, python-format
@@ -918,11 +933,15 @@ msgid ""
"for user %(user_display)s\n"
" ."
msgstr ""
"Παρακαλώ επιβεβαιώστε ότι το\n"
" <a href=\"mailto:%(email)s\">%(email)s</a> είναι μια διεύθυνση "
"e-mail για τον χρήστη %(user_display)s\n"
" ."
#: .\cookbook\templates\account\email_confirm.html:22
#: .\cookbook\templates\generic\delete_template.html:72
msgid "Confirm"
msgstr ""
msgstr "Επιβεβαίωση"
#: .\cookbook\templates\account\email_confirm.html:29
#, python-format
@@ -931,11 +950,15 @@ msgid ""
" <a href=\"%(email_url)s\">issue a new e-mail confirmation "
"request</a>."
msgstr ""
"Αυτός ο σύνδεσμος επιβεβαίωσης έχει λήξει είναι δεν είναι έγκυρος. Παρακαλώ "
"\n"
" <a href=\"%(email_url)s\">κάντε ένα νέο αίτημα για επιβεβαιωτικό "
"e-mail</a>."
#: .\cookbook\templates\account\login.html:8
#: .\cookbook\templates\base.html:340 .\cookbook\templates\openid\login.html:8
msgid "Login"
msgstr ""
msgstr "Σύνδεση"
#: .\cookbook\templates\account\login.html:15
#: .\cookbook\templates\account\login.html:31
@@ -945,41 +968,43 @@ msgstr ""
#: .\cookbook\templates\openid\login.html:26
#: .\cookbook\templates\socialaccount\authentication_error.html:15
msgid "Sign In"
msgstr ""
msgstr "Σύνδεση"
#: .\cookbook\templates\account\login.html:34
#: .\cookbook\templates\socialaccount\signup.html:8
#: .\cookbook\templates\socialaccount\signup.html:57
msgid "Sign Up"
msgstr ""
msgstr "Εγγραφή"
#: .\cookbook\templates\account\login.html:39
#: .\cookbook\templates\account\login.html:41
#: .\cookbook\templates\account\password_reset.html:29
msgid "Reset My Password"
msgstr ""
msgstr "Επαναφορά κωδικού πρόσβασης"
#: .\cookbook\templates\account\login.html:40
msgid "Lost your password?"
msgstr ""
msgstr "Χασάτε τον κωδικό πρόσβασης;"
#: .\cookbook\templates\account\login.html:52
msgid "Social Login"
msgstr ""
msgstr "Σύνδεση με social media"
#: .\cookbook\templates\account\login.html:53
msgid "You can use any of the following providers to sign in."
msgstr ""
"Μπορείτε να χρησιμοποιήσετε οποιονδήποτε από τους παρακάτω παρόχους για να "
"συνδεθείτε."
#: .\cookbook\templates\account\logout.html:5
#: .\cookbook\templates\account\logout.html:9
#: .\cookbook\templates\account\logout.html:18
msgid "Sign Out"
msgstr ""
msgstr "Αποσύνδεση"
#: .\cookbook\templates\account\logout.html:11
msgid "Are you sure you want to sign out?"
msgstr ""
msgstr "Είστε σίγουροι ότι θέλετε να αποσυνδεθείτε;"
#: .\cookbook\templates\account\password_change.html:6
#: .\cookbook\templates\account\password_change.html:16
@@ -989,44 +1014,50 @@ msgstr ""
#: .\cookbook\templates\account\password_reset_from_key_done.html:7
#: .\cookbook\templates\account\password_reset_from_key_done.html:13
msgid "Change Password"
msgstr ""
msgstr "Αλλαγή κωδικού πρόσβασης"
#: .\cookbook\templates\account\password_change.html:12
#: .\cookbook\templates\account\password_set.html:12
#: .\cookbook\templates\settings.html:76
msgid "Password"
msgstr ""
msgstr "Κωδικός πρόσβασης"
#: .\cookbook\templates\account\password_change.html:22
msgid "Forgot Password?"
msgstr ""
msgstr "Ξεχάσατε τον κωδικό πρόσβασης;"
#: .\cookbook\templates\account\password_reset.html:7
#: .\cookbook\templates\account\password_reset.html:13
#: .\cookbook\templates\account\password_reset_done.html:7
#: .\cookbook\templates\account\password_reset_done.html:10
msgid "Password Reset"
msgstr ""
msgstr "Επαναφορά κωδικού πρόσβασης"
#: .\cookbook\templates\account\password_reset.html:24
msgid ""
"Forgotten your password? Enter your e-mail address below, and we'll send you "
"an e-mail allowing you to reset it."
msgstr ""
"Ξεχάσατε τον κωδικό πρόσβασης σας; Εισάγετε τη διεύθυνση ηλεκτρονικού "
"ταχυδρομείου σας παρακάτω και θα σας στείλουμε ένα email που θα σας "
"επιτρέψει να τον επαναφέρετε."
#: .\cookbook\templates\account\password_reset.html:32
msgid "Password reset is disabled on this instance."
msgstr ""
"Η επαναφορά κωδικού πρόσβασης είναι απενεργοποιημένη σε αυτήν την πλατφόρμα."
#: .\cookbook\templates\account\password_reset_done.html:16
msgid ""
"We have sent you an e-mail. Please contact us if you do not receive it "
"within a few minutes."
msgstr ""
"Σας έχουμε στείλει ένα email. Παρακαλούμε επικοινωνήστε μαζί μας αν δεν το "
"λάβετε εντός λίγων λεπτών."
#: .\cookbook\templates\account\password_reset_from_key.html:13
msgid "Bad Token"
msgstr ""
msgstr "Μη έγκυρο token"
#: .\cookbook\templates\account\password_reset_from_key.html:25
#, python-format
@@ -1036,168 +1067,172 @@ msgid ""
" Please request a <a href=\"%(passwd_reset_url)s\">new "
"password reset</a>."
msgstr ""
"Ο σύνδεσμος επαναφοράς κωδικού πρόσβασης ήταν άκυρος, πιθανώς επειδή έχει "
"ήδη χρησιμοποιηθεί.\n"
" Παρακαλώ ζητήστε έναν <a href=\"%(passwd_reset_url)s\""
">νέο σύνδεσμο επαναφοράς κωδικού πρόσβασης</a>."
#: .\cookbook\templates\account\password_reset_from_key.html:33
msgid "change password"
msgstr ""
msgstr "Αλλαγή κωδικού πρόσβασης"
#: .\cookbook\templates\account\password_reset_from_key.html:36
#: .\cookbook\templates\account\password_reset_from_key_done.html:19
msgid "Your password is now changed."
msgstr ""
msgstr "Ο κωδικός πρόσβασης σας έχει αλλάξει."
#: .\cookbook\templates\account\password_set.html:6
#: .\cookbook\templates\account\password_set.html:16
#: .\cookbook\templates\account\password_set.html:21
msgid "Set Password"
msgstr ""
msgstr "Ορισμός Κωδικού Πρόσβασης"
#: .\cookbook\templates\account\signup.html:6
msgid "Register"
msgstr ""
msgstr "Εγγραφή"
#: .\cookbook\templates\account\signup.html:12
msgid "Create an Account"
msgstr ""
msgstr "Δημιουργία λογαριασμού"
#: .\cookbook\templates\account\signup.html:42
#: .\cookbook\templates\socialaccount\signup.html:33
msgid "I accept the follwoing"
msgstr ""
msgstr "Αποδέχομαι τα παρακάτω"
#: .\cookbook\templates\account\signup.html:45
#: .\cookbook\templates\socialaccount\signup.html:36
msgid "Terms and Conditions"
msgstr ""
msgstr "Όροι και προϋποθέσεις"
#: .\cookbook\templates\account\signup.html:48
#: .\cookbook\templates\socialaccount\signup.html:39
msgid "and"
msgstr ""
msgstr "και"
#: .\cookbook\templates\account\signup.html:52
#: .\cookbook\templates\socialaccount\signup.html:43
msgid "Privacy Policy"
msgstr ""
msgstr "Πολιτική απορρήτου"
#: .\cookbook\templates\account\signup.html:65
msgid "Create User"
msgstr ""
msgstr "Δημιουργία χρήστη"
#: .\cookbook\templates\account\signup.html:69
msgid "Already have an account?"
msgstr ""
msgstr "Έχετε ήδη λογαριασμό;"
#: .\cookbook\templates\account\signup_closed.html:5
#: .\cookbook\templates\account\signup_closed.html:11
msgid "Sign Up Closed"
msgstr ""
msgstr "Οι εγγραφές έκλεισαν"
#: .\cookbook\templates\account\signup_closed.html:13
msgid "We are sorry, but the sign up is currently closed."
msgstr ""
msgstr "Λυπούμαστε, αλλά οι εγγραφές έχουν ήδη κλείσει."
#: .\cookbook\templates\api_info.html:5 .\cookbook\templates\base.html:330
#: .\cookbook\templates\rest_framework\api.html:11
msgid "API Documentation"
msgstr ""
msgstr "Τεκμηρίωση API"
#: .\cookbook\templates\base.html:103 .\cookbook\templates\index.html:87
#: .\cookbook\templates\stats.html:22
msgid "Recipes"
msgstr ""
msgstr "Συνταγές"
#: .\cookbook\templates\base.html:111
msgid "Shopping"
msgstr ""
msgstr "Αγορές"
#: .\cookbook\templates\base.html:150 .\cookbook\views\lists.py:105
msgid "Foods"
msgstr ""
msgstr "Φαγητά"
#: .\cookbook\templates\base.html:162
#: .\cookbook\templates\forms\ingredients.html:24
#: .\cookbook\templates\stats.html:26 .\cookbook\views\lists.py:122
msgid "Units"
msgstr ""
msgstr "Μονάδες μέτρησης"
#: .\cookbook\templates\base.html:176 .\cookbook\templates\supermarket.html:7
msgid "Supermarket"
msgstr ""
msgstr "Supermarket"
#: .\cookbook\templates\base.html:188
msgid "Supermarket Category"
msgstr ""
msgstr "Κατηγορία Supermarket"
#: .\cookbook\templates\base.html:200 .\cookbook\views\lists.py:171
msgid "Automations"
msgstr ""
msgstr "Αυτοματισμοί"
#: .\cookbook\templates\base.html:214 .\cookbook\views\lists.py:207
msgid "Files"
msgstr ""
msgstr "Αρχεία"
#: .\cookbook\templates\base.html:226
msgid "Batch Edit"
msgstr ""
msgstr "Μαζική Επεξεργασία"
#: .\cookbook\templates\base.html:238 .\cookbook\templates\history.html:6
#: .\cookbook\templates\history.html:14
msgid "History"
msgstr ""
msgstr "Ιστορικό"
#: .\cookbook\templates\base.html:252
#: .\cookbook\templates\ingredient_editor.html:7
#: .\cookbook\templates\ingredient_editor.html:13
msgid "Ingredient Editor"
msgstr ""
msgstr "Επεξεργαστής Συστατικών"
#: .\cookbook\templates\base.html:264
#: .\cookbook\templates\export_response.html:7
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
msgid "Export"
msgstr ""
msgstr "Εξαγωγή"
#: .\cookbook\templates\base.html:280 .\cookbook\templates\index.html:47
msgid "Import Recipe"
msgstr ""
msgstr "Εισαγωγή συνταγής"
#: .\cookbook\templates\base.html:282
msgid "Create"
msgstr ""
msgstr "Δημιουργία"
#: .\cookbook\templates\base.html:295
#: .\cookbook\templates\generic\list_template.html:14
#: .\cookbook\templates\stats.html:43
msgid "External Recipes"
msgstr ""
msgstr "Εξωτερικές Συνταγές"
#: .\cookbook\templates\base.html:298
#: .\cookbook\templates\space_manage.html:15
msgid "Space Settings"
msgstr ""
msgstr "Ρυθμίσεις χώρου"
#: .\cookbook\templates\base.html:303 .\cookbook\templates\system.html:13
msgid "System"
msgstr ""
msgstr "Σύστημα"
#: .\cookbook\templates\base.html:305
msgid "Admin"
msgstr ""
msgstr "Διαχειριστής"
#: .\cookbook\templates\base.html:309
#: .\cookbook\templates\space_overview.html:25
msgid "Your Spaces"
msgstr ""
msgstr "Οι χώροι σας"
#: .\cookbook\templates\base.html:320
#: .\cookbook\templates\space_overview.html:6
msgid "Overview"
msgstr ""
msgstr "Σύνοψη"
#: .\cookbook\templates\base.html:324
msgid "Markdown Guide"
msgstr ""
msgstr "Οδηγός χρήσης του Markdown"
#: .\cookbook\templates\base.html:326
msgid "GitHub"
@@ -1205,53 +1240,57 @@ msgstr "GitHub"
#: .\cookbook\templates\base.html:328
msgid "Translate Tandoor"
msgstr ""
msgstr "Μεταφράστε το Tandoor"
#: .\cookbook\templates\base.html:332
msgid "API Browser"
msgstr ""
msgstr "Περιηγητής API"
#: .\cookbook\templates\base.html:335
msgid "Log out"
msgstr ""
msgstr "Αποσύνδεση"
#: .\cookbook\templates\base.html:357
msgid "You are using the free version of Tandor"
msgstr ""
msgstr "Χρησιμοποιείται την δωρεάν έκδοση του Tandoor"
#: .\cookbook\templates\base.html:358
msgid "Upgrade Now"
msgstr ""
msgstr "Αναβαθμιστείτε τώρα"
#: .\cookbook\templates\batch\edit.html:6
msgid "Batch edit Category"
msgstr ""
msgstr "Μαζική τροποποίηση κατηγοριών"
#: .\cookbook\templates\batch\edit.html:15
msgid "Batch edit Recipes"
msgstr ""
msgstr "Μαζική τροποποίηση Συνταγών"
#: .\cookbook\templates\batch\edit.html:20
msgid "Add the specified keywords to all recipes containing a word"
msgstr ""
"Προσθέστε τις καθορισμένες λέξεις-κλειδιά σε όλες τις συνταγές που περιέχουν "
"μια λέξη"
#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:73
msgid "Sync"
msgstr ""
msgstr "Συγχρονισμός"
#: .\cookbook\templates\batch\monitor.html:10
msgid "Manage watched Folders"
msgstr ""
msgstr "Διαχείριση φακέλων που έχουν προβληθεί"
#: .\cookbook\templates\batch\monitor.html:14
msgid ""
"On this Page you can manage all storage folder locations that should be "
"monitored and synced."
msgstr ""
"Σε αυτήν τη σελίδα μπορείτε να διαχειριστείτε όλες τις τοποθεσίες "
"αποθήκευσης φακέλων που πρέπει να παρακολουθούνται και να συγχρονίζονται."
#: .\cookbook\templates\batch\monitor.html:16
msgid "The path must be in the following format"
msgstr ""
msgstr "Η διαδρομή (path) πρέπει να είναι στην ακόλουθη μορφή"
#: .\cookbook\templates\batch\monitor.html:20
#: .\cookbook\templates\forms\edit_import_recipe.html:14
@@ -1263,55 +1302,57 @@ msgstr ""
#: .\cookbook\templates\settings.html:202
#: .\cookbook\templates\settings.html:213
msgid "Save"
msgstr ""
msgstr "Αποθήκευση"
#: .\cookbook\templates\batch\monitor.html:21
msgid "Manage External Storage"
msgstr ""
msgstr "Διαχείριση εξωτερικού χώρου αποθήκευσης"
#: .\cookbook\templates\batch\monitor.html:28
msgid "Sync Now!"
msgstr ""
msgstr "Συγχρονισμός τώρα!"
#: .\cookbook\templates\batch\monitor.html:29
msgid "Show Recipes"
msgstr ""
msgstr "Προβολή Συνταγών"
#: .\cookbook\templates\batch\monitor.html:30
msgid "Show Log"
msgstr ""
msgstr "Προβολή αρχείων καταγραφής"
#: .\cookbook\templates\batch\waiting.html:4
#: .\cookbook\templates\batch\waiting.html:10
msgid "Importing Recipes"
msgstr ""
msgstr "Οι συνταγές εισάγονται"
#: .\cookbook\templates\batch\waiting.html:28
msgid ""
"This can take a few minutes, depending on the number of recipes in sync, "
"please wait."
msgstr ""
"Αυτή η διαδικασία μπορεί να πάρει μερικά λεπτά, ανάλογα με τον αριθμό των "
"συνταγών που πρέπει να συγχρονιστούν, παρακαλώ περιμένετε."
#: .\cookbook\templates\books.html:7
msgid "Recipe Books"
msgstr ""
msgstr "Βιβλία Συνταγών"
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
msgid "Export Recipes"
msgstr ""
msgstr "Εξαγωγή Συνταγών"
#: .\cookbook\templates\forms\edit_import_recipe.html:5
#: .\cookbook\templates\forms\edit_import_recipe.html:9
msgid "Import new Recipe"
msgstr ""
msgstr "Εισαγωγή μια νέας συνταγή"
#: .\cookbook\templates\forms\edit_internal_recipe.html:7
msgid "Edit Recipe"
msgstr ""
msgstr "Τροποποίηση συνταγής"
#: .\cookbook\templates\forms\ingredients.html:15
msgid "Edit Ingredients"
msgstr ""
msgstr "Τροποποίηση υλικών"
#: .\cookbook\templates\forms\ingredients.html:16
msgid ""
@@ -1323,32 +1364,41 @@ msgid ""
"them.\n"
" "
msgstr ""
"\n"
" Την παρακάτω φόρμα μπορεί να χρησιμοποιηθεί στην περίπτωση που, κατά "
"λάθος, δημιουργήθηκαν δύο (ή περισσότερες) μονάδες μέτρησης ή συστατικά που "
"θα έπρεπε να είναι\n"
" τα ίδια.\n"
" Αυτή η φόρμα συγχωνεύει δύο μονάδες ή συστατικά και ενημερώνει όλες "
"τις συνταγές που τα χρησιμοποιούν.\n"
" "
#: .\cookbook\templates\forms\ingredients.html:26
msgid "Are you sure that you want to merge these two units?"
msgstr ""
msgstr "Είστε βέβαιος ότι θέλετε να συγχωνεύσετε αυτές τις δύο μονάδες;"
#: .\cookbook\templates\forms\ingredients.html:31
#: .\cookbook\templates\forms\ingredients.html:40
msgid "Merge"
msgstr ""
msgstr "Συγχώνευση"
#: .\cookbook\templates\forms\ingredients.html:36
msgid "Are you sure that you want to merge these two ingredients?"
msgstr ""
msgstr "Είστε βέβαιος ότι θέλετε να συγχωνεύσετε αυτά τα δύο υλικά;"
#: .\cookbook\templates\generic\delete_template.html:21
#, python-format
msgid "Are you sure you want to delete the %(title)s: <b>%(object)s</b> "
msgstr ""
"Είστε σίγουροι ότι θέλετε να διαγράψετε τα %(title)s: <b>%(object)s</b> "
#: .\cookbook\templates\generic\delete_template.html:22
msgid "This cannot be undone!"
msgstr ""
msgstr "Αυτό δεν μπορεί να αναιρεθεί!"
#: .\cookbook\templates\generic\delete_template.html:27
msgid "Protected"
msgstr ""
msgstr "Προστατευμένο"
#: .\cookbook\templates\generic\delete_template.html:42
msgid "Cascade"
@@ -1356,68 +1406,68 @@ msgstr ""
#: .\cookbook\templates\generic\delete_template.html:73
msgid "Cancel"
msgstr ""
msgstr "Ακύρωση"
#: .\cookbook\templates\generic\edit_template.html:32
msgid "View"
msgstr ""
msgstr "Προβολή"
#: .\cookbook\templates\generic\edit_template.html:36
msgid "Delete original file"
msgstr ""
msgstr "Διαγραφή πρωτότυπου αρχείου"
#: .\cookbook\templates\generic\list_template.html:6
#: .\cookbook\templates\generic\list_template.html:22
msgid "List"
msgstr ""
msgstr "Λίστα"
#: .\cookbook\templates\generic\list_template.html:36
msgid "Filter"
msgstr ""
msgstr "Φίλτρο"
#: .\cookbook\templates\generic\list_template.html:41
msgid "Import all"
msgstr ""
msgstr "Εισαγωγή όλων"
#: .\cookbook\templates\generic\table_template.html:76
#: .\cookbook\templates\recipes_table.html:121
msgid "previous"
msgstr ""
msgstr "προηγούμενο"
#: .\cookbook\templates\generic\table_template.html:98
#: .\cookbook\templates\recipes_table.html:143
msgid "next"
msgstr ""
msgstr "επόμενο"
#: .\cookbook\templates\history.html:20
msgid "View Log"
msgstr ""
msgstr "Προβολή αρχείων καταγραφής"
#: .\cookbook\templates\history.html:24
msgid "Cook Log"
msgstr ""
msgstr "Αρχείο καταγραφής μαγειρέματος"
#: .\cookbook\templates\import.html:6
msgid "Import Recipes"
msgstr ""
msgstr "Εισαγωγή Συνταγών"
#: .\cookbook\templates\import.html:14 .\cookbook\templates\import.html:20
#: .\cookbook\templates\import_response.html:7 .\cookbook\views\delete.py:86
#: .\cookbook\views\edit.py:191
msgid "Import"
msgstr ""
msgstr "Εισαγωγή"
#: .\cookbook\templates\include\recipe_open_modal.html:18
msgid "Close"
msgstr ""
msgstr "Κλείσιμο"
#: .\cookbook\templates\include\recipe_open_modal.html:32
msgid "Open Recipe"
msgstr ""
msgstr "Άνοιγμα Συνταγής"
#: .\cookbook\templates\include\storage_backend_warning.html:4
msgid "Security Warning"
msgstr ""
msgstr "Προειδοποίηση ασφαλείας"
#: .\cookbook\templates\include\storage_backend_warning.html:5
msgid ""
@@ -1434,32 +1484,32 @@ msgstr ""
#: .\cookbook\templates\index.html:29
msgid "Search recipe ..."
msgstr ""
msgstr "Αναζήτηση συνταγής ..."
#: .\cookbook\templates\index.html:44
msgid "New Recipe"
msgstr ""
msgstr "Νέα συνταγή"
#: .\cookbook\templates\index.html:53
msgid "Advanced Search"
msgstr ""
msgstr "Αναζήτηση για προχωρημένους"
#: .\cookbook\templates\index.html:57
msgid "Reset Search"
msgstr ""
msgstr "Επαναφορά αναζήτησης"
#: .\cookbook\templates\index.html:85
msgid "Last viewed"
msgstr ""
msgstr "Τελευταίες προβολές"
#: .\cookbook\templates\index.html:94
msgid "Log in to view recipes"
msgstr ""
msgstr "Συνδεθείτε για να δείτε τις συνταγές"
#: .\cookbook\templates\markdown_info.html:5
#: .\cookbook\templates\markdown_info.html:13
msgid "Markdown Info"
msgstr ""
msgstr "Πληροφορίες για το Markdown"
#: .\cookbook\templates\markdown_info.html:14
msgid ""
@@ -1479,31 +1529,33 @@ msgstr ""
#: .\cookbook\templates\markdown_info.html:25
msgid "Headers"
msgstr ""
msgstr "Επικεφαλίδες"
#: .\cookbook\templates\markdown_info.html:54
msgid "Formatting"
msgstr ""
msgstr "Μορφοποίηση"
#: .\cookbook\templates\markdown_info.html:56
#: .\cookbook\templates\markdown_info.html:72
msgid "Line breaks are inserted by adding two spaces after the end of a line"
msgstr ""
"Οι αλλαγές γραμμής εισάγονται προσθέτοντας δύο κενά μετά το τέλος μιας "
"γραμμής"
#: .\cookbook\templates\markdown_info.html:57
#: .\cookbook\templates\markdown_info.html:73
msgid "or by leaving a blank line in between."
msgstr ""
msgstr "ή αφήνοντας μια κενή γραμμή μεταξύ τους."
#: .\cookbook\templates\markdown_info.html:59
#: .\cookbook\templates\markdown_info.html:74
msgid "This text is bold"
msgstr ""
msgstr "Το κείμενο είναι έντονο (bold)"
#: .\cookbook\templates\markdown_info.html:60
#: .\cookbook\templates\markdown_info.html:75
msgid "This text is italic"
msgstr ""
msgstr "Αυτό το κείμενο είναι πλάγιο (italic)"
#: .\cookbook\templates\markdown_info.html:61
#: .\cookbook\templates\markdown_info.html:77
@@ -1512,7 +1564,7 @@ msgstr ""
#: .\cookbook\templates\markdown_info.html:84
msgid "Lists"
msgstr ""
msgstr "Λίστες"
#: .\cookbook\templates\markdown_info.html:85
msgid ""
@@ -1550,7 +1602,7 @@ msgstr ""
#: .\cookbook\templates\markdown_info.html:125
msgid "Images & Links"
msgstr ""
msgstr "Φωτογραφίες και σύνδεσμοι"
#: .\cookbook\templates\markdown_info.html:126
msgid ""

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"PO-Revision-Date: 2023-08-13 08:19+0000\n"
"Last-Translator: Miha Perpar <miha.perpar2@gmail.com>\n"
"Language-Team: Slovenian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/sl/>\n"
"Language: sl\n"
@@ -964,7 +964,7 @@ msgstr ""
#: .\cookbook\templates\base.html:275
msgid "GitHub"
msgstr ""
msgstr "GitHub"
#: .\cookbook\templates\base.html:277
msgid "Translate Tandoor"
@@ -1961,7 +1961,7 @@ msgstr ""
#: .\cookbook\templates\space.html:106
msgid "user"
msgstr ""
msgstr "uporabnik"
#: .\cookbook\templates\space.html:107
msgid "guest"

View File

@@ -0,0 +1,18 @@
# Generated by Django 4.1.9 on 2023-06-26 13:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0193_space_internal_note'),
]
operations = [
migrations.AlterField(
model_name='food',
name='properties_food_amount',
field=models.DecimalField(blank=True, decimal_places=2, default=100, max_digits=16),
),
]

View File

@@ -0,0 +1,34 @@
# Generated by Django 4.1.9 on 2023-06-30 20:34
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0194_alter_food_properties_food_amount'),
]
operations = [
migrations.AddField(
model_name='invitelink',
name='internal_note',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='userspace',
name='internal_note',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='userspace',
name='invite_link',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='cookbook.invitelink'),
),
migrations.AlterField(
model_name='userpreference',
name='theme',
field=models.CharField(choices=[('TANDOOR', 'Tandoor'), ('BOOTSTRAP', 'Bootstrap'), ('DARKLY', 'Darkly'), ('FLATLY', 'Flatly'), ('SUPERHERO', 'Superhero'), ('TANDOOR_DARK', 'Tandoor Dark (INCOMPLETE)')], default='TANDOOR', max_length=128),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 4.1.10 on 2023-07-22 06:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0195_invitelink_internal_note_userspace_internal_note_and_more'),
]
operations = [
migrations.AddField(
model_name='food',
name='url',
field=models.CharField(blank=True, default='', max_length=1024, null=True),
),
]

View File

@@ -331,6 +331,7 @@ class UserPreference(models.Model, PermissionModelMixin):
FLATLY = 'FLATLY'
SUPERHERO = 'SUPERHERO'
TANDOOR = 'TANDOOR'
TANDOOR_DARK = 'TANDOOR_DARK'
THEMES = (
(TANDOOR, 'Tandoor'),
@@ -338,6 +339,7 @@ class UserPreference(models.Model, PermissionModelMixin):
(DARKLY, 'Darkly'),
(FLATLY, 'Flatly'),
(SUPERHERO, 'Superhero'),
(TANDOOR_DARK, 'Tandoor Dark (INCOMPLETE)'),
)
# Nav colors
@@ -413,6 +415,9 @@ class UserSpace(models.Model, PermissionModelMixin):
# that having more than one active space should just break certain parts of the application and not leak any data
active = models.BooleanField(default=False)
invite_link = models.ForeignKey("InviteLink", on_delete=models.PROTECT, null=True, blank=True)
internal_note = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@@ -574,6 +579,7 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
name = models.CharField(max_length=128, validators=[MinLengthValidator(1)])
plural_name = models.CharField(max_length=128, null=True, blank=True, default=None)
recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL)
url = models.CharField(max_length=1024, blank=True, null=True, default='')
supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL) # inherited field
ignore_shopping = models.BooleanField(default=False) # inherited field
onhand_users = models.ManyToManyField(User, blank=True)
@@ -585,7 +591,7 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
child_inherit_fields = models.ManyToManyField(FoodInheritField, blank=True, related_name='child_inherit')
properties = models.ManyToManyField("Property", blank=True, through='FoodProperty')
properties_food_amount = models.IntegerField(default=100, blank=True)
properties_food_amount = models.DecimalField(default=100, max_digits=16, decimal_places=2, blank=True)
properties_food_unit = models.ForeignKey(Unit, on_delete=models.PROTECT, blank=True, null=True)
preferred_unit = models.ForeignKey(Unit, on_delete=models.SET_NULL, null=True, blank=True, default=None, related_name='preferred_unit')
@@ -717,25 +723,6 @@ class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, Permiss
space = models.ForeignKey(Space, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
food = ""
unit = ""
if self.always_use_plural_food and self.food.plural_name not in (None, "") and not self.no_amount:
food = self.food.plural_name
else:
if self.amount > 1 and self.food.plural_name not in (None, "") and not self.no_amount:
food = self.food.plural_name
else:
food = str(self.food)
if self.always_use_plural_unit and self.unit.plural_name not in (None, "") and not self.no_amount:
unit = self.unit.plural_name
else:
if self.amount > 1 and self.unit is not None and self.unit.plural_name not in (None, "") and not self.no_amount:
unit = self.unit.plural_name
else:
unit = str(self.unit)
return str(self.amount) + ' ' + str(unit) + ' ' + str(food)
class Meta:
ordering = ['order', 'pk']
indexes = (
@@ -1142,6 +1129,8 @@ class InviteLink(ExportModelOperationsMixin('invite_link'), models.Model, Permis
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
internal_note = models.TextField(blank=True, null=True)
space = models.ForeignKey(Space, on_delete=models.CASCADE)
objects = ScopedManager(space='space')

View File

@@ -109,7 +109,7 @@ class CustomDecimalField(serializers.Field):
if data == '':
return 0
try:
return float(data.replace(',', ''))
return float(data.replace(',', '.'))
except ValueError:
raise ValidationError('A valid number is required')
@@ -322,8 +322,8 @@ class UserSpaceSerializer(WritableNestedModelSerializer):
class Meta:
model = UserSpace
fields = ('id', 'user', 'space', 'groups', 'active', 'created_at', 'updated_at',)
read_only_fields = ('id', 'created_at', 'updated_at', 'space')
fields = ('id', 'user', 'space', 'groups', 'active', 'internal_note', 'invite_link', 'created_at', 'updated_at',)
read_only_fields = ('id', 'invite_link', 'created_at', 'updated_at', 'space')
class SpacedModelSerializer(serializers.ModelSerializer):
@@ -478,7 +478,7 @@ class UnitSerializer(UniqueFieldsMixin, ExtendedRecipeMixin, OpenDataModelMixin)
class Meta:
model = Unit
fields = ('id', 'name', 'plural_name', 'description', 'numrecipe', 'image', 'open_data_slug')
fields = ('id', 'name', 'plural_name', 'description', 'base_unit', 'numrecipe', 'image', 'open_data_slug')
read_only_fields = ('id', 'numrecipe', 'image')
@@ -514,11 +514,13 @@ class SupermarketSerializer(UniqueFieldsMixin, SpacedModelSerializer, OpenDataMo
fields = ('id', 'name', 'description', 'category_to_supermarket', 'open_data_slug')
class PropertyTypeSerializer(OpenDataModelMixin):
class PropertyTypeSerializer(OpenDataModelMixin, WritableNestedModelSerializer, UniqueFieldsMixin):
id = serializers.IntegerField(required=False)
def create(self, validated_data):
validated_data['space'] = self.context['request'].space
if property_type := PropertyType.objects.filter(Q(name=validated_data['name'])).first():
if property_type := PropertyType.objects.filter(Q(name=validated_data['name'])).filter(space=self.context['request'].space).first():
return property_type
return super().create(validated_data)
@@ -532,8 +534,6 @@ class PropertySerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
property_type = PropertyTypeSerializer()
property_amount = CustomDecimalField()
# TODO prevent updates
def create(self, validated_data):
validated_data['space'] = self.context['request'].space
return super().create(validated_data)
@@ -541,7 +541,6 @@ class PropertySerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
class Meta:
model = Property
fields = ('id', 'property_amount', 'property_type')
read_only_fields = ('id',)
class RecipeSimpleSerializer(WritableNestedModelSerializer):
@@ -582,6 +581,7 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
properties = PropertySerializer(many=True, allow_null=True, required=False)
properties_food_unit = UnitSerializer(allow_null=True, required=False)
properties_food_amount = CustomDecimalField(required=False)
recipe_filter = 'steps__ingredients__food'
images = ['recipe__image']
@@ -649,8 +649,15 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
if properties_food_unit := validated_data.pop('properties_food_unit', None):
properties_food_unit = Unit.objects.filter(name=properties_food_unit['name']).first()
properties = validated_data.pop('properties', None)
obj, created = Food.objects.get_or_create(name=name, plural_name=plural_name, space=space, properties_food_unit=properties_food_unit,
defaults=validated_data)
if properties and len(properties) > 0:
for p in properties:
obj.properties.add(Property.objects.create(property_type_id=p['property_type']['id'], property_amount=p['property_amount'], space=space))
return obj
def update(self, instance, validated_data):
@@ -677,7 +684,7 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
class Meta:
model = Food
fields = (
'id', 'name', 'plural_name', 'description', 'shopping', 'recipe',
'id', 'name', 'plural_name', 'description', 'shopping', 'recipe', 'url',
'properties', 'properties_food_amount', 'properties_food_unit',
'food_onhand', 'supermarket_category',
'image', 'parent', 'numchild', 'numrecipe', 'inherit_fields', 'full_name', 'ignore_shopping',
@@ -1238,7 +1245,7 @@ class InviteLinkSerializer(WritableNestedModelSerializer):
class Meta:
model = InviteLink
fields = (
'id', 'uuid', 'email', 'group', 'valid_until', 'used_by', 'reusable', 'created_by', 'created_at',)
'id', 'uuid', 'email', 'group', 'valid_until', 'used_by', 'reusable', 'internal_note', 'created_by', 'created_at',)
read_only_fields = ('id', 'uuid', 'created_by', 'created_at',)
@@ -1355,7 +1362,7 @@ class RecipeExportSerializer(WritableNestedModelSerializer):
model = Recipe
fields = (
'name', 'description', 'keywords', 'steps', 'working_time',
'waiting_time', 'internal', 'nutrition', 'servings', 'servings_text',
'waiting_time', 'internal', 'nutrition', 'servings', 'servings_text', 'source_url',
)
def create(self, validated_data):

View File

@@ -7,8 +7,7 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="2000px"
height="2000px"
viewBox="0 0 2000 2000"
version="1.1"
id="SVGRoot"

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

10486
cookbook/static/themes/tandoor_dark.min.css vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -73,7 +73,7 @@
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-{% nav_color request %}"
<nav class="navbar navbar-expand-lg {% nav_color request %}"
id="id_main_nav"
style="{% sticky_nav request %}">

View File

@@ -11,29 +11,39 @@
{% block content %}
<h1>{% trans 'System' %}</h1>
<br/>
<br/>
<br/>
<br/>
<h3>{% trans 'System Information' %}</h3>
{% blocktrans %}
Django Recipes is an open source free software application. It can be found on
<a href="https://github.com/vabene1111/recipes">GitHub</a>.
Changelogs can be found <a href="https://github.com/vabene1111/recipes/releases">here</a>.
{% endblocktrans %}
<br/>
<br/>
Current Version: {% if version and version != '' %}
<a href="https://github.com/vabene1111/recipes/releases/tag/{{ version }}">{{ version }}</a>{% else %}
{{ version }}{% endif %}<br/>
Ref: <a href="https://github.com/vabene1111/recipes/commit/{{ ref }}">{{ ref }}</a>
<br/>
<br/>
<br/>
<h4>{% trans 'Media Serving' %} <span class="badge badge-{% if gunicorn_media %}danger{% else %}success{% endif %}">{% if gunicorn_media %}
<h3 class="mt-5">{% trans 'System Information' %}</h3>
{% if version_info %}
<div class="row">
<div class="col">
<div class="list-group">
{% for v in version_info %}
<div class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{ v.name }} ({{ v.branch }}) {% if v.tag %}- {{ v.tag }}{% endif %}</h5>
</div>
<pre class="card-text p-2" style="border: 1px solid lightgrey; border-radius: 5px" target="_blank">{{ v.version }}</pre>
<a href="{{ v.website }}">Website</a>
{% if v.commit_link %}
- <a href="{{ v.commit_link }}" target="_blank">Commit</a>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
{% else %}
{% blocktrans %}
You need to execute <code>version.py</code> in your update script to generate version information (done automatically in docker).
{% endblocktrans %}
{% endif %}
<h4 class="mt-3">{% trans 'Media Serving' %} <span class="badge badge-{% if gunicorn_media %}danger{% else %}success{% endif %}">{% if gunicorn_media %}
{% trans 'Warning' %}{% else %}{% trans 'Ok' %}{% endif %}</span></h4>
{% if gunicorn_media %}
{% blocktrans %}Serving media files directly using gunicorn/python is <b>not recommend</b>!
@@ -44,10 +54,9 @@
{% else %}
{% trans 'Everything is fine!' %}
{% endif %}
<br/>
<br/>
<h4>{% trans 'Secret Key' %} <span
<h4 class="mt-3">{% trans 'Secret Key' %} <span
class="badge badge-{% if secret_key %}danger{% else %}success{% endif %}">{% if secret_key %}
{% trans 'Warning' %}{% else %}{% trans 'Ok' %}{% endif %}</span></h4>
{% if secret_key %}
@@ -60,10 +69,8 @@
{% else %}
{% trans 'Everything is fine!' %}
{% endif %}
<br/>
<br/>
<h4>{% trans 'Debug Mode' %} <span
<h4 class="mt-3">{% trans 'Debug Mode' %} <span
class="badge badge-{% if debug %}danger{% else %}success{% endif %}">{% if debug %}
{% trans 'Warning' %}{% else %}{% trans 'Ok' %}{% endif %}</span></h4>
{% if debug %}
@@ -75,10 +82,8 @@
{% else %}
{% trans 'Everything is fine!' %}
{% endif %}
<br/>
<br/>
<h4>{% trans 'Database' %} <span
<h4 class="mt-3">{% trans 'Database' %} <span
class="badge badge-{% if postgres %}warning{% else %}success{% endif %}">{% if postgres %}
{% trans 'Info' %}{% else %}{% trans 'Ok' %}{% endif %}</span></h4>
{% if postgres %}
@@ -89,9 +94,8 @@
{% else %}
{% trans 'Everything is fine!' %}
{% endif %}
<br/>
<br/>
<h4>Debug</h4>
<h4 class="mt-3">Debug</h4>
<textarea class="form-control" rows="20">
Gunicorn Media: {{ gunicorn_media }}
Sqlite: {{ postgres }}
@@ -99,9 +103,9 @@ Debug: {{ debug }}
{% for key,value in request.META.items %}{% if key in 'SERVER_PORT,REMOTE_HOST,REMOTE_ADDR,SERVER_PROTOCOL' %}{{ key }}:{{ value }}
{% endif %}{% endfor %}
{% for key,value in request.META.items %}{% if 'HTTP_' in key %}{{ key }}:{{ value }}
{% for key,value in request.META.items %}{% if 'HTTP_' in key %}{{ key }}:{{ value }}
{% endif %}{% endfor %}
{% for key,value in request.META.items %}{% if 'wsgi.' in key %}{{ key }}:{{ value }}
{% for key,value in request.META.items %}{% if 'wsgi.' in key %}{{ key }}:{{ value }}
{% endif %}{% endfor %}
</textarea>
<br/>

View File

@@ -16,6 +16,7 @@ def theme_url(request):
UserPreference.DARKLY: 'themes/darkly.min.css',
UserPreference.SUPERHERO: 'themes/superhero.min.css',
UserPreference.TANDOOR: 'themes/tandoor.min.css',
UserPreference.TANDOOR_DARK: 'themes/tandoor_dark.min.css',
}
if request.user.userpreference.theme in themes:
return static(themes[request.user.userpreference.theme])
@@ -26,8 +27,12 @@ def theme_url(request):
@register.simple_tag
def nav_color(request):
if not request.user.is_authenticated:
return 'primary'
return request.user.userpreference.nav_color.lower()
return 'navbar-light bg-primary'
if request.user.userpreference.nav_color.lower() in ['light', 'warning', 'info', 'success']:
return f'navbar-light bg-{request.user.userpreference.nav_color.lower()}'
else:
return f'navbar-dark bg-{request.user.userpreference.nav_color.lower()}'
@register.simple_tag

View File

@@ -475,6 +475,7 @@ def test_root_filter(obj_tree_1, obj_2, obj_3, u1_s1):
with scope(space=obj_tree_1.space):
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
obj_2 = Food.objects.get(id=obj_2.id)
parent = obj_tree_1.get_parent()
# should return root objects in the space (obj_1, obj_2), ignoring query filters
@@ -499,17 +500,16 @@ def test_tree_filter(obj_tree_1, obj_2, obj_3, u1_s1):
with scope(space=obj_tree_1.space):
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
obj_2 = Food.objects.get(id=obj_2.id)
parent = obj_tree_1.get_parent()
obj_2.move(parent, node_location)
obj_2 = Food.objects.get(id=obj_2.id)
parent = Food.objects.get(id=parent.id)
# should return full tree starting at parent (obj_tree_1, obj_2), ignoring query filters
response = json.loads(
u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}').content)
# should return full tree starting at, but excluding parent (obj_tree_1, obj_2), ignoring query filters
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}').content)
assert response['count'] == 4
response = json.loads(u1_s1.get(
f'{reverse(LIST_URL)}?tree={parent.id}&query={obj_2.name[4:]}').content)
# filtering is ignored - should return identical results as ?tree=x
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}&query={obj_2.name[4:]}').content)
assert response['count'] == 4

View File

@@ -81,10 +81,10 @@ def test_share_permission(recipe_1_s1, u1_s1, u1_s2, u2_s1, a_u):
@pytest.mark.parametrize("arg", [
['a_u', 403],
['g1_s1', 200],
['g1_s1', 403],
['u1_s1', 200],
['a1_s1', 200],
['g1_s2', 404],
['g1_s2', 403],
['u1_s2', 404],
['a1_s2', 404],
])
@@ -140,7 +140,7 @@ def test_update_private_recipe(u1_s1, u2_s1, recipe_1_s1):
@pytest.mark.parametrize("arg", [
['a_u', 403],
['g1_s1', 201],
['g1_s1', 403],
['u1_s1', 201],
['a1_s1', 201],
])

View File

@@ -48,7 +48,7 @@ def recipe(request, space_1, u1_s1):
@pytest.mark.parametrize("arg", [
['g1_s1', 204],
['g1_s1', 403],
['u1_s1', 204],
['u1_s2', 404],
['a1_s1', 204],

View File

@@ -15,9 +15,9 @@ DETAIL_URL = 'api:space-detail'
@pytest.mark.parametrize("arg", [
['a_u', 403, 0],
['g1_s1', 403, 0],
['u1_s1', 403, 0],
['u1_s1', 200, 1],
['a1_s1', 200, 1],
['a2_s1', 200, 0],
['a2_s1', 200, 1],
])
def test_list_permission(arg, request, space_1, a1_s1):
space_1.created_by = auth.get_user(a1_s1)
@@ -29,16 +29,6 @@ def test_list_permission(arg, request, space_1, a1_s1):
assert len(json.loads(result.content)) == arg[2]
def test_list_permission_owner(u1_s1, a1_s1, space_1):
space_1.created_by = auth.get_user(a1_s1)
space_1.save()
assert len(json.loads(a1_s1.get(reverse(LIST_URL)).content)) == 1
assert u1_s1.get(reverse(LIST_URL)).status_code == 403
space_1.created_by = auth.get_user(u1_s1)
space_1.save()
assert u1_s1.get(reverse(LIST_URL)).status_code == 403
@pytest.mark.parametrize("arg", [
['a_u', 403],
['g1_s1', 403],

View File

@@ -48,7 +48,7 @@ def test_list_filter(obj_1, obj_2, u1_s1):
assert r.status_code == 200
response = json.loads(r.content)
assert len(response) == 2
assert response[0]['name'] == obj_1.name
# assert response[0]['name'] == obj_1.name # assuming an order when it's not always valid
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content)
assert len(response) == 1

View File

@@ -27,7 +27,7 @@ def test_list_permission(arg, request, space_1, g1_s1, u1_s1, a1_s1):
result = c.get(reverse(LIST_URL))
assert result.status_code == arg[1]
if arg[1] == 200:
assert len(json.loads(result.content)) == arg[2]
assert len(json.loads(result.content)['results']) == arg[2]
@pytest.mark.parametrize("arg", [

View File

@@ -7,7 +7,7 @@ from rest_framework.schemas import get_schema_view
from cookbook.helper import dal
from recipes.settings import DEBUG, PLUGINS
from recipes.version import VERSION_NUMBER
from cookbook.version_info import TANDOOR_VERSION
from .models import (Automation, Comment, CustomFilter, Food, InviteLink, Keyword, MealPlan, Recipe,
RecipeBook, RecipeBookEntry, RecipeImport, ShoppingList, Step, Storage,
@@ -148,7 +148,7 @@ urlpatterns = [
path('docs/search/', views.search_info, name='docs_search'),
path('docs/api/', views.api_info, name='docs_api'),
path('openapi/', get_schema_view(title="Django Recipes", version=VERSION_NUMBER, public=True,
path('openapi/', get_schema_view(title="Django Recipes", version=TANDOOR_VERSION, public=True,
permission_classes=(permissions.AllowAny,)), name='openapi-schema'),
path('api/', include((router.urls, 'api'))),

3
cookbook/version_info.py Normal file
View File

@@ -0,0 +1,3 @@
TANDOOR_VERSION = ""
TANDOOR_REF = ""
VERSION_INFO = []

View File

@@ -60,7 +60,7 @@ from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsOwner,
CustomIsSpaceOwner, CustomIsUser, group_required,
is_space_owner, switch_user_active_space, above_space_limit,
CustomRecipePermission, CustomUserPermission,
CustomTokenHasReadWriteScope, CustomTokenHasScope, has_group_permission)
CustomTokenHasReadWriteScope, CustomTokenHasScope, has_group_permission, IsReadOnlyDRF)
from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch
from cookbook.helper.recipe_url_import import get_from_youtube_scraper, get_images_from_soup, clean_dict
from cookbook.helper.scrapers.scrapers import text_scraper
@@ -402,11 +402,11 @@ class GroupViewSet(viewsets.ModelViewSet):
class SpaceViewSet(viewsets.ModelViewSet):
queryset = Space.objects
serializer_class = SpaceSerializer
permission_classes = [CustomIsOwner & CustomIsAdmin & CustomTokenHasReadWriteScope]
permission_classes = [IsReadOnlyDRF & CustomIsUser | CustomIsOwner & CustomIsAdmin & CustomTokenHasReadWriteScope]
http_method_names = ['get', 'patch']
def get_queryset(self):
return self.queryset.filter(id=self.request.space.id, created_by=self.request.user)
return self.queryset.filter(id=self.request.space.id)
class UserSpaceViewSet(viewsets.ModelViewSet):
@@ -414,6 +414,7 @@ class UserSpaceViewSet(viewsets.ModelViewSet):
serializer_class = UserSpaceSerializer
permission_classes = [(CustomIsSpaceOwner | CustomIsOwnerReadOnly) & CustomTokenHasReadWriteScope]
http_method_names = ['get', 'patch', 'delete']
pagination_class = DefaultPagination
def destroy(self, request, *args, **kwargs):
if request.space.created_by == UserSpace.objects.get(pk=kwargs['pk']).user:
@@ -421,6 +422,10 @@ class UserSpaceViewSet(viewsets.ModelViewSet):
return super().destroy(request, *args, **kwargs)
def get_queryset(self):
internal_note = self.request.query_params.get('internal_note', None)
if internal_note is not None:
self.queryset = self.queryset.filter(internal_note=internal_note)
if is_space_owner(self.request.user, self.request.space):
return self.queryset.filter(space=self.request.space)
else:
@@ -1047,6 +1052,21 @@ class ShoppingListEntryViewSet(viewsets.ModelViewSet):
Q(created_by=self.request.user)
| Q(shoppinglist__shared=self.request.user)
| Q(created_by__in=list(self.request.user.get_shopping_share()))
).prefetch_related(
'created_by',
'food',
'food__properties',
'food__properties__property_type',
'food__inherit_fields',
'food__supermarket_category',
'food__onhand_users',
'food__substitute',
'food__child_inherit_fields',
'unit',
'list_recipe',
'list_recipe__mealplan',
'list_recipe__mealplan__recipe',
).distinct().all()
if pk := self.request.query_params.getlist('id', []):
@@ -1165,6 +1185,11 @@ class InviteLinkViewSet(viewsets.ModelViewSet, StandardFilterMixin):
permission_classes = [CustomIsSpaceOwner & CustomIsAdmin & CustomTokenHasReadWriteScope]
def get_queryset(self):
internal_note = self.request.query_params.get('internal_note', None)
if internal_note is not None:
self.queryset = self.queryset.filter(internal_note=internal_note)
if is_space_owner(self.request.user, self.request.space):
self.queryset = self.queryset.filter(space=self.request.space).all()
return super().get_queryset()
@@ -1308,8 +1333,12 @@ def recipe_from_source(request):
}, status=status.HTTP_400_BAD_REQUEST)
else:
try:
json.loads(data)
data = "<script type='application/ld+json'>" + data + "</script>"
data_json = json.loads(data)
if '@context' not in data_json:
data_json['@context'] = 'https://schema.org'
if '@type' not in data_json:
data_json['@type'] = 'Recipe'
data = "<script type='application/ld+json'>" + json.dumps(data_json) + "</script>"
except JSONDecodeError:
pass
scrape = text_scraper(text=data, url=url)

View File

@@ -22,7 +22,8 @@ from cookbook.helper.permission_helper import group_required, has_group_permissi
from cookbook.models import (Comment, CookLog, InviteLink, SearchFields, SearchPreference, ShareLink,
Space, ViewLog, UserSpace)
from cookbook.tables import (CookLogTable, ViewLogTable)
from recipes.version import BUILD_REF, VERSION_NUMBER
from cookbook.version_info import VERSION_INFO
from recipes.settings import PLUGINS
def index(request):
@@ -320,8 +321,8 @@ def system(request):
'gunicorn_media': settings.GUNICORN_MEDIA,
'debug': settings.DEBUG,
'postgres': postgres,
'version': VERSION_NUMBER,
'ref': BUILD_REF,
'version_info': VERSION_INFO,
'plugins': PLUGINS,
'secret_key': secret_key
})
@@ -370,7 +371,7 @@ def invite_link(request, token):
link.used_by = request.user
link.save()
user_space = UserSpace.objects.create(user=request.user, space=link.space, active=False)
user_space = UserSpace.objects.create(user=request.user, space=link.space, internal_note=link.internal_note, invite_link=link, active=False)
if request.user.userspace_set.count() == 1:
user_space.active = True

View File

@@ -2,7 +2,7 @@ version: "2.4"
services:
db_recipes:
restart: always
image: postgres:11-alpine
image: postgres:15-alpine
volumes:
- ${POSTGRES_DATA_DIR:-./postgresql}:/var/lib/postgresql/data
env_file:
@@ -22,6 +22,7 @@ services:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/opt/recipes/nginx/conf.d
- ${MEDIA_FILES_DIR:-./mediafiles}:/opt/recipes/mediafiles
depends_on:
@@ -41,6 +42,7 @@ services:
depends_on:
- web_recipes
volumes:
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static:ro
- ${MEDIA_FILES_DIR:-./mediafiles}:/media:ro

View File

@@ -2,7 +2,7 @@ version: "3"
services:
db_recipes:
restart: always
image: postgres:11-alpine
image: postgres:15-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
@@ -17,6 +17,7 @@ services:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/opt/recipes/nginx/conf.d
- ./mediafiles:/opt/recipes/mediafiles
depends_on:
@@ -32,6 +33,7 @@ services:
depends_on:
- web_recipes
volumes:
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static:ro
- ./mediafiles:/media:ro

View File

@@ -2,7 +2,7 @@ version: "3"
services:
db_recipes:
restart: always
image: postgres:11-alpine
image: postgres:15-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
@@ -15,6 +15,7 @@ services:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/opt/recipes/nginx/conf.d
- ./mediafiles:/opt/recipes/mediafiles
depends_on:
@@ -30,6 +31,7 @@ services:
depends_on:
- web_recipes
volumes:
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static:ro
- ./mediafiles:/media:ro

View File

@@ -2,7 +2,7 @@ version: "3"
services:
db_recipes:
restart: always
image: postgres:11-alpine
image: postgres:15-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
@@ -17,6 +17,7 @@ services:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/opt/recipes/nginx/conf.d
- ./mediafiles:/opt/recipes/mediafiles
depends_on:
@@ -30,6 +31,7 @@ services:
env_file:
- ./.env
volumes:
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static:ro
- ./mediafiles:/media:ro

View File

@@ -69,7 +69,7 @@ services:
db_recipes:
restart: always
container_name: db_recipes
image: postgres:11-alpine
image: postgres:15-alpine
volumes:
- ./recipes/db:/var/lib/postgresql/data
env_file:

View File

@@ -0,0 +1,133 @@
!!! info "Community Contributed"
This guide was contributed by the community and is neither officially supported, nor updated or tested.
This guide is to assist those installing Tandoor Recipes on Truenas Core using Docker and or Portainer
Docker install instructions adapted from [PhasedLogix IT Services's guide](https://getmethegeek.com/blog/2021-01-07-add-docker-capabilities-to-truenas-core/). Portainer install instructions adopted from the [Portainer Official Documentation](https://docs.portainer.io/start/install-ce/server/docker/linux). Tandoor installation on Portainer provided by users `Szeraax` and `TransatlanticFoe` on Discord (Thank you two!)
## **Instructions**
Basic guide to setup Docker and Portainer TrueNAS Core.
### 1. Login to TrueNAS through your browser
- Go to the Virtual Machines Menu
![Screenshot of TrueNAS VM Menu[(https://d33wubrfki0l68.cloudfront.net/e5bc016268e41fadea77fd91a35c40d52280d221/c9daf/images/blog/truenasvmpage.png)
- Click Add to add a new virtual machine. You will want the following settings:
-Guest operating system: Linux
-Name: UBUDocker (or whatever you want it to be)
-System Clock: Local
-Boot method: UEFI
-Shutdown time: 90
-Start on boot enabled
-Enable VNC enabled
![Screenshot of Add VM Menu](https://d33wubrfki0l68.cloudfront.net/d366b2c17d8e8515c9b266ff5451d2b35413cca3/1e0fa/images/blog/vmsetupscreen.png)
- Click next to dedicate resources to the VM (see below image of authors setup, you may need to change resources to fit your needs)
![Screenshot of Suggested VM resources](https://d33wubrfki0l68.cloudfront.net/b96ec49a4ba0c3a5577d5f22275e31d7dbdebe52/81017/images/blog/dockerresourcesetup.png)
- Hit next to go to disk setup
-You want to create a new disk, here are the settings you should use
-Disk Type: AHCI
-Zvol location: tank/vm (Or wherever you have your VM memory located at)
-Size: Atleast 30 gigs
![Screenshot of Disk Setup](https://d33wubrfki0l68.cloudfront.net/adb782ea4ec5531710e69bfefde641927ebdce00/a8cde/images/blog/dockerdisksetup.png)
-Hit next to go to network interface (The defaults are fine but make sure you select the right network adapter)
-Hit next to go to installation
-Navigate to your ubuntu ISO file (The original author and this author used Ubuntu Server. This OS uses less resources than some other OS's and can be ran Headless with either VNC or SSH access. You can use other OS's, but this guide was written with Ubuntu Server)
-Hit next, then submit, you have made the virtual machine!
-Open the virtual machine then hit VNC to open ubuntu
![Screenshot of VM Options](https://d33wubrfki0l68.cloudfront.net/93d874e9630735f8a8d851a220b0411446149c6a/5deb3/images/blog/docketvmpage.png)
-Once its up choose your language and go through the installer
-Once you are done with the setup we want to SSH into the ubuntu VM to setup docker
-Open powershell and type SSH "user"@(ip) (replace "user" with the user you setup in the OS installation)
-Enter your Password if requested
-Close the VNC Console
-Go back into the SSH console and get ready to type some commands. Type these commands in order:
`sudo apt update`
`sudo apt install apt-transport-https ca-certificates curl software-properties-common`
`y` (If prompted with a question)
`curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -`
`sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"`
`sudo apt update`
`apt-cache policy docker-ce`
-To make it so you dont have to use sudo for every docker command run this command
`sudo usermod -aG docker ${USER}`
`su - ${USER}`
### 2. Install Portainer
!!! Note: By default, Portainer Server will expose the UI over port 9443 and expose a TCP tunnel server over port 8000. The latter is optional and is only required if you plan to use the Edge compute features with Edge agents.
-First, create the volume that Portainer Server will use to store its database:
`docker volume create portainer_data`
-Then, download and install the Portainer Server container:
`docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest`
-Portainer Server has now been installed. You can check to see whether the Portainer Server container has started by running `docker ps`
-Now that the installation is complete, you can log into your Portainer Server instance by opening a web browser and going to:
`https://localhost:9443`
-Replace `localhost` with the relevant IP address or FQDN if needed, and adjust the port if you changed it earlier.
-You will be presented with the initial setup page for Portainer Server.
-Create your first user
-Your first user will be an administrator. The username defaults to admin but you can change it if you prefer. The password must be at least 12 characters long and meet the listed password requirements.
-Connect Portainer to your environments.
-Once the admin user has been created, the "Environment Wizard" will automatically launch. The wizard will help get you started with Portainer.
-Select "Get Started" to use the Enviroment Portainer is running in
![Screenshot of Enviroment Wizard](https://2914113074-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiZWHJxqQsgWYd9sI88sO%2Fuploads%2Fsig45vFliINvOKGKVStk%2F2.15-install-server-setup-wizard.png?alt=media&token=cd21d9e8-0632-40db-af9a-581365f98209)
### 3. Install Tandoor Recipies VIA Portainer Web Editor
-From the menu select Stacks, click Add stack, give the stack a descriptive name then select Web editor.
![Screenshot of Stack List](https://2914113074-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiZWHJxqQsgWYd9sI88sO%2Fuploads%2FnBx62EIPhmUy1L0S1iKI%2F2.15-docker_add_stack_web_editor.gif?alt=media&token=c45c0151-9c15-4d79-b229-1a90a7a86b84)
-Use the below code and input it into the Web Editor:
`version: "3"
services:
db_recipes:
restart: always
image: postgres:15-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
- stack.env
web_recipes:
# image: vabene1111/recipes:latest
image: vabene1111/recipes:beta
env_file:
- stack.env
volumes:
- staticfiles:/opt/recipes/staticfiles
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/opt/recipes/nginx/conf.d
- ./mediafiles:/opt/recipes/mediafiles
depends_on:
- db_recipes
nginx_recipes:
image: nginx:mainline-alpine
restart: always
ports:
- 12008:80
env_file:
- stack.env
depends_on:
- web_recipes
volumes:
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static
- ./mediafiles:/media
volumes:
nginx_config:
staticfiles:`
-Download the .env template from [HERE](https://raw.githubusercontent.com/vabene1111/recipes/develop/.env.template) and load this file by pressing the "Load Variables from .env File" button:
![Screenshot of Add Stack screen](https://www.portainer.io/hubfs/image-png-Feb-21-2022-06-21-15-88-PM.png)
-You will need to change the following variables:
-`SECRET_KEY` needs to be replaced with a new key. This can be generated from websites like [Djecrety](https://djecrety.ir/)
-`TIMEZONE` needs to be replaced with the appropriate code for your timezone. Accepted values can be found at [TimezoneDB](https://timezonedb.com/time-zones)
-`POSTGRES_USER` and `POSTGRES_PASSWORD` needs to be replaced with your username and password from [PostgreSQL](https://www.postgresql.org/) !!!NOTE Do not sign in using social media. You need to sign up using Email and Password.
-After those veriables are changed, you may press the `Deploy the Stack` button at the bottom of the page. This will create the needed containers to run Tandoor Recipes.
### 4. Login and Setup your new server!
- You need to access your Tandoor Server through its Webpage: `https://localhost:xxxx` replacing `localhost` with the IP of the VM running Docker and `xxxx` with the port you chose in the Web Editor for `nginx_recipes` above. In this case, `12008`.
!!! While the containers are starting and doing whatever they need to do, you might still get HTTP errors e.g. 500 or 502. Just be patient and try again in a moment
-You will now need to set up the Tandoor Server through the WebGUI.

View File

@@ -33,6 +33,7 @@ nav:
- Synology: install/synology.md
- Kubernetes: install/kubernetes.md
- KubeSail or PiBox: install/kubesail.md
- TrueNAS Portainer: install/truenas_portainer.md
- WSL: install/wsl.md
- Manual: install/manual.md
- Other setups: install/other.md

View File

@@ -128,34 +128,43 @@ INSTALLED_APPS = [
'treebeard',
]
PLUGINS_DIRECTORY = os.path.join(BASE_DIR, 'recipes', 'plugins')
PLUGINS = []
try:
for d in os.listdir(os.path.join(BASE_DIR, 'recipes', 'plugins')):
if d != '__pycache__':
try:
apps_path = f'recipes.plugins.{d}.apps'
__import__(apps_path)
app_config_classname = dir(sys.modules[apps_path])[1]
plugin_module = f'recipes.plugins.{d}.apps.{app_config_classname}'
if plugin_module not in INSTALLED_APPS:
INSTALLED_APPS.append(plugin_module)
plugin_class = getattr(
sys.modules[apps_path], app_config_classname)
plugin_config = {
'name': plugin_class.verbose_name if hasattr(plugin_class, 'verbose_name') else plugin_class.name,
'module': f'recipes.plugins.{d}',
'base_path': os.path.join(BASE_DIR, 'recipes', 'plugins', d),
'base_url': plugin_class.base_url,
'bundle_name': plugin_class.bundle_name if hasattr(plugin_class, 'bundle_name') else '',
'api_router_name': plugin_class.api_router_name if hasattr(plugin_class, 'api_router_name') else '',
'nav_main': plugin_class.nav_main if hasattr(plugin_class, 'nav_main') else '',
'nav_dropdown': plugin_class.nav_dropdown if hasattr(plugin_class, 'nav_dropdown') else '',
}
PLUGINS.append(plugin_config)
except Exception:
if DEBUG:
traceback.print_exc()
print(f'ERROR failed to initialize plugin {d}')
if os.path.isdir(PLUGINS_DIRECTORY):
for d in os.listdir(PLUGINS_DIRECTORY):
if d != '__pycache__':
try:
apps_path = f'recipes.plugins.{d}.apps'
__import__(apps_path)
app_config_classname = dir(sys.modules[apps_path])[1]
plugin_module = f'recipes.plugins.{d}.apps.{app_config_classname}'
plugin_class = getattr(sys.modules[apps_path], app_config_classname)
plugin_disabled = False
if hasattr(plugin_class, 'disabled'):
plugin_disabled = plugin_class.disabled
if plugin_module not in INSTALLED_APPS and not plugin_disabled:
INSTALLED_APPS.append(plugin_module)
plugin_config = {
'name': plugin_class.verbose_name if hasattr(plugin_class, 'verbose_name') else plugin_class.name,
'version': plugin_class.VERSION if hasattr(plugin_class, 'VERSION') else 'unknown',
'website': plugin_class.website if hasattr(plugin_class, 'website') else '',
'github': plugin_class.github if hasattr(plugin_class, 'github') else '',
'module': f'recipes.plugins.{d}',
'base_path': os.path.join(BASE_DIR, 'recipes', 'plugins', d),
'base_url': plugin_class.base_url,
'bundle_name': plugin_class.bundle_name if hasattr(plugin_class, 'bundle_name') else '',
'api_router_name': plugin_class.api_router_name if hasattr(plugin_class, 'api_router_name') else '',
'nav_main': plugin_class.nav_main if hasattr(plugin_class, 'nav_main') else '',
'nav_dropdown': plugin_class.nav_dropdown if hasattr(plugin_class, 'nav_dropdown') else '',
}
PLUGINS.append(plugin_config)
print(f'PLUGIN {d} loaded')
except Exception:
if DEBUG:
traceback.print_exc()
print(f'ERROR failed to initialize plugin {d}')
except Exception:
if DEBUG:
print('ERROR failed to initialize plugins')
@@ -522,4 +531,4 @@ DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', 'webmaster@localhost')
ACCOUNT_EMAIL_SUBJECT_PREFIX = os.getenv(
'ACCOUNT_EMAIL_SUBJECT_PREFIX', '[Tandoor Recipes] ') # allauth sender prefix
mimetypes.add_type("text/javascript", ".js", True)
mimetypes.add_type("text/javascript", ".js", True)

View File

@@ -1,2 +0,0 @@
VERSION_NUMBER = "0.0.0"
BUILD_REF = ""

View File

@@ -1,5 +1,5 @@
Django==4.1.9
cryptography==41.0.0
Django==4.1.10
cryptography===41.0.3
django-annoying==0.10.6
django-autocomplete-light==3.9.4
django-cleanup==7.0.0
@@ -20,9 +20,9 @@ python-dotenv==0.21.0
requests==2.31.0
six==1.16.0
webdavclient3==3.14.6
whitenoise==6.2.0
whitenoise==6.5.0
icalendar==5.0.4
pyyaml==6.0
pyyaml==6.0.1
uritemplate==4.1.1
beautifulsoup4==4.11.1
microdata==0.8.0
@@ -45,4 +45,4 @@ django-auth-ldap==4.2.0
pytest-factoryboy==2.5.1
pyppeteer==1.0.2
validators==0.20.0
pytube==12.1.0
pytube==15.0.0

74
version.py Normal file
View File

@@ -0,0 +1,74 @@
import os
import re
import subprocess
import sys
import traceback
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
PLUGINS_DIRECTORY = os.path.join(BASE_DIR, 'recipes', 'plugins')
version_info = []
tandoor_tag = ''
tandoor_hash = ''
try:
print('getting tandoor version')
r = subprocess.check_output(['git', 'show', '-s'], cwd=BASE_DIR).decode()
tandoor_branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], cwd=BASE_DIR).decode()
tandoor_hash = r.split('\n')[0].split(' ')[1]
try:
tandoor_tag = subprocess.check_output(['git', 'describe', '--exact-match', tandoor_hash], cwd=BASE_DIR).decode().replace('\n', '')
except:
pass
version_info.append({
'name': 'Tandoor ',
'version': re.sub(r'<.*>', '', r),
'website': 'https://github.com/TandoorRecipes/recipes',
'commit_link': 'https://github.com/TandoorRecipes/recipes/commit/' + r.split('\n')[0].split(' ')[1],
'ref': tandoor_hash,
'branch': tandoor_branch,
'tag': tandoor_tag
})
if os.path.isdir(PLUGINS_DIRECTORY):
for d in os.listdir(PLUGINS_DIRECTORY):
if d != '__pycache__':
try:
apps_path = f'recipes.plugins.{d}.apps'
__import__(apps_path)
app_config_classname = dir(sys.modules[apps_path])[1]
plugin_module = f'recipes.plugins.{d}.apps.{app_config_classname}'
plugin_class = getattr(sys.modules[apps_path], app_config_classname)
print('getting plugin version for ', plugin_class.verbose_name if hasattr(plugin_class, 'verbose_name') else plugin_class.name)
r = subprocess.check_output(['git', 'show', '-s'], cwd=os.path.join(BASE_DIR, 'recipes', 'plugins', d)).decode()
branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], cwd=os.path.join(BASE_DIR, 'recipes', 'plugins', d)).decode()
commit_hash = r.split('\n')[0].split(' ')[1]
try:
print('running describe')
tag = subprocess.check_output(['git', 'describe', '--exact-match', commit_hash], cwd=os.path.join(BASE_DIR, 'recipes', 'plugins', d)).decode().replace('\n', '')
except:
tag = ''
version_info.append({
'name': 'Plugin: ' + plugin_class.verbose_name if hasattr(plugin_class, 'verbose_name') else plugin_class.name,
'version': re.sub(r'<.*>', '', r),
'website': plugin_class.website if hasattr(plugin_class, 'website') else '',
'commit_link': plugin_class.github if hasattr(plugin_class, 'github') else '' + '/commit/' + commit_hash,
'ref': commit_hash,
'branch': branch,
'tag': tag
})
except subprocess.CalledProcessError as e:
print("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
except Exception:
traceback.print_exc()
except subprocess.CalledProcessError as e:
print("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
except:
traceback.print_exc()
with open('cookbook/version_info.py', 'w+', encoding='UTF-8') as f:
print(f"writing version info {version_info}")
f.write(f'TANDOOR_VERSION = "{tandoor_tag}"\nTANDOOR_REF = "{tandoor_hash}"\nVERSION_INFO = {version_info}')

View File

@@ -675,12 +675,26 @@ export default {
*/
autoImport: function () {
this.collapse_visible.import = true
this.website_url_list.split('\n').forEach(r => {
this.loadRecipe(r, true, undefined).then((recipe_json) => {
let url_list = this.website_url_list.split('\n').filter(x => x.trim() !== '')
if (url_list.length > 0) {
let url = url_list.shift()
this.website_url_list = url_list.join('\n')
this.loadRecipe(url, true, undefined).then((recipe_json) => {
this.importRecipe('multi_import', recipe_json, true)
setTimeout(() => {
this.autoImport()
}, 2000)
}).catch((err) => {
})
})
this.website_url_list = ''
} else {
this.import_loading = false
this.loading = false
}
},
/**
* Import recipes with uploaded files and app integration

View File

@@ -1254,28 +1254,34 @@ export default {
ing_list.forEach((ing) => {
if (ing.trim() !== "") {
promises.push(this.genericPostAPI("api_ingredient_from_string", {text: ing}).then((result) => {
let unit = null
if (result.data.unit !== "" && result.data.unit !== null) {
unit = {name: result.data.unit}
}
parsed_ing_list.push({
let new_ingredient = {
amount: result.data.amount,
unit: unit,
food: {name: result.data.food},
note: result.data.note,
original_text: ing,
})
}
console.log(ing, new_ingredient)
parsed_ing_list.push(new_ingredient)
}))
}
})
Promise.allSettled(promises).then(() => {
ing_list.forEach(ing => {
step.ingredients.push(parsed_ing_list.find(x => x.original_text === ing))
if(ing.trim() !== ""){
step.ingredients.push(parsed_ing_list.find(x => x.original_text === ing))
}
})
})
},
duplicateIngredient: function (step, ingredient, new_index) {
delete ingredient.id
ingredient = JSON.parse(JSON.stringify(ingredient))
step.ingredients.splice(new_index < 0 ? 0 : new_index, 0, ingredient)
}
},

View File

@@ -48,7 +48,7 @@
</tr>
</thead>
<tr v-for="us in user_spaces" :key="us.id">
<td>{{ us.user.username }}</td>
<td>{{ us.user.display_name }}</td>
<td>
<generic-multiselect
class="input-group-text m-0 p-0"
@@ -238,8 +238,8 @@ export default {
apiFactory.retrieveSpace(window.ACTIVE_SPACE_ID).then(r => {
this.space = r.data
})
apiFactory.listUserSpaces().then(r => {
this.user_spaces = r.data
apiFactory.listUserSpaces(1, 25).then(r => { //TODO build proper pagination
this.user_spaces = r.data.results
})
this.loadInviteLinks()
},

View File

@@ -25,6 +25,9 @@
<b-form-group :label="$t('Plural')" description="">
<b-form-input v-model="food.plural_name"></b-form-input>
</b-form-group>
<b-form-group :label="$t('Description')" description="">
<b-form-textarea v-model="food.description" rows="2"></b-form-textarea>
</b-form-group>
<!-- Food properties -->
@@ -71,8 +74,8 @@
}}</span></span>
</td>
<td>
<button class="btn btn-danger btn-small" @click="deleteProperty(fp)"><i
class="fas fa-trash-alt"></i></button>
<a class="btn btn-danger btn-small" @click="deleteProperty(fp)"><i
class="fas fa-trash-alt"></i></a>
</td>
</tr>
</table>
@@ -167,6 +170,10 @@
></generic-multiselect>
</b-form-group>
<b-form-group :label="$t('URL')" description="">
<b-form-input v-model="food.url"></b-form-input>
</b-form-group>
<b-form-group :description="$t('OnHand_help')">
<b-form-checkbox v-model="food.food_onhand">{{ $t('OnHand') }}</b-form-checkbox>
</b-form-group>
@@ -293,7 +300,9 @@ export default {
if (this.item1.id !== undefined) {
pf = apiClient.retrieveFood(this.item1.id).then((r) => {
this.food = r.data
this.food.properties_food_unit = {name: 'g'}
if (this.food.properties_food_unit === null) {
this.food.properties_food_unit = {name: 'g'}
}
}).catch(err => {
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
})
@@ -304,6 +313,7 @@ export default {
description: "",
shopping: false,
recipe: null,
url: '',
properties: [],
properties_food_amount: 100,
properties_food_unit: {name: 'g'},

View File

@@ -30,21 +30,13 @@
</td>
<td @click="done">
<template v-if="ingredient.food !== null">
<a :href="resolveDjangoUrl('view_recipe', ingredient.food.recipe.id)" v-if="ingredient.food.recipe !== null" target="_blank" rel="noopener noreferrer">{{
ingredient.food.name
}}</a>
<template v-if="ingredient.food.recipe === null">
<template>
<template v-if="ingredient.food.plural_name === '' || ingredient.food.plural_name === null">
<span>{{ ingredient.food.name }}</span>
</template>
<template v-else>
<span v-if="ingredient.always_use_plural_food">{{ ingredient.food.plural_name }}</span>
<span v-else-if="ingredient.no_amount">{{ ingredient.food.name }}</span>
<span v-else-if="ingredient.amount * this.ingredient_factor > 1">{{ ingredient.food.plural_name }}</span>
<span v-else>{{ ingredient.food.name }}</span>
</template>
</template>
<a :href="resolveDjangoUrl('view_recipe', ingredient.food.recipe.id)" v-if="ingredient.food.recipe !== null" target="_blank" rel="noopener noreferrer">
{{ ingredientName(ingredient) }}
</a>
<a :href="ingredient.food.url" v-else-if="ingredient.food.url !== ''" target="_blank" rel="noopener noreferrer">
{{ ingredientName(ingredient) }}</a>
<template v-else>
<span>{{ ingredientName(ingredient) }}</span>
</template>
</template>
</td>
@@ -62,7 +54,7 @@
</template>
<script>
import { calculateAmount, ResolveUrlMixin } from "@/utils/utils"
import {calculateAmount, ResolveUrlMixin} from "@/utils/utils"
import Vue from "vue"
import VueSanitize from "vue-sanitize"
@@ -73,8 +65,8 @@ export default {
name: "IngredientComponent",
props: {
ingredient: Object,
ingredient_factor: { type: Number, default: 1 },
detailed: { type: Boolean, default: true },
ingredient_factor: {type: Number, default: 1},
detailed: {type: Boolean, default: true},
},
mixins: [ResolveUrlMixin],
data() {
@@ -83,7 +75,8 @@ export default {
}
},
watch: {},
mounted() {},
mounted() {
},
methods: {
calculateAmount: function (x) {
return this.$sanitize(calculateAmount(x, this.ingredient_factor))
@@ -92,6 +85,20 @@ export default {
done: function () {
this.$emit("checked-state-changed", this.ingredient)
},
ingredientName: function (ingredient) {
if (ingredient.food.plural_name == null || ingredient.food.plural_name === '') {
return ingredient.food.name
}
if (ingredient.always_use_plural_food) {
return ingredient.food.plural_name
} else if (ingredient.no_amount) {
return ingredient.food.name
} else if (ingredient.amount * this.ingredient_factor > 1) {
return ingredient.food.plural_name
} else {
return ingredient.food.name
}
}
},
}
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div>
<b-form-group v-bind:label="label" class="mb-3">
<b-form-group v-bind:label="field_label" class="mb-3">
<b-form-select v-model="new_value" :placeholder="placeholder" :options="translatedOptions"></b-form-select>
</b-form-group>
</div>
@@ -10,12 +10,13 @@
export default {
name: "ChoiceInput",
props: {
field: { type: String, default: "You Forgot To Set Field Name" },
label: { type: String, default: "Text Field" },
value: { type: String, default: "" },
field: {type: String, default: "You Forgot To Set Field Name"},
label: {type: String, default: "Text Field"},
value: {type: String, default: ""},
options: [],
placeholder: { type: String, default: "You Should Add Placeholder Text" },
show_merge: { type: Boolean, default: false },
placeholder: {type: String, default: "You Should Add Placeholder Text"},
show_merge: {type: Boolean, default: false},
optional: {type: Boolean, default: false},
},
data() {
return {
@@ -31,9 +32,16 @@ export default {
},
},
computed: {
field_label: function () {
if (this.optional) {
return this.label
} else {
return this.label + '*'
}
},
translatedOptions() {
return this.options.map((x) => {
return { ...x, text: this.$t(x.text) }
return {...x, text: this.$t(x.text)}
})
},
},

View File

@@ -1,6 +1,6 @@
<template>
<div>
<b-form-group v-bind:label="label" class="mb-3">
<b-form-group v-bind:label="field_label" class="mb-3">
<b-form-input v-model="new_value" type="date" ></b-form-input>
<em v-if="help" class="small text-muted">{{ help }}</em>
<small v-if="subtitle" class="text-muted">{{ subtitle }}</small>
@@ -17,6 +17,16 @@ export default {
value: { type: String, default: "" },
help: { type: String, default: undefined },
subtitle: { type: String, default: undefined },
optional: {type: Boolean, default: false},
},
computed: {
field_label: function () {
if (this.optional) {
return this.label
} else {
return this.label + '*'
}
}
},
data() {
return {

View File

@@ -1,7 +1,7 @@
<template>
<div>
<b-form-group
v-bind:label="label"
v-bind:label="field_label"
class="mb-3">
<input class="form-control" v-model="new_value">
@@ -27,6 +27,7 @@ export default {
field: {type: String, default: 'You Forgot To Set Field Name'},
label: {type: String, default: ''},
value: {type: String, default: ''},
optional: {type: Boolean, default: false},
},
data() {
return {
@@ -36,6 +37,15 @@ export default {
emojisOutput: ""
}
},
computed: {
field_label: function () {
if (this.optional) {
return this.label
} else {
return this.label + '*'
}
}
},
watch: {
'new_value': function () {
this.$root.$emit('change', this.field, this.new_value ?? null)

View File

@@ -1,7 +1,7 @@
<template>
<div>
<b-form-group
v-bind:label="label"
v-bind:label="field_label"
class="mb-3">
<b-form-file
v-model="new_value"
@@ -30,7 +30,17 @@ export default {
value: {type: String, default: ''},
placeholder: {type: String, default: ''},
show_merge: {type: Boolean, default: false},
optional: {type: Boolean, default: false},
},
computed: {
field_label: function () {
if (this.optional) {
return this.label
} else {
return this.label + '*'
}
}
},
data() {
return {
new_value: undefined,

View File

@@ -11,15 +11,16 @@
</template>
<div v-for="(f, i) in form.fields" v-bind:key="i">
<p v-if="visibleCondition(f, 'instruction')">{{ f.label }}</p>
<lookup-input v-if="visibleCondition(f, 'lookup')" :form="f" :model="listModel(f.list)" @change="storeValue" :help="showHelp && f.help"/>
<lookup-input v-if="visibleCondition(f, 'lookup')" :form="f" :model="listModel(f.list)" @change="storeValue" :help="showHelp && f.help" :optional="f.optional"/>
<checkbox-input class="mb-3" v-if="visibleCondition(f, 'checkbox')" :label="f.label" :value="f.value" :field="f.field" :help="showHelp && f.help"/>
<text-input v-if="visibleCondition(f, 'text')" :label="f.label" :value="f.value" :field="f.field" :placeholder="f.placeholder" :help="showHelp && f.help" :subtitle="f.subtitle" :disabled="f.disabled"/>
<choice-input v-if="visibleCondition(f, 'choice')" :label="f.label" :value="f.value" :field="f.field" :options="f.options" :placeholder="f.placeholder"/>
<emoji-input v-if="visibleCondition(f, 'emoji')" :label="f.label" :value="f.value" :field="f.field" @change="storeValue"/>
<file-input v-if="visibleCondition(f, 'file')" :label="f.label" :value="f.value" :field="f.field" @change="storeValue"/>
<small-text v-if="visibleCondition(f, 'smalltext')" :value="f.value"/>
<date-input v-if="visibleCondition(f, 'date')" :label="f.label" :value="f.value" :field="f.field" :help="showHelp && f.help" :subtitle="f.subtitle"/>
<number-input v-if="visibleCondition(f, 'number')" :label="f.label" :value="f.value" :field="f.field" :placeholder="f.placeholder" :help="showHelp && f.help" :subtitle="f.subtitle"/>
<text-input v-if="visibleCondition(f, 'text')" :label="f.label" :value="f.value" :field="f.field" :placeholder="f.placeholder" :help="showHelp && f.help" :subtitle="f.subtitle" :disabled="f.disabled" :optional="f.optional"/>
<text-area-input v-if="visibleCondition(f, 'textarea')" :label="f.label" :value="f.value" :field="f.field" :placeholder="f.placeholder" :help="showHelp && f.help" :subtitle="f.subtitle" :disabled="f.disabled" :optional="f.optional"/>
<choice-input v-if="visibleCondition(f, 'choice')" :label="f.label" :value="f.value" :field="f.field" :options="f.options" :placeholder="f.placeholder" :optional="f.optional"/>
<emoji-input v-if="visibleCondition(f, 'emoji')" :label="f.label" :value="f.value" :field="f.field" @change="storeValue" :optional="f.optional"/>
<file-input v-if="visibleCondition(f, 'file')" :label="f.label" :value="f.value" :field="f.field" @change="storeValue" :optional="f.optional"/>
<small-text v-if="visibleCondition(f, 'smalltext')" :value="f.value" />
<date-input v-if="visibleCondition(f, 'date')" :label="f.label" :value="f.value" :field="f.field" :help="showHelp && f.help" :subtitle="f.subtitle" :optional="f.optional"/>
<number-input v-if="visibleCondition(f, 'number')" :label="f.label" :value="f.value" :field="f.field" :placeholder="f.placeholder" :help="showHelp && f.help" :subtitle="f.subtitle" :optional="f.optional"/>
</div>
<template v-slot:modal-footer>
<div class="row w-100">
@@ -57,6 +58,7 @@ import FileInput from "@/components/Modals/FileInput"
import SmallText from "@/components/Modals/SmallText"
import HelpBadge from "@/components/Badges/Help"
import NumberInput from "@/components/Modals/NumberInput.vue";
import TextAreaInput from "@/components/Modals/TextAreaInput.vue";
export default {
name: "GenericModalForm",
@@ -70,7 +72,8 @@ export default {
SmallText,
HelpBadge,
DateInput,
NumberInput
NumberInput,
TextAreaInput
},
mixins: [ApiMixin, ToastMixin],
props: {

View File

@@ -2,7 +2,7 @@
<div>
<b-form-group :class="class_list">
<template #label v-if="show_label">
{{ form.label }}
{{ field_label }}
</template>
<generic-multiselect
@change="new_value = $event.val"
@@ -27,11 +27,11 @@
<script>
import GenericMultiselect from "@/components/GenericMultiselect"
import { StandardToasts, ApiMixin } from "@/utils/utils"
import {StandardToasts, ApiMixin} from "@/utils/utils"
export default {
name: "LookupInput",
components: { GenericMultiselect },
components: {GenericMultiselect},
mixins: [ApiMixin],
props: {
form: {
@@ -46,11 +46,13 @@ export default {
return undefined
},
},
class_list: { type: String, default: "mb-3" },
show_label: { type: Boolean, default: true },
clear: { type: Number },
help: { type: String, default: undefined },
class_list: {type: String, default: "mb-3"},
show_label: {type: Boolean, default: true},
clear: {type: Number},
help: {type: String, default: undefined},
optional: {type: Boolean, default: false},
},
data() {
return {
new_value: undefined,
@@ -67,7 +69,7 @@ export default {
this.label = this.form?.label ?? ""
this.sticky_options = this.form?.sticky_options ?? []
this.sticky_options = this.sticky_options.map((x) => {
return { ...x, name: this.$t(x.name) }
return {...x, name: this.$t(x.name)}
})
this.list_label = this.form?.list_label ?? undefined
if (this.list_label?.includes("::")) {
@@ -75,6 +77,13 @@ export default {
}
},
computed: {
field_label: function () {
if (this.optional) {
return this.form.label
} else {
return this.form.label + '*'
}
},
modelName() {
return this.$t(this?.model?.name) ?? this.$t("Search")
},
@@ -124,7 +133,7 @@ export default {
let item = undefined
let label = this.form.list_label.split("::")
itemlist.forEach((x) => {
item = { ...x }
item = {...x}
for (const [k, v] of Object.entries(x)) {
if (k == label[0]) {
item["id"] = v.id

View File

@@ -1,6 +1,6 @@
<template>
<div>
<b-form-group v-bind:label="label" class="mb-3">
<b-form-group v-bind:label="field_label" class="mb-3">
<b-form-input v-model="new_value" type="number" :placeholder="placeholder"></b-form-input>
<em v-if="help" class="small text-muted">{{ help }}</em>
<small v-if="subtitle" class="text-muted">{{ subtitle }}</small>
@@ -18,6 +18,16 @@ export default {
placeholder: { type: Number, default: 0 },
help: { type: String, default: undefined },
subtitle: { type: String, default: undefined },
optional: {type: Boolean, default: false},
},
computed: {
field_label: function () {
if (this.optional) {
return this.label
} else {
return this.label + '*'
}
}
},
data() {
return {

View File

@@ -0,0 +1,48 @@
<template>
<div>
<b-form-group v-bind:label="field_label" class="mb-3">
<b-form-textarea v-model="new_value" type="text" :placeholder="placeholder" :disabled="disabled"></b-form-textarea>
<em v-if="help" class="small text-muted">{{ help }}</em>
<small v-if="subtitle" class="text-muted">{{ subtitle }}</small>
</b-form-group>
</div>
</template>
<script>
export default {
name: "TextAreaInput",
props: {
field: {type: String, default: "You Forgot To Set Field Name"},
label: {type: String, default: "Text Field"},
value: {type: String, default: ""},
placeholder: {type: String, default: "You Should Add Placeholder Text"},
help: {type: String, default: undefined},
subtitle: {type: String, default: undefined},
disabled: {type: Boolean, default: false},
optional: {type: Boolean, default: false},
},
computed: {
field_label: function () {
if (this.optional) {
return this.label
} else {
return this.label + '*'
}
}
},
data() {
return {
new_value: undefined,
}
},
mounted() {
this.new_value = this.value
},
watch: {
new_value: function () {
this.$root.$emit("change", this.field, this.new_value)
},
},
methods: {},
}
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div>
<b-form-group v-bind:label="label" class="mb-3">
<b-form-group v-bind:label="field_label" class="mb-3">
<b-form-input v-model="new_value" type="text" :placeholder="placeholder" :disabled="disabled"></b-form-input>
<em v-if="help" class="small text-muted">{{ help }}</em>
<small v-if="subtitle" class="text-muted">{{ subtitle }}</small>
@@ -18,13 +18,23 @@ export default {
placeholder: { type: String, default: "You Should Add Placeholder Text" },
help: { type: String, default: undefined },
subtitle: { type: String, default: undefined },
disabled: { type: Boolean, default: false }
disabled: { type: Boolean, default: false },
optional: {type: Boolean, default: false},
},
data() {
return {
new_value: undefined,
}
},
computed: {
field_label: function () {
if (this.optional) {
return this.label
} else {
return this.label + '*'
}
}
},
mounted() {
this.new_value = this.value
},

View File

@@ -1,28 +1,28 @@
<template>
<div>
<iframe :src="pdfUrl" width="100%" height="700px" style="border: none;"></iframe>
</div>
<div>
<iframe :src="pdfUrl" width="100%" height="700px" style="border: none;"></iframe>
</div>
</template>
<script>
import {resolveDjangoUrl, ResolveUrlMixin} from "@/utils/utils";
import {resolveDjangoStatic, resolveDjangoUrl, ResolveUrlMixin} from "@/utils/utils";
export default {
name: 'PdfViewer',
mixins: [
ResolveUrlMixin
],
props: {
recipe: Object,
},
computed: {
pdfUrl: function() {
return '/static/pdfjs/viewer.html?file=' + resolveDjangoUrl('api_get_recipe_file', (this.recipe.id))
}
},
name: 'PdfViewer',
mixins: [
ResolveUrlMixin
],
props: {
recipe: Object,
},
computed: {
pdfUrl: function () {
return resolveDjangoStatic('pdfjs/viewer.html?file=' + resolveDjangoUrl('api_get_recipe_file', (this.recipe.id)))
}
},
}
</script>

View File

@@ -2,7 +2,7 @@
<div>
<div class="card p-4 pb-2" v-if="recipe !== undefined">
<div class="card p-4 pb-2" v-if="recipe !== undefined && property_list.length > 0">
<b-row>
<b-col>
<h5><i class="fas fa-database"></i> {{ $t('Properties') }}</h5>

View File

@@ -149,7 +149,8 @@
<div class="row text-center d-print-none" style="margin-top: 3vh; margin-bottom: 3vh"
v-if="share_uid !== 'None' && !loading">
<div class="col col-md-12">
<import-tandoor></import-tandoor> <br/>
<import-tandoor></import-tandoor>
<br/>
<a :href="resolveDjangoUrl('view_report_share_abuse', share_uid)" class="mt-3">{{ $t("Report Abuse") }}</a>
</div>
</div>
@@ -236,6 +237,7 @@ export default {
},
props: {
recipe_id: Number,
recipe_obj: {type: Object, default: null},
show_context_menu: {type: Boolean, default: true},
enable_keyword_links: {type: Boolean, default: true},
show_recipe_switcher: {type: Boolean, default: true},
@@ -247,7 +249,14 @@ export default {
},
},
mounted() {
this.loadRecipe(this.recipe_id)
if (this.recipe_obj !== null) {
this.recipe = this.rootrecipe = this.recipe_obj
this.prepareView()
} else {
this.loadRecipe(this.recipe_id)
}
this.$i18n.locale = window.CUSTOM_LOCALE
this.requestWakeLock()
window.addEventListener('resize', this.handleResize);
@@ -291,33 +300,36 @@ export default {
},
loadRecipe: function (recipe_id) {
apiLoadRecipe(recipe_id).then((recipe) => {
let total_time = 0
for (let step of recipe.steps) {
for (let ingredient of step.ingredients) {
this.$set(ingredient, "checked", false)
}
step.time_offset = total_time
total_time += step.time
}
// set start time only if there are any steps with timers (otherwise no timers are rendered)
if (total_time > 0) {
this.start_time = moment().format("yyyy-MM-DDTHH:mm")
}
if (recipe.image === null) this.printReady()
this.recipe = this.rootrecipe = recipe
this.servings = this.servings_cache[this.rootrecipe.id] = recipe.servings
this.loading = false
setTimeout(() => {
this.handleResize()
}, 100)
this.prepareView()
})
},
prepareView: function () {
let total_time = 0
for (let step of this.recipe.steps) {
for (let ingredient of step.ingredients) {
this.$set(ingredient, "checked", false)
}
step.time_offset = total_time
total_time += step.time
}
// set start time only if there are any steps with timers (otherwise no timers are rendered)
if (total_time > 0) {
this.start_time = moment().format("yyyy-MM-DDTHH:mm")
}
if (this.recipe.image === null) this.printReady()
this.servings = this.servings_cache[this.rootrecipe.id] = this.recipe.servings
this.loading = false
setTimeout(() => {
this.handleResize()
}, 100)
},
updateStartTime: function (e) {
this.start_time = e
},

View File

@@ -50,6 +50,7 @@
<b-form-select-option value="DARKLY">Darkly</b-form-select-option>
<b-form-select-option value="FLATLY">Flatly</b-form-select-option>
<b-form-select-option value="SUPERHERO">Superhero</b-form-select-option>
<b-form-select-option value="TANDOOR_DARK">Tandoor Dark (INCOMPLETE)</b-form-select-option>
</b-form-select>
</b-form-group>

View File

@@ -4,6 +4,8 @@ import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
function loadLocaleMessages () {
const start_time = Date.now();
console.log('started loading locale messages')
const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
const messages = {}
locales.keys().forEach(key => {
@@ -13,6 +15,7 @@ function loadLocaleMessages () {
messages[locale] = locales(key)
}
})
console.log('finished loading messages in ', Date.now() - start_time, ' ms')
return messages
}

View File

@@ -1,457 +1,457 @@
{
"warning_feature_beta": "",
"err_fetching_resource": "",
"err_creating_resource": "",
"err_updating_resource": "",
"err_deleting_resource": "",
"err_deleting_protected_resource": "",
"err_moving_resource": "",
"err_merging_resource": "",
"success_fetching_resource": "",
"success_creating_resource": "",
"success_updating_resource": "",
"success_deleting_resource": "",
"success_moving_resource": "",
"success_merging_resource": "",
"file_upload_disabled": "",
"warning_space_delete": "",
"food_inherit_info": "",
"facet_count_info": "",
"step_time_minutes": "",
"confirm_delete": "",
"import_running": "",
"all_fields_optional": "",
"convert_internal": "",
"show_only_internal": "",
"show_split_screen": "",
"warning_feature_beta": "Tato funkce je momentálně ve fázi Beta (testování). Očekávejte, prosím, chyby. V budoucnosti může dojít i ke ztrátě dat.",
"err_fetching_resource": "Během načítání došlo k chybě!",
"err_creating_resource": "Během vytváření došlo k chybě!",
"err_updating_resource": "Během úprav došlo k chybě!",
"err_deleting_resource": "Během mazání došlo k chybě!",
"err_deleting_protected_resource": "Položka, kterou chcete smazat, je stále používána a nemůže být odstraněna.",
"err_moving_resource": "Během přesunu došlo k chybě!",
"err_merging_resource": "Během slučování došlo k chybě!",
"success_fetching_resource": "Úspěšně načteno!",
"success_creating_resource": "Úspěšně vytvořeno!",
"success_updating_resource": "Úspěšně upraveno!",
"success_deleting_resource": "Úspěšně smazáno!",
"success_moving_resource": "Úspěšně přesunuto!",
"success_merging_resource": "Úspěšně sloučeno!",
"file_upload_disabled": "Nahrávání souborů není povoleno pro Váš prostor.",
"warning_space_delete": "Můžete smazat váš prostor včetně všech receptů, nákupních seznamů, jídelníčků a všeho ostatního, co jste vytvořili. Tuto akci nemůžete vzít zpět! Jste si jisti, že chcete pokračovat?",
"food_inherit_info": "Pole potravin, která budou standardně zděděna.",
"facet_count_info": "Zobraz počet receptů u filtrů vyhledávání.",
"step_time_minutes": "Nastavte čas v minutách",
"confirm_delete": "Jste si jisti že chcete odstranit tento {objekt}?",
"import_running": "Probíhá import, čekejte prosím!",
"all_fields_optional": "Všechna pole jsou nepviná a mohou být ponechána prázdná.",
"convert_internal": "Převést na interní recept",
"show_only_internal": "Zobrazit pouze interní recepty",
"show_split_screen": "Rozdělené zobrazení",
"Log_Recipe_Cooking": "",
"External_Recipe_Image": "",
"Add_to_Shopping": "",
"Add_to_Plan": "",
"Step_start_time": "",
"Sort_by_new": "",
"Table_of_Contents": "",
"External_Recipe_Image": "Externí obrázek receptu",
"Add_to_Shopping": "Přidat k nákupu",
"Add_to_Plan": "Přidat do jídelníčku",
"Step_start_time": "Nastav počáteční čas",
"Sort_by_new": "Seřadit od nejnovějšího",
"Table_of_Contents": "Obsah",
"Recipes_per_page": "Receptů na stránku",
"Show_as_header": "",
"Hide_as_header": "",
"Show_as_header": "Nastav jako nadpis",
"Hide_as_header": "Skryj jako nadpis",
"Add_nutrition_recipe": "Přidat nutriční hodnoty",
"Remove_nutrition_recipe": "Smazat nutriční hodnoty",
"Copy_template_reference": "",
"Save_and_View": "Uložit & Zobrazit",
"Manage_Books": "",
"Manage_Books": "Spravovat kuchařky",
"Meal_Plan": "Jídelníček",
"Select_Book": "",
"Select_Book": "Vyber kuchařku",
"Select_File": "Vybrat soubor",
"Recipe_Image": "",
"Recipe_Image": "Obrázek k receptu",
"Import_finished": "Import dokončen",
"View_Recipes": "Zobrazit recepty",
"Log_Cooking": "",
"New_Recipe": "Nový recept",
"Url_Import": "",
"Reset_Search": "",
"Recently_Viewed": "",
"Load_More": "",
"New_Keyword": "",
"Delete_Keyword": "",
"Edit_Keyword": "",
"Url_Import": "Import pomocí URL odkazu",
"Reset_Search": "Zrušit filtry vyhledávání",
"Recently_Viewed": "Naposledy prohlížené",
"Load_More": "Načíst další",
"New_Keyword": "Nové klíčové slovo",
"Delete_Keyword": "Smazat klíčové slovo",
"Edit_Keyword": "Upravit klíčové slovo",
"Edit_Recipe": "Upravit recept",
"Move_Keyword": "",
"Merge_Keyword": "",
"Hide_Keywords": "",
"Hide_Recipes": "",
"Move_Keyword": "Přesunout klíčové slovo",
"Merge_Keyword": "Sloučit klíčové slovo",
"Hide_Keywords": "Skrýt klíčové slovo",
"Hide_Recipes": "Skrýt recept",
"Move_Up": "Nahoru",
"Move_Down": "Dolů",
"Step_Name": "Název kroku",
"Step_Type": "",
"Make_Header": "",
"Make_Ingredient": "",
"Step_Type": "Druh kroku",
"Make_Header": "Použij jako nadpis",
"Make_Ingredient": "Použij jako ingredienci",
"Amount": "Množství",
"Enable_Amount": "Zobrazit množství",
"Disable_Amount": "Skrýt množství",
"Ingredient Editor": "Editace ingrediencí",
"Description_Replace": "",
"Instruction_Replace": "",
"Auto_Sort": "",
"Auto_Sort_Help": "",
"Private_Recipe": "",
"Private_Recipe_Help": "",
"reusable_help_text": "",
"Add_Step": "",
"Keywords": "",
"Books": "",
"Description_Replace": "Nahraď popis",
"Instruction_Replace": "Nahraď instrukce",
"Auto_Sort": "Automatické řazení",
"Auto_Sort_Help": "Přiřadit všechny ingredience k nejlépe vyhovujícímu kroku.",
"Private_Recipe": "Soukromý recept",
"Private_Recipe_Help": "Recept můžete zobrazit pouze vy a lidé, se kterými jej sdílíte.",
"reusable_help_text": "Má-li pozvánka platit pro více než jednoho uživatele.",
"Add_Step": "Přidat krok",
"Keywords": "Klíčová slova",
"Books": "Kuchařky",
"Proteins": "Proteiny",
"Fats": "Tuky",
"Carbohydrates": "",
"Calories": "",
"Energy": "",
"Carbohydrates": "Sacharidy",
"Calories": "Kalorie",
"Energy": "Energie",
"Nutrition": "",
"Date": "",
"Share": "",
"Automation": "",
"Parameter": "",
"Export": "",
"Copy": "",
"Rating": "",
"Close": "",
"Cancel": "",
"Link": "",
"Add": "",
"New": "",
"Note": "",
"Success": "",
"Failure": "",
"Protected": "",
"Ingredients": "",
"Supermarket": "",
"Categories": "",
"Category": "",
"Selected": "",
"min": "",
"Servings": "",
"Waiting": "",
"Preparation": "",
"External": "",
"Size": "",
"Files": "",
"File": "",
"Edit": "",
"Image": "",
"Delete": "",
"Open": "",
"Ok": "",
"Save": "",
"Step": "",
"Search": "",
"Import": "",
"Print": "",
"Settings": "",
"or": "",
"and": "",
"Information": "",
"Download": "",
"Create": "",
"Search Settings": "",
"View": "",
"Recipes": "",
"Move": "",
"Merge": "",
"Parent": "",
"Copy Link": "",
"Copy Token": "",
"delete_confirmation": "",
"move_confirmation": "",
"merge_confirmation": "",
"create_rule": "",
"move_selection": "",
"merge_selection": "",
"Root": "",
"Ignore_Shopping": "",
"Shopping_Category": "",
"Shopping_Categories": "",
"Edit_Food": "",
"Move_Food": "",
"New_Food": "",
"Hide_Food": "",
"Food_Alias": "",
"Unit_Alias": "",
"Keyword_Alias": "",
"Delete_Food": "",
"No_ID": "",
"Meal_Plan_Days": "",
"merge_title": "",
"move_title": "",
"Food": "",
"Original_Text": "",
"Recipe_Book": "",
"del_confirmation_tree": "",
"delete_title": "",
"create_title": "",
"edit_title": "",
"Name": "",
"Type": "",
"Description": "",
"Recipe": "",
"Date": "Datum",
"Share": "Sdílet",
"Automation": "Automatizace",
"Parameter": "Parametr",
"Export": "Export",
"Copy": "Kopírovat",
"Rating": "Hodnocení",
"Close": "Zavřít",
"Cancel": "Zrušit",
"Link": "Odkaz",
"Add": "Přidat",
"New": "Nový",
"Note": "Poznámka",
"Success": "Úspěch",
"Failure": "Selhání",
"Protected": "Chráněný",
"Ingredients": "Ingredience",
"Supermarket": "Obchod",
"Categories": "Kategorie",
"Category": "Kategorie",
"Selected": "Vybrané",
"min": "min",
"Servings": "Porce",
"Waiting": "Čekající",
"Preparation": "Příprava",
"External": "Externí",
"Size": "Velikost",
"Files": "Soubory",
"File": "Soubor",
"Edit": "Upravit",
"Image": "Obrázek",
"Delete": "Smazat",
"Open": "Otevřít",
"Ok": "Ok",
"Save": "Uložit",
"Step": "Krok",
"Search": "Hledat",
"Import": "Import",
"Print": "Tisk",
"Settings": "Nastavení",
"or": "nebo",
"and": "a",
"Information": "Informace",
"Download": "Stáhnout",
"Create": "Vytvořit",
"Search Settings": "Nastavení vyhledávání",
"View": "Zobrazit",
"Recipes": "Recepty",
"Move": "Přesunout",
"Merge": "Spojit",
"Parent": "Nadřazená",
"Copy Link": "Kopírovat odkaz",
"Copy Token": "Kopírovat token",
"delete_confirmation": "Jste si jistí, že chcete smazat {source}?",
"move_confirmation": "Přesunout <i>{child}</i> do nadřazené <i>{parent}</i>",
"merge_confirmation": "Nahradit <i>{source}</i> za <i>{target}</i>",
"create_rule": "a vytvořit automatizaci",
"move_selection": "Vybrat nadřazený {type} kam {source} přesunout.",
"merge_selection": "Nahradit všechny výskyty {source} za vybraný {type}.",
"Root": "Kořen",
"Ignore_Shopping": "Ignorovat nákupní seznam",
"Shopping_Category": "Kategorie nákupního seznamu",
"Shopping_Categories": "Kategorie nákupního seznamu",
"Edit_Food": "Upravit potravinu",
"Move_Food": "Přesunout potravinu",
"New_Food": "Nová potravina",
"Hide_Food": "Skrýt potravinu",
"Food_Alias": "Přezdívka potraviny",
"Unit_Alias": "Přezdívka jednotky",
"Keyword_Alias": "Přezdívka klíčového slova",
"Delete_Food": "Smazat potravinu",
"No_ID": "ID nenalezeno, odstranění není možné.",
"Meal_Plan_Days": "Budoucí jídelníčky",
"merge_title": "Sloučit {type}",
"move_title": "Přesunout {type}",
"Food": "Potravina",
"Original_Text": "Původní text",
"Recipe_Book": "Kuchařka",
"del_confirmation_tree": "Jste si jistí, že chcete odstranit {source} se všemi pořazenými ?",
"delete_title": "Smazat {type}",
"create_title": "Nový {type}",
"edit_title": "Upravit {type}",
"Name": "Jméno",
"Type": "Typ",
"Description": "Popis",
"Recipe": "Recept",
"tree_root": "",
"Icon": "",
"Unit": "",
"Decimals": "",
"Default_Unit": "",
"No_Results": "",
"New_Unit": "",
"Create_New_Shopping Category": "",
"Create_New_Food": "",
"Create_New_Keyword": "",
"Create_New_Unit": "",
"Create_New_Meal_Type": "",
"Create_New_Shopping_Category": "",
"and_up": "",
"and_down": "",
"Instructions": "",
"Unrated": "",
"Automate": "",
"Empty": "",
"Key_Ctrl": "",
"Key_Shift": "",
"Time": "",
"Text": "",
"Shopping_list": "",
"Added_by": "",
"Added_on": "",
"AddToShopping": "",
"IngredientInShopping": "",
"NotInShopping": "",
"OnHand": "",
"FoodOnHand": "",
"FoodNotOnHand": "",
"Undefined": "",
"Create_Meal_Plan_Entry": "",
"Edit_Meal_Plan_Entry": "",
"Title": "",
"Week": "",
"Month": "",
"Year": "",
"Planner": "",
"Planner_Settings": "",
"Period": "",
"Plan_Period_To_Show": "",
"Periods": "",
"Plan_Show_How_Many_Periods": "",
"Starting_Day": "",
"Meal_Types": "",
"Meal_Type": "",
"New_Entry": "",
"Clone": "",
"Drag_Here_To_Delete": "",
"Meal_Type_Required": "",
"Title_or_Recipe_Required": "",
"Color": "",
"New_Meal_Type": "",
"Use_Fractions": "",
"Use_Fractions_Help": "",
"AddFoodToShopping": "",
"RemoveFoodFromShopping": "",
"DeleteShoppingConfirm": "",
"IgnoredFood": "",
"Add_Servings_to_Shopping": "",
"Week_Numbers": "",
"Show_Week_Numbers": "",
"Export_As_ICal": "",
"Export_To_ICal": "",
"Cannot_Add_Notes_To_Shopping": "",
"Added_To_Shopping_List": "",
"Shopping_List_Empty": "",
"Next_Period": "",
"Previous_Period": "",
"Current_Period": "",
"Next_Day": "",
"Previous_Day": "",
"Inherit": "",
"InheritFields": "",
"FoodInherit": "",
"ShowUncategorizedFood": "",
"GroupBy": "",
"Language": "",
"Theme": "",
"SupermarketCategoriesOnly": "",
"MoveCategory": "",
"CountMore": "",
"IgnoreThis": "",
"DelayFor": "",
"Warning": "",
"NoCategory": "",
"InheritWarning": "",
"ShowDelayed": "",
"Completed": "",
"OfflineAlert": "",
"shopping_share": "",
"shopping_auto_sync": "",
"one_url_per_line": "",
"mealplan_autoadd_shopping": "",
"mealplan_autoexclude_onhand": "",
"mealplan_autoinclude_related": "",
"default_delay": "",
"plan_share_desc": "",
"shopping_share_desc": "",
"shopping_auto_sync_desc": "",
"mealplan_autoadd_shopping_desc": "",
"mealplan_autoexclude_onhand_desc": "",
"mealplan_autoinclude_related_desc": "",
"default_delay_desc": "",
"filter_to_supermarket": "",
"Coming_Soon": "",
"Auto_Planner": "",
"New_Cookbook": "",
"Hide_Keyword": "",
"Hour": "",
"Hours": "",
"Day": "",
"Days": "",
"Second": "",
"Seconds": "",
"Clear": "",
"Users": "",
"Invites": "",
"err_move_self": "",
"nothing": "",
"err_merge_self": "",
"show_sql": "",
"filter_to_supermarket_desc": "",
"CategoryName": "",
"SupermarketName": "",
"CategoryInstruction": "",
"shopping_recent_days_desc": "",
"shopping_recent_days": "",
"download_pdf": "",
"download_csv": "",
"csv_delim_help": "",
"csv_delim_label": "",
"SuccessClipboard": "",
"copy_to_clipboard": "",
"csv_prefix_help": "",
"csv_prefix_label": "",
"copy_markdown_table": "",
"in_shopping": "",
"DelayUntil": "",
"Pin": "",
"Unpin": "",
"PinnedConfirmation": "",
"UnpinnedConfirmation": "",
"mark_complete": "",
"QuickEntry": "",
"shopping_add_onhand_desc": "",
"shopping_add_onhand": "",
"related_recipes": "",
"today_recipes": "",
"sql_debug": "",
"remember_search": "",
"remember_hours": "",
"tree_select": "",
"OnHand_help": "",
"ignore_shopping_help": "",
"shopping_category_help": "",
"Icon": "Ikona",
"Unit": "Jednotka",
"Decimals": "Desetinná místa",
"Default_Unit": "Výchozí jednotka",
"No_Results": "Žádné výsledky",
"New_Unit": "Nová jednotka",
"Create_New_Shopping Category": "Vytvořit novou nákupní kategorii",
"Create_New_Food": "Přidat novou potravinu",
"Create_New_Keyword": "Přidat nové klíčové slovo",
"Create_New_Unit": "Přidat novou jednotku",
"Create_New_Meal_Type": "Přidat nový druh jídla",
"Create_New_Shopping_Category": "Přidat novou nákupní kategorii",
"and_up": "a nahoru",
"and_down": "a dolů",
"Instructions": "Instrukce",
"Unrated": "Nehodnocené",
"Automate": "Automatizovat",
"Empty": "Prázdné",
"Key_Ctrl": "Ctrl",
"Key_Shift": "Shift",
"Time": "Čas",
"Text": "Text",
"Shopping_list": "Nákupní seznam",
"Added_by": "Přidáno uživatelem",
"Added_on": "Přidáno v",
"AddToShopping": "Přidat do nákupního seznamu",
"IngredientInShopping": "Tato ingredience je na vašem nákupním seznamu.",
"NotInShopping": "{food} není na vašem nákupním seznamu.",
"OnHand": "Momentálně k dispozici",
"FoodOnHand": "{food} máte k dispozici.",
"FoodNotOnHand": "Nemáte {food} k dispozici.",
"Undefined": "Neurčeno",
"Create_Meal_Plan_Entry": "Vytvořit položku v jídelníčku",
"Edit_Meal_Plan_Entry": "Upravit položku v jídelníčku",
"Title": "Název",
"Week": "Týden",
"Month": "Měsíc",
"Year": "Rok",
"Planner": "Plánovač",
"Planner_Settings": "Nastavení plánovače",
"Period": "Období",
"Plan_Period_To_Show": "Zobrazit týdny, měsíce nebo roky",
"Periods": "Období",
"Plan_Show_How_Many_Periods": "Kolik období bude zobrazeno",
"Starting_Day": "První den v týdnu",
"Meal_Types": "Druhy jídel",
"Meal_Type": "Druh jídla",
"New_Entry": "Nová položka",
"Clone": "Klonovat",
"Drag_Here_To_Delete": "Přesunutím sem smazat",
"Meal_Type_Required": "Druh jídla je povinný",
"Title_or_Recipe_Required": "Je požadován název nebo výběr receptu",
"Color": "Barva",
"New_Meal_Type": "Nový druh jídla",
"Use_Fractions": "Použít zlomky",
"Use_Fractions_Help": "Automaticky převézt desetinná čísla na zlomky při prohlížení repetu.",
"AddFoodToShopping": "Přidat {food} na váš nákupní seznam",
"RemoveFoodFromShopping": "Odstranit {food} z nákupního seznamu",
"DeleteShoppingConfirm": "Jste si jistí, že chcete odstranit všechno {food} z nákupního seznamu?",
"IgnoredFood": "{food} bude ignorovat nákup.",
"Add_Servings_to_Shopping": "Přidat {servings} porce na nákupní seznam",
"Week_Numbers": "Číslo týdne",
"Show_Week_Numbers": "Zobrazit čísla týdnů?",
"Export_As_ICal": "Exportovat současný úsek do formátu iCal",
"Export_To_ICal": "Export ovat .ics",
"Cannot_Add_Notes_To_Shopping": "Poznámky nemohou být přidány na nákupní seznam",
"Added_To_Shopping_List": "Přidáno na nákupní seznam",
"Shopping_List_Empty": "Váš nákupní seznam je momentálně prázdný, můžete přidat položky pomocí kontextového menu záznamu v jídelníčku (pravým kliknutím na kartu nebo levým kliknutím na ikonu menu)",
"Next_Period": "Další období",
"Previous_Period": "Předchozí období",
"Current_Period": "Současné období",
"Next_Day": "Následující den",
"Previous_Day": "Předchozí den",
"Inherit": "Propsat",
"InheritFields": "Propsat hodnoty polí",
"FoodInherit": "Propisovatelná pole potraviny",
"ShowUncategorizedFood": "Zobrazit nedefinované",
"GroupBy": "Seskupit podle",
"Language": "Jazyk",
"Theme": "Téma",
"SupermarketCategoriesOnly": "Pouze kategorie obchodu",
"MoveCategory": "Přesunout do: ",
"CountMore": "...+{count} víc",
"IgnoreThis": "Nikdy automaticky nepřídávat {food} na nákupní seznam",
"DelayFor": "Odložit na {hours} hodin",
"Warning": "Varování",
"NoCategory": "Není vybrána žádná kategorie.",
"InheritWarning": "{food} se propisuje, změny nemusí setrvat.",
"ShowDelayed": "Zobrazit odložené položky",
"Completed": "Dokončeno",
"OfflineAlert": "Jste offline, nákupní seznam nemusí být synchronizován.",
"shopping_share": "Sdílet nákupní seznam",
"shopping_auto_sync": "Automatická synchronizace",
"one_url_per_line": "Jeden URL odkaz na řádek",
"mealplan_autoadd_shopping": "Automaticky přidat jídelníček",
"mealplan_autoexclude_onhand": "Nezahrnovat potraviny k dispozici",
"mealplan_autoinclude_related": "Přidat podobné recepty",
"default_delay": "Výchozí doba odložení v hodinách",
"plan_share_desc": "Nové položky v jídelníčku budou automaticky sdíleny s vybranými uživateli.",
"shopping_share_desc": "Uživatelé uvidí všechny položky na vašem nákupním seznamu. Abyste viděli položky na jejich seznamu, musí si přidat vás.",
"shopping_auto_sync_desc": "Nastavením 0 dojde k vypnutí automatické synchronizace. Při prohlížení nákupního seznamu je vždy po uplynutí nastaveného počtu vteřin aktualizován o změny, které mohli provést jiní uživatelé. To je užitečné, pokud nakupujete ve více lidech, ale může používat více dat.",
"mealplan_autoadd_shopping_desc": "Automaticky podle jídelníčku přidat ingredience na nákupní seznam.",
"mealplan_autoexclude_onhand_desc": "Nepřidávat ingredience, které jsou k dispozici, na nákupní seznam, když je vytvořen podle jídelníčku (manuálně nebo automaticky).",
"mealplan_autoinclude_related_desc": "Když je nákupní seznam vytvořen podle jídelníčku, přidat i položky z přidružených receptů.",
"default_delay_desc": "Výchozí odložení položek v nákupním seznamu v hodinách.",
"filter_to_supermarket": "Filtrovat podle obchodu",
"Coming_Soon": "Již brzy",
"Auto_Planner": "Automatický plánovač",
"New_Cookbook": "Nová kuchařka",
"Hide_Keyword": "Skrýt klíčová slova",
"Hour": "Hodina",
"Hours": "Hodiny",
"Day": "Den",
"Days": "Dny",
"Second": "Vteřina",
"Seconds": "Vteřiny",
"Clear": "Vyčistit",
"Users": "Uživatelé",
"Invites": "Pozvánky",
"err_move_self": "Není možné přesunout jednu položku do sebe samé",
"nothing": "Není co dělat",
"err_merge_self": "Není možné sloučit položku samu se sebou",
"show_sql": "Zobrazit SQL",
"filter_to_supermarket_desc": "Standartně zobrazovat položky v nákupním seznamu pouze pro vybraný obchod.",
"CategoryName": "Název kategorie",
"SupermarketName": "Název obchodu",
"CategoryInstruction": "Přetáhnutím kategorií změníte pořadí, ve kterém se zobrazují v nákupním seznamu.",
"shopping_recent_days_desc": "Počet dní k zobrazení posledních přidaných položek na nákupním seznamu.",
"shopping_recent_days": "Nedávné dny",
"download_pdf": "Stáhnout PDF",
"download_csv": "Stáhnout CSV",
"csv_delim_help": "Který znak bude použit pro oddělení záznamů v CSV.",
"csv_delim_label": "Oddělovač záznamů v CSV",
"SuccessClipboard": "Nákupní seznam byl zkopírován do schránky",
"copy_to_clipboard": "Zkopírovat do schránky",
"csv_prefix_help": "Prefix přidaný ke zkopírovanému seznamu do schránky.",
"csv_prefix_label": "Prefix seznamu",
"copy_markdown_table": "Kopírovat jako Markdown tabulku",
"in_shopping": "V nákupním seznamu",
"DelayUntil": "Odložit do",
"Pin": "Připnout",
"Unpin": "Odepnout",
"PinnedConfirmation": "{recipe} byl připnut.",
"UnpinnedConfirmation": "{recipe} byl odepnut.",
"mark_complete": "Označit jako hotové",
"QuickEntry": "Rychlý záznam",
"shopping_add_onhand_desc": "Označit potravinu jako \"K dispozici\" když je odškrtnuta na nákupním seznamu.",
"shopping_add_onhand": "Automaticky K dispozici",
"related_recipes": "Související recepty",
"today_recipes": "Dnešní recepty",
"sql_debug": "SQL Debug",
"remember_search": "Pamatovat vyhledávání",
"remember_hours": "Kolik hodin pamatovat",
"tree_select": "Použít stromový výběr",
"OnHand_help": "Potravina je v inventáři a nebude automaticky přidána na nákupní seznam. Status \"k dipozici\" je sdílen s nakupujícími uživateli.",
"ignore_shopping_help": "Nikdy nepřidávat potravinu na nákupní seznam (např. voda)",
"shopping_category_help": "Obchody mohou být seřazeny a třízeny pomocí nákupních kategorií podle rozvržení uliček a regálů.",
"food_recipe_help": "",
"Foods": "",
"Account": "",
"Cosmetic": "",
"Foods": "Potraviny",
"Account": "Účet",
"Cosmetic": "Zobrazení",
"API": "API",
"enable_expert": "",
"expert_mode": "",
"simple_mode": "",
"advanced": "",
"fields": "",
"show_keywords": "",
"show_foods": "",
"show_books": "",
"show_rating": "",
"show_units": "",
"show_filters": "",
"not": "",
"save_filter": "",
"filter_name": "",
"left_handed": "",
"left_handed_help": "",
"Custom Filter": "",
"shared_with": "",
"sort_by": "",
"enable_expert": "Povolit Expertní režim",
"expert_mode": "Expertní režim",
"simple_mode": "Jednoduchý režim",
"advanced": "Pokročilé",
"fields": "Pole",
"show_keywords": "Zobrazit klíčová slova",
"show_foods": "Zobrazit potraviny",
"show_books": "Zobrazit kuchařky",
"show_rating": "Zobrazit hodnocení",
"show_units": "Zobrazit jednotky",
"show_filters": "Zobrazit filtry",
"not": "ne",
"save_filter": "Uložit filtr",
"filter_name": "Název filtru",
"left_handed": "Režim pro leváky",
"left_handed_help": "Optimalizuje uživatelské prostředí pro levou ruku.",
"Custom Filter": "Uživatelský filtr",
"shared_with": "Sdíleno s",
"sort_by": "Seřadit podle",
"asc": "Vzestupně",
"desc": "Sestupně",
"date_viewed": "",
"last_cooked": "",
"times_cooked": "",
"date_created": "",
"show_sortby": "",
"date_viewed": "Poslední prohlížené",
"last_cooked": "Naposledy vařeno",
"times_cooked": "Kolkrát vařeno",
"date_created": "Datum vytvoření",
"show_sortby": "Zobrazit Seřazeno podle",
"search_rank": "",
"make_now": "",
"recipe_filter": "Filtrovat recepty",
"book_filter_help": "",
"review_shopping": "",
"book_filter_help": "Zahrnout i recepty z filtru stejně jako manuálně přidané.",
"review_shopping": "Zkontrolovat nákupní položky před uložením",
"view_recipe": "Zobrazit recept",
"copy_to_new": "",
"copy_to_new": "Zkopírovat do nového receptu",
"recipe_name": "Název receptu",
"paste_ingredients_placeholder": "",
"paste_ingredients": "",
"ingredient_list": "",
"explain": "",
"paste_ingredients_placeholder": "Zde vložit seznam ingrediencí.",
"paste_ingredients": "Vložit ingredince",
"ingredient_list": "Seznam ingrediencí",
"explain": "Vysvětlit",
"filter": "Filtr",
"Website": "Web",
"App": "Aplikace",
"Message": "",
"Bookmarklet": "",
"Sticky_Nav": "",
"Sticky_Nav_Help": "",
"Nav_Color": "",
"Nav_Color_Help": "",
"Message": "Zpráva",
"Bookmarklet": "Skript v záložce",
"Sticky_Nav": "Připnout navigační panel",
"Sticky_Nav_Help": "Vždy zobrazit navigační panel na vrchu stránky.",
"Nav_Color": "Barva navigačního panelu",
"Nav_Color_Help": "Zmenit barvu navigačního panelu.",
"Use_Kj": "Používat kJ místo kcal",
"Comments_setting": "Zobrazit komentáře",
"click_image_import": "Vyberte obrázek, který chcete přiřadit k tomuto receptu",
"no_more_images_found": "Žádné další obrázky na zadaném odkazu.",
"import_duplicates": "",
"paste_json": "",
"Click_To_Edit": "",
"search_no_recipes": "",
"search_import_help_text": "",
"search_create_help_text": "",
"warning_duplicate_filter": "",
"reset_children": "",
"import_duplicates": "Aby bylo zamezeno duplicitním receptům, recepty se stejným jménem jako již existující jsou ignorovány. Pokud chcete přidat všechno, zaškrtněte toto políčko.",
"paste_json": "Sem zkopírujte zdroj ve formátu json nebo html.",
"Click_To_Edit": "Kliknutím editovat",
"search_no_recipes": "Nebyly nealezeny žádné recepty!",
"search_import_help_text": "Importovat recept z externí webové stránky nebo aplikace.",
"search_create_help_text": "Vytvořit nový recept přímo v Tandoor.",
"warning_duplicate_filter": "Varování: Kvůli technickým omezení může použití několika filtrů se stejnou kombinací (a/nebo/ne) přinést neočekávaný výsledek.",
"reset_children": "Resetovat propsání podřízených",
"reset_children_help": "",
"reset_food_inheritance": "",
"reset_food_inheritance": "Resetovat propisování",
"reset_food_inheritance_info": "",
"substitute_help": "",
"substitute_siblings_help": "",
"substitute_children_help": "",
"substitute_siblings": "",
"substitute_children": "",
"SubstituteOnHand": "",
"ChildInheritFields": "",
"ChildInheritFields_help": "",
"InheritFields_help": "",
"show_ingredient_overview": "",
"Ingredient Overview": "",
"substitute_help": "Při hledání podle ingrediencí, které jsou k dispozici, jsou zvažovány náhrady.",
"substitute_siblings_help": "Všechny potraviny, které sdílejí nadřazenou položku jsou považovány za náhrady.",
"substitute_children_help": "Všechny potraviny, které jsou podřízeny této, jsou považovány za náhražky.",
"substitute_siblings": "Související náhrady",
"substitute_children": "Podřízené náhrady",
"SubstituteOnHand": "Máte k dispozici náhradu.",
"ChildInheritFields": "Propisovaná pole podřízených",
"ChildInheritFields_help": "Podřízeným se budou standardně propisovat tato pole.",
"InheritFields_help": "Hodnoty těchto polí budou propsány z nadřazených (Výjimka: prázdné nákupní kategorie nejsou propsány)",
"show_ingredient_overview": "Zobrazit seznam všech ingrediencí na začátku receptu.",
"Ingredient Overview": "Přehled ingrediencí",
"last_viewed": "Naposledy zobrazeno",
"created_on": "Vytvořeno",
"updatedon": "Upraveno",
"Imported_From": "",
"advanced_search_settings": "",
"nothing_planned_today": "",
"no_pinned_recipes": "",
"Planned": "",
"Pinned": "",
"Imported": "",
"Quick actions": "",
"Imported_From": "Importováno z",
"advanced_search_settings": "Rozšířené vyhledávání",
"nothing_planned_today": "Dnes nemáte nic naplánováno!",
"no_pinned_recipes": "Nemáte žádné připnuté recepty!",
"Planned": "Naplánované",
"Pinned": "Připnuté",
"Imported": "Importované",
"Quick actions": "Rychlé akce",
"Ratings": "Hodnocení",
"Internal": "",
"Internal": "Interní",
"Units": "Jednotky",
"Manage_Emails": "",
"Manage_Emails": "Spravovat emaily",
"Change_Password": "Změna hesla",
"Social_Authentication": "",
"Social_Authentication": "Přihlašování pomocí účtů sociálních sítí",
"Random Recipes": "Náhodné recepty",
"parameter_count": "",
"select_keyword": "",
"add_keyword": "",
"select_file": "",
"select_recipe": "",
"select_unit": "",
"select_food": "",
"remove_selection": "",
"empty_list": "",
"Select": "",
"Supermarkets": "",
"parameter_count": "Parametr {count}",
"select_keyword": "Vybrat klíčové slovo",
"add_keyword": "Přidat klíčové slovo",
"select_file": "Vybrat soubor",
"select_recipe": "Vybrat recept",
"select_unit": "Vybrat jednotku",
"select_food": "Vybrat potravinu",
"remove_selection": "Odznačit",
"empty_list": "Seznam je prázdný.",
"Select": "Vybrat",
"Supermarkets": "Obchody",
"User": "Uživatel",
"Username": "Uživatelské jméno",
"First_name": "Jméno",
"Last_name": "Příjmení",
"Keyword": "",
"Advanced": "",
"Page": "",
"Single": "",
"Multiple": "",
"Reset": "",
"Disabled": "",
"Disable": "",
"Options": "",
"Create Food": "",
"create_food_desc": "",
"additional_options": "",
"Keyword": "Klíčové slovo",
"Advanced": "Rozšířené",
"Page": "Stránka",
"Single": "Jednoduchý",
"Multiple": "Vícenásobný",
"Reset": "Resetovat",
"Disabled": "Deaktivované",
"Disable": "Deaktivovat",
"Options": "Možnosti",
"Create Food": "Vytvořit potravinu",
"create_food_desc": "Vytvořit potravinu a propojit ji s tímto receptem.",
"additional_options": "Rozšířené možnosti",
"Importer_Help": "Nápověda k importu z této aplikace:",
"Documentation": "Dokumentace",
"Select_App_To_Import": "Vyberte aplikaci, ze které chcete importovat",
@@ -461,22 +461,39 @@
"Export_Not_Yet_Supported": "Export není zatím podporován",
"Import_Result_Info": "{imported} z {total} receptů naimportováno",
"Recipes_In_Import": "Receptů v importním souboru",
"Toggle": "",
"Import_Error": "",
"Warning_Delete_Supermarket_Category": "",
"New_Supermarket": "",
"New_Supermarket_Category": "",
"Are_You_Sure": "",
"Valid Until": "",
"Split_All_Steps": "",
"Combine_All_Steps": "",
"Plural": "",
"plural_short": "",
"Use_Plural_Unit_Always": "",
"Use_Plural_Unit_Simple": "",
"Use_Plural_Food_Always": "",
"Use_Plural_Food_Simple": "",
"plural_usage_info": "",
"Toggle": "Přepnout",
"Import_Error": "Během importu došlo k chybě. Pro více informací rozbalte Detaily na konci stránky.",
"Warning_Delete_Supermarket_Category": "Vymazáním kategorie obchodu dojde k odstranění všech vazeb na potraviny. Jste si jistí?",
"New_Supermarket": "Vytvořit nový obchod",
"New_Supermarket_Category": "Vytvořit novou kategorii obchodu",
"Are_You_Sure": "Jste si jistí?",
"Valid Until": "Platné do",
"Split_All_Steps": "Rozdělit každý řádek do samostatného kroku.",
"Combine_All_Steps": "Zkombinovat všechny kroky do jednoho kroku.",
"Plural": "Množné číslo",
"plural_short": "množné číslo",
"Use_Plural_Unit_Always": "Vždy použít množné číslo pro jednotku",
"Use_Plural_Unit_Simple": "Dynamicky použít množné číslo pro jednotku",
"Use_Plural_Food_Always": "Použít u potraviny vždy množné číslo",
"Use_Plural_Food_Simple": "Použít u potraviny množné číslo dynamicky",
"plural_usage_info": "Použít množné číslo pro jednotky a potraviny v tomto prostoru.",
"Create Recipe": "Vytvořit recept",
"Import Recipe": "Importovat recept"
"Import Recipe": "Importovat recept",
"per_serving": "na porci",
"open_data_help_text": "Projekt Tandoor Open Data nabízí komunitou poskytnutá data pro Tandoor. Toto pole je automaticky vyplněno při importu a může být později upraveno.",
"Data_Import_Info": "Rozšiřte svůj prostor o seznamy potravin, jednotek a další spravované komunitou, a vylepšete tak svoji sbírku receptů.",
"Update_Existing_Data": "Aktualizovat existující data",
"Use_Metric": "Používat metrické jednotky",
"Learn_More": "Zjistit víc",
"converted_unit": "Převedená jendotka",
"converted_amount": "Převedené množství",
"base_unit": "Základní jednotka",
"base_amount": "Základní množství",
"Datatype": "Datový typ",
"Number of Objects": "Počet Objektů",
"Property": "Vlastnost",
"Conversion": "Převod",
"Properties": "Vlastnosti",
"recipe_property_info": "Můžete také přidávat vlastnosti k Vašim potravinám. Hodnoty budou automaticky přepočteny na základě Vašeho receptu!",
"total": "celkem"
}

View File

@@ -140,6 +140,7 @@
"advanced_search_settings": "Erweiterte Sucheinstellungen",
"View": "Ansicht",
"Recipes": "Rezepte",
"Welcome": "Willkommen",
"Move": "Verschieben",
"Merge": "Zusammenführen",
"Parent": "Eltern",
@@ -356,12 +357,12 @@
"search_rank": "Such-Rang",
"paste_ingredients": "Zutaten einfügen",
"Ingredient Editor": "Zutateneditor",
"Protected": "Schützen",
"Protected": "Geschützt",
"not": "nicht",
"warning_duplicate_filter": "Warnung: Wegen technischen Limitierungen können mehrere Filter der selben Kombination (und/oder/nicht) zu unerwarteten Ergebnissen führen.",
"and_down": "& Runter",
"enable_expert": "Expertenmodus aktivieren",
"filter_name": "Name des Filters",
"filter_name": "Filtername",
"shared_with": "geteilt mit",
"asc": "Aufsteigend",
"desc": "Absteigend",
@@ -460,7 +461,7 @@
"Comments_setting": "Kommentare anzeigen",
"reset_food_inheritance": "Vererbung zurücksetzen",
"food_inherit_info": "Datenfelder des Lebensmittels, die standardmäßig vererbt werden sollen.",
"Are_You_Sure": "Sind sie sicher?",
"Are_You_Sure": "Sind Sie sicher?",
"Plural": "Plural",
"plural_short": "Plural",
"Use_Plural_Unit_Always": "Pluralform der Maßeinheit immer verwenden",
@@ -479,7 +480,9 @@
"reset_children_help": "Überschreibe alle Kinder mit den Werten der vererbten Felder. Die vererbten Felder der Kinder werden als vererbte Felder gesetzt, es sei denn, das Kind-Vererben-Feld ist gesetzt.",
"Unpin": "Lösen",
"Amount": "Menge",
"Back": "Zurück",
"Original_Text": "Originaler Text",
"Choose_Category": "Kategorie Auswählen",
"Import Recipe": "Rezept importieren",
"Create Recipe": "Rezept erstellen",
"recipe_property_info": "Sie können auch Eigenschaften zu Lebensmitteln hinzufügen, um sie automatisch auf der Grundlage Ihres Rezepts zu berechnen!",
@@ -499,5 +502,10 @@
"Property": "Eigenschaft",
"Conversion": "Umrechnung",
"Properties": "Eigenschaften",
"total": "gesamt"
"total": "gesamt",
"Open_Data_Slug": "Open Data Slug",
"g": "Gramm [g] (metrisch, Gewicht)",
"kg": "Kilogramm [kg] (metrisch, Gewicht)",
"ounce": "Unze [oz] (Gewicht)",
"pound": "Pfund (Gewicht)"
}

501
vue/src/locales/el.json Normal file
View File

@@ -0,0 +1,501 @@
{
"warning_feature_beta": "Αυτή η λειτουργία βρίσκεται αυτήν τη στιγμή σε κατάσταση BETA (δοκιμαστική). Παρακαλούμε να αναμένετε σφάλματα και πιθανές αλλαγές που μπορεί να προκαλέσουν απώλεια δεδομένων που σχετίζονται με τις διάφορες λειτουργίες στο μέλλον.",
"err_fetching_resource": "",
"err_creating_resource": "",
"err_updating_resource": "",
"err_deleting_resource": "",
"err_deleting_protected_resource": "",
"err_moving_resource": "",
"err_merging_resource": "",
"success_fetching_resource": "",
"success_creating_resource": "",
"success_updating_resource": "",
"success_deleting_resource": "",
"success_moving_resource": "",
"success_merging_resource": "",
"file_upload_disabled": "",
"recipe_property_info": "",
"warning_space_delete": "",
"food_inherit_info": "",
"facet_count_info": "",
"step_time_minutes": "",
"confirm_delete": "",
"import_running": "",
"all_fields_optional": "",
"convert_internal": "",
"show_only_internal": "",
"show_split_screen": "",
"Log_Recipe_Cooking": "",
"External_Recipe_Image": "",
"Add_to_Shopping": "",
"Add_to_Plan": "",
"Step_start_time": "",
"Sort_by_new": "",
"Table_of_Contents": "",
"Recipes_per_page": "",
"Show_as_header": "",
"Hide_as_header": "",
"Add_nutrition_recipe": "",
"Remove_nutrition_recipe": "",
"Copy_template_reference": "",
"per_serving": "",
"Save_and_View": "",
"Manage_Books": "",
"Meal_Plan": "",
"Select_Book": "",
"Select_File": "",
"Recipe_Image": "",
"Import_finished": "",
"View_Recipes": "",
"Log_Cooking": "",
"New_Recipe": "",
"Url_Import": "",
"Reset_Search": "",
"Recently_Viewed": "",
"Load_More": "",
"New_Keyword": "",
"Delete_Keyword": "",
"Edit_Keyword": "",
"Edit_Recipe": "",
"Move_Keyword": "",
"Merge_Keyword": "",
"Hide_Keywords": "",
"Hide_Recipes": "",
"Move_Up": "",
"Move_Down": "",
"Step_Name": "",
"Step_Type": "",
"Make_Header": "",
"Make_Ingredient": "",
"Amount": "",
"Enable_Amount": "",
"Disable_Amount": "",
"Ingredient Editor": "",
"Description_Replace": "",
"Instruction_Replace": "",
"Auto_Sort": "",
"Auto_Sort_Help": "",
"Private_Recipe": "",
"Private_Recipe_Help": "",
"reusable_help_text": "",
"open_data_help_text": "",
"Open_Data_Slug": "",
"Open_Data_Import": "",
"Data_Import_Info": "",
"Update_Existing_Data": "",
"Use_Metric": "",
"Learn_More": "",
"converted_unit": "",
"converted_amount": "",
"base_unit": "",
"base_amount": "",
"Datatype": "",
"Number of Objects": "",
"Add_Step": "",
"Keywords": "Λέξεις κλειδιά",
"Books": "Βιβλία",
"Proteins": "",
"Fats": "",
"Carbohydrates": "",
"Calories": "",
"Energy": "",
"Nutrition": "",
"Date": "",
"Share": "",
"Automation": "",
"Parameter": "",
"Export": "",
"Copy": "",
"Rating": "",
"Close": "",
"Cancel": "",
"Link": "",
"Add": "",
"New": "",
"Note": "",
"Success": "",
"Failure": "",
"Protected": "",
"Ingredients": "",
"Supermarket": "",
"Categories": "",
"Category": "",
"Selected": "",
"min": "",
"Servings": "Μερίδες",
"Waiting": "",
"Preparation": "",
"External": "",
"Size": "",
"Files": "",
"File": "",
"Edit": "",
"Image": "",
"Delete": "",
"Open": "",
"Ok": "",
"Save": "",
"Step": "",
"Search": "",
"Import": "",
"Print": "",
"Settings": "Ρυθμίσεις",
"or": "",
"and": "",
"Information": "",
"Download": "",
"Create": "",
"Search Settings": "",
"View": "",
"Recipes": "",
"Move": "",
"Merge": "",
"Parent": "",
"Copy Link": "",
"Copy Token": "",
"delete_confirmation": "",
"move_confirmation": "",
"merge_confirmation": "",
"create_rule": "",
"move_selection": "",
"merge_selection": "",
"Root": "",
"Ignore_Shopping": "",
"Shopping_Category": "",
"Shopping_Categories": "",
"Edit_Food": "",
"Move_Food": "",
"New_Food": "",
"Hide_Food": "",
"Food_Alias": "",
"Unit_Alias": "",
"Keyword_Alias": "",
"Delete_Food": "",
"No_ID": "",
"Meal_Plan_Days": "",
"merge_title": "",
"move_title": "",
"Food": "Φαγητό",
"Property": "",
"Conversion": "",
"Original_Text": "",
"Recipe_Book": "",
"del_confirmation_tree": "",
"delete_title": "",
"create_title": "",
"edit_title": "",
"Name": "",
"Properties": "",
"Type": "",
"Description": "",
"Recipe": "",
"tree_root": "",
"Icon": "",
"Unit": "",
"Decimals": "",
"Default_Unit": "",
"No_Results": "",
"New_Unit": "",
"Create_New_Shopping Category": "",
"Create_New_Food": "",
"Create_New_Keyword": "",
"Create_New_Unit": "",
"Create_New_Meal_Type": "",
"Create_New_Shopping_Category": "",
"and_up": "",
"and_down": "",
"Instructions": "",
"Unrated": "",
"Automate": "",
"Empty": "",
"Key_Ctrl": "",
"Key_Shift": "",
"Time": "",
"Text": "",
"Shopping_list": "",
"Added_by": "",
"Added_on": "",
"AddToShopping": "",
"IngredientInShopping": "",
"NotInShopping": "",
"OnHand": "",
"FoodOnHand": "",
"FoodNotOnHand": "",
"Undefined": "",
"Create_Meal_Plan_Entry": "",
"Edit_Meal_Plan_Entry": "",
"Title": "",
"Week": "",
"Month": "",
"Year": "",
"Planner": "",
"Planner_Settings": "",
"Period": "",
"Plan_Period_To_Show": "",
"Periods": "",
"Plan_Show_How_Many_Periods": "",
"Starting_Day": "",
"Meal_Types": "",
"Meal_Type": "",
"New_Entry": "",
"Clone": "",
"Drag_Here_To_Delete": "",
"Meal_Type_Required": "",
"Title_or_Recipe_Required": "",
"Color": "",
"New_Meal_Type": "",
"Use_Fractions": "",
"Use_Fractions_Help": "",
"AddFoodToShopping": "",
"RemoveFoodFromShopping": "",
"DeleteShoppingConfirm": "",
"IgnoredFood": "",
"Add_Servings_to_Shopping": "",
"Week_Numbers": "",
"Show_Week_Numbers": "",
"Export_As_ICal": "",
"Export_To_ICal": "",
"Cannot_Add_Notes_To_Shopping": "",
"Added_To_Shopping_List": "",
"Shopping_List_Empty": "",
"Next_Period": "",
"Previous_Period": "",
"Current_Period": "",
"Next_Day": "",
"Previous_Day": "",
"Inherit": "",
"InheritFields": "",
"FoodInherit": "",
"ShowUncategorizedFood": "",
"GroupBy": "",
"Language": "",
"Theme": "",
"SupermarketCategoriesOnly": "",
"MoveCategory": "",
"CountMore": "",
"IgnoreThis": "",
"DelayFor": "",
"Warning": "",
"NoCategory": "",
"InheritWarning": "",
"ShowDelayed": "",
"Completed": "",
"OfflineAlert": "",
"shopping_share": "",
"shopping_auto_sync": "",
"one_url_per_line": "",
"mealplan_autoadd_shopping": "",
"mealplan_autoexclude_onhand": "",
"mealplan_autoinclude_related": "",
"default_delay": "",
"plan_share_desc": "",
"shopping_share_desc": "",
"shopping_auto_sync_desc": "",
"mealplan_autoadd_shopping_desc": "",
"mealplan_autoexclude_onhand_desc": "",
"mealplan_autoinclude_related_desc": "",
"default_delay_desc": "",
"filter_to_supermarket": "",
"Coming_Soon": "",
"Auto_Planner": "",
"New_Cookbook": "",
"Hide_Keyword": "",
"Hour": "",
"Hours": "",
"Day": "",
"Days": "",
"Second": "",
"Seconds": "",
"Clear": "",
"Users": "",
"Invites": "",
"err_move_self": "",
"nothing": "",
"err_merge_self": "",
"show_sql": "",
"filter_to_supermarket_desc": "",
"CategoryName": "",
"SupermarketName": "",
"CategoryInstruction": "",
"shopping_recent_days_desc": "",
"shopping_recent_days": "",
"download_pdf": "",
"download_csv": "",
"csv_delim_help": "",
"csv_delim_label": "",
"SuccessClipboard": "",
"copy_to_clipboard": "",
"csv_prefix_help": "",
"csv_prefix_label": "",
"copy_markdown_table": "",
"in_shopping": "",
"DelayUntil": "",
"Pin": "",
"Unpin": "",
"PinnedConfirmation": "",
"UnpinnedConfirmation": "",
"mark_complete": "",
"QuickEntry": "",
"shopping_add_onhand_desc": "",
"shopping_add_onhand": "",
"related_recipes": "",
"today_recipes": "",
"sql_debug": "",
"remember_search": "",
"remember_hours": "",
"tree_select": "",
"OnHand_help": "",
"ignore_shopping_help": "",
"shopping_category_help": "",
"food_recipe_help": "",
"Foods": "",
"Account": "",
"Cosmetic": "",
"API": "",
"enable_expert": "",
"expert_mode": "",
"simple_mode": "",
"advanced": "",
"fields": "",
"show_keywords": "",
"show_foods": "",
"show_books": "",
"show_rating": "",
"show_units": "",
"show_filters": "",
"not": "",
"save_filter": "",
"filter_name": "",
"left_handed": "",
"left_handed_help": "",
"Custom Filter": "",
"shared_with": "",
"sort_by": "",
"asc": "",
"desc": "",
"date_viewed": "",
"last_cooked": "",
"times_cooked": "",
"date_created": "",
"show_sortby": "",
"search_rank": "",
"make_now": "",
"recipe_filter": "",
"book_filter_help": "",
"review_shopping": "",
"view_recipe": "",
"copy_to_new": "",
"recipe_name": "",
"paste_ingredients_placeholder": "",
"paste_ingredients": "",
"ingredient_list": "",
"explain": "",
"filter": "",
"Website": "",
"App": "",
"Message": "",
"Bookmarklet": "",
"Sticky_Nav": "",
"Sticky_Nav_Help": "",
"Nav_Color": "",
"Nav_Color_Help": "",
"Use_Kj": "",
"Comments_setting": "",
"click_image_import": "",
"no_more_images_found": "",
"import_duplicates": "",
"paste_json": "",
"Click_To_Edit": "",
"search_no_recipes": "",
"search_import_help_text": "",
"search_create_help_text": "",
"warning_duplicate_filter": "",
"reset_children": "",
"reset_children_help": "",
"reset_food_inheritance": "",
"reset_food_inheritance_info": "",
"substitute_help": "",
"substitute_siblings_help": "",
"substitute_children_help": "",
"substitute_siblings": "",
"substitute_children": "",
"SubstituteOnHand": "",
"ChildInheritFields": "",
"ChildInheritFields_help": "",
"InheritFields_help": "",
"show_ingredient_overview": "",
"Ingredient Overview": "",
"last_viewed": "",
"created_on": "",
"updatedon": "",
"Imported_From": "",
"advanced_search_settings": "",
"nothing_planned_today": "",
"no_pinned_recipes": "",
"Planned": "",
"Pinned": "",
"Imported": "",
"Quick actions": "",
"Ratings": "",
"Internal": "",
"Units": "",
"Manage_Emails": "",
"Change_Password": "",
"Social_Authentication": "",
"Random Recipes": "",
"parameter_count": "",
"select_keyword": "",
"add_keyword": "",
"select_file": "",
"select_recipe": "",
"select_unit": "",
"select_food": "",
"remove_selection": "",
"empty_list": "",
"Select": "",
"Supermarkets": "",
"User": "",
"Username": "",
"First_name": "",
"Last_name": "",
"Keyword": "Λέξη κλειδί",
"Advanced": "",
"Page": "",
"Single": "",
"Multiple": "",
"Reset": "",
"Disabled": "",
"Disable": "",
"Options": "",
"Create Food": "",
"create_food_desc": "",
"additional_options": "",
"Importer_Help": "",
"Documentation": "",
"Select_App_To_Import": "",
"Import_Supported": "",
"Export_Supported": "",
"Import_Not_Yet_Supported": "",
"Export_Not_Yet_Supported": "",
"Import_Result_Info": "",
"Recipes_In_Import": "",
"Toggle": "",
"total": "",
"Import_Error": "",
"Warning_Delete_Supermarket_Category": "",
"New_Supermarket": "",
"New_Supermarket_Category": "",
"Are_You_Sure": "",
"Valid Until": "",
"Split_All_Steps": "",
"Combine_All_Steps": "",
"Plural": "",
"plural_short": "",
"Use_Plural_Unit_Always": "",
"Use_Plural_Unit_Simple": "",
"Use_Plural_Food_Always": "",
"Use_Plural_Food_Simple": "",
"plural_usage_info": "",
"Create Recipe": "",
"Import Recipe": ""
}

View File

@@ -148,6 +148,7 @@
"Search Settings": "Search Settings",
"View": "View",
"Recipes": "Recipes",
"Welcome": "Welcome",
"Move": "Move",
"Merge": "Merge",
"Parent": "Parent",
@@ -491,6 +492,27 @@
"Combine_All_Steps": "Combine all steps into a single field.",
"Plural": "Plural",
"plural_short": "plural",
"g": "gram [g] (metric, weight)",
"kg": "kilogram [kg] (metric, weight)",
"ounce": "ounce [oz] (weight)",
"pound": "pound (weight)",
"ml": "millilitre [ml] (metric, volume)",
"l": "litre [l] (metric, volume)",
"fluid_ounce": "fluid ounce [fl oz] (US, volume)",
"pint": "pint [pt] (US, volume)",
"quart": "quart [qt] (US, volume)",
"gallon": "gallon [gal] (US, volume)",
"tbsp": "tablespoon [tbsp] (US, volume)",
"tsp": "teaspoon [tsp] (US, volume)",
"imperial_fluid_ounce": "imperial fluid ounce [imp fl oz] (UK, volume)",
"imperial_pint": "imperial pint [imp pt] (UK, volume)",
"imperial_quart": "imperial quart [imp qt] (UK, volume)",
"imperial_gallon": "imperial gal [imp gal] (UK, volume)",
"imperial_tbsp": "imperial tablespoon [imp tbsp] (UK, volume)",
"imperial_tsp": "imperial teaspoon [imp tsp] (UK, volume)",
"Choose_Category": "Choose Category",
"Back": "Back",
"Use_Plural_Unit_Always": "Use plural form for unit always",
"Use_Plural_Unit_Simple": "Use plural form for unit dynamically",
"Use_Plural_Food_Always": "Use plural form for food always",

522
vue/src/locales/he.json Normal file
View File

@@ -0,0 +1,522 @@
{
"warning_feature_beta": "יכולת זו כרגע בבטא. צפה שגיאות ואף תקלות בהמשך בעת שימוש ביכולת זו.",
"err_fetching_resource": "שגיאה בעת טעינת משאב!",
"err_creating_resource": "שגיאה בעת יצירת משאב!",
"err_updating_resource": "שגיאה בעת עדכון משאב!",
"err_deleting_resource": "שגיאה בעת מחיקת משאב!",
"err_deleting_protected_resource": "האובייקט שאתה מנסה למחור עדיין בשימוש ואי אפשר למחוקו.",
"err_moving_resource": "שגיאה בהעברת משאב!",
"err_merging_resource": "שגיאה בעת איחוד משאב!",
"success_fetching_resource": "משאב נטען בהצלחה!",
"success_creating_resource": "משאב נוצר בהצלחה!",
"success_updating_resource": "משאב עודן בהצלחה!",
"success_deleting_resource": "משאב נמחק בהצלחה!",
"success_moving_resource": "משאב הועבר בהצלחה!",
"success_merging_resource": "משאב אוחד בהצלחה!",
"file_upload_disabled": "העלאת קבצים לא מאופשרת במרחב זה.",
"recipe_property_info": "ניתן גם להוסיף ערכים למאכלים בכדי לחשב אוטומטית בהתאם למתכון שלך!",
"warning_space_delete": "ניתן למחיק את המרחב כולל כל המתכונים, רשימות קניות, תוכניות אוכל וכל מה שנוצר. פעולה זו הינה בלתי הפיכה! האם אתה בטוח ?",
"food_inherit_info": "ערכים על אוכל שאמורים להיות תורשתיים כברירת מחדל.",
"facet_count_info": "הצג מספר מתכונים בסנני החיפוש.",
"step_time_minutes": "זמן הצעד בדקות",
"confirm_delete": "האם אתה בטוח רוצה למחק את {object}?",
"import_running": "ייבוא מתבצע, נא להמתין!",
"all_fields_optional": "כל השדות הינן שדות רשות וניתן להשאירם ריקים.",
"convert_internal": "המר למתכון פנימי",
"show_only_internal": "הצג רק מתכונים פנימיים",
"show_split_screen": "תצוגה מפוצלת",
"Log_Recipe_Cooking": "רשום בישול מתכון",
"External_Recipe_Image": "תמונת מתכון חיצונית",
"Add_to_Shopping": "הוסף לקניות",
"Add_to_Plan": "הוסף לתוכנית",
"Step_start_time": "זמן התחלת הצעד",
"Sort_by_new": "סדר ע\"י חדש",
"Table_of_Contents": "תוכן עניינים",
"Recipes_per_page": "מתכונים בכל דף",
"Show_as_header": "הצג בתור כותרת",
"Hide_as_header": "הסתר בתור כותרת",
"Add_nutrition_recipe": "הוסף ערכים תזונתיים למתכון",
"Remove_nutrition_recipe": "מחר ערכים תזונתיים מהמתכון",
"Copy_template_reference": "העתק הפניה לתבנית",
"per_serving": "לפי מנה",
"Save_and_View": "שמור וצפה",
"Manage_Books": "נהל ספרים",
"Meal_Plan": "תוכנית ארוחה",
"Select_Book": "בחר ספר",
"Select_File": "בחר קובץ",
"Recipe_Image": "תמונת מתכון",
"Import_finished": "ייבוא הסתיים",
"View_Recipes": "הצג מתכונים",
"Log_Cooking": "רשום הכנת מתכון",
"New_Recipe": "מתכון חדש",
"Url_Import": "ייבוא מכתובת",
"Reset_Search": "אפס חיפוש",
"Recently_Viewed": "נצפו לאחרונה",
"Load_More": "טען עוד",
"New_Keyword": "מילת מפתח חדשה",
"Delete_Keyword": "מחר מילת מפתח",
"Edit_Keyword": "עדכן מילת מפתח",
"Edit_Recipe": "עדכן מתכון",
"Move_Keyword": "העברת מילת מפתח",
"Merge_Keyword": "איחוד מילת מפתח",
"Hide_Keywords": "הסתרת מילת מפתח",
"Hide_Recipes": "הסתרת מתכונים",
"Move_Up": "העברה למעלה",
"Move_Down": "העברה למטה",
"Step_Name": "שם צעד",
"Step_Type": "סוג צעד",
"Make_Header": "הפוך לכותרת",
"Make_Ingredient": "הפוך למרכיב",
"Amount": "כמות",
"Enable_Amount": "אפשר כמות",
"Disable_Amount": "אל תאפשר כמות",
"Ingredient Editor": "עורך המרכיבים",
"Description_Replace": "החלפת תיאור",
"Instruction_Replace": "החלפת הוראות",
"Auto_Sort": "סידור אוטומטי",
"Auto_Sort_Help": "העברת כל המרכיבים למיקום המתאים ביותר.",
"Private_Recipe": "מתכון פרטי",
"Private_Recipe_Help": "המתכון מוצג רק לך ולאנשים ששותפו.",
"reusable_help_text": "האם הכתובת השיתוף תהיה שמישה ליותר ממשתמש אחד.",
"open_data_help_text": "הקהילה מאחורי פרוייקט Tandoor Open Data תורמת מידע לTandoor. ערך זה ממולא אוטומטית כאשר מייברים אותו ומאפשר עדכון בעתיד.",
"Open_Data_Slug": "מידע פתוח",
"Open_Data_Import": "פתח ייבוא מידע",
"Data_Import_Info": "שפר את המרחב שלך ע\"י ייבוא רשימת משאבים קהילתית כמו מאכלים, ערכים ועוד.",
"Update_Existing_Data": "עדכון מידע קיים",
"Use_Metric": "השתמש ביחידות מטריות",
"Learn_More": "למד עוד",
"converted_unit": "יחידה מומרת",
"converted_amount": "כמות מומרת",
"base_unit": "יחידת בסיס",
"base_amount": "כמות בסיס",
"Datatype": "סוג מידע",
"Number of Objects": "מספר אובייקטים",
"Add_Step": "הוספת צעד",
"Keywords": "מילות מפתח",
"Books": "ספרים",
"Proteins": "פרוטאינים",
"Fats": "שומנים",
"Carbohydrates": "פחמימות",
"Calories": "קלוריות",
"Energy": "אנרגיה",
"Nutrition": "תזונה",
"Date": "תאריך",
"Share": "שיתוף",
"Automation": "אוטומטציה",
"Parameter": "פרמטר",
"Export": "ייצוא",
"Copy": "העתקה",
"Rating": "דירוג",
"Close": "סגירה",
"Cancel": "ביטול",
"Link": "קישור",
"Add": "הוספה",
"New": "חדש",
"Note": "הערה",
"Success": "הצלחה",
"Failure": "כשלון",
"Protected": "מוגן",
"Ingredients": "מרכיבים",
"Supermarket": "סופר מרקט",
"Categories": "קטגוריות",
"Category": "קטגוריה",
"Selected": "נבחר",
"min": "דקה",
"Servings": "מנות",
"Waiting": "המתנה",
"Preparation": "הכנה",
"External": "חיצוני",
"Size": "גודל",
"Files": "קבצים",
"File": "קובץ",
"Edit": "ערוך",
"Image": "תמונה",
"Delete": "מחק",
"Open": "פתח",
"Ok": "אישור",
"Save": "שמור",
"Step": "צעד",
"Search": "חיפוש",
"Import": "ייבוא",
"Print": "הדפסה",
"Settings": "הגדרות",
"or": "או",
"and": "וגם",
"Information": "מידע",
"Download": "הורדה",
"Create": "יצירה",
"Search Settings": "חיפוש הגדרות",
"View": "תצוגה",
"Recipes": "מתכונים",
"Welcome": "ברוכים הבאים",
"Move": "העברה",
"Merge": "איחוד",
"Parent": "הורה",
"Copy Link": "העתק קישור",
"Copy Token": "העתק טוקן",
"delete_confirmation": "האם אתה בטוח שאתה רוצה למחוק {source}?",
"move_confirmation": "העבר<i>{child}</i> אל הורה <i>{parent}</i>",
"merge_confirmation": "החלף <i>{source}</i> עם <i>{target}</i>",
"create_rule": "וגם צור אוטומציה",
"move_selection": "בחר הורה {type} להעביר את {source} אליו.",
"merge_selection": "החלף את כל העותקים של {source} בסוג הנבחר {type}.",
"Root": "ראשי",
"Ignore_Shopping": "התעלם מקניות",
"Shopping_Category": "קטגוריית קניות",
"Shopping_Categories": "קטגוריות קניות",
"Edit_Food": "ערוך אוכל",
"Move_Food": "העבר אוכל",
"New_Food": "אוכל חדש",
"Hide_Food": "הסתר אוכל",
"Food_Alias": "שם כינוי לאוכל",
"Unit_Alias": "שם כינוי ליחידה",
"Keyword_Alias": "שם כינוי למילת מפתח",
"Delete_Food": "מחק אוכל",
"No_ID": "מזהה לא נמצא, בלתי ניתן למחיקה.",
"Meal_Plan_Days": "תכנון אוכל עתידי",
"merge_title": "איחוד {type}",
"move_title": "העברה {type}",
"Food": "אוכל",
"Property": "נכס",
"Conversion": "עברית",
"Original_Text": "כיתוב מקורי",
"Recipe_Book": "ספר מתכון",
"del_confirmation_tree": "האם אתה בטוח שאתה רוצה למחק את {source] ואת כל ילדיו ?",
"delete_title": "מחק {type}",
"create_title": "חדש {type}",
"edit_title": "ערוך {type}",
"Name": "שם",
"Properties": "ערכים",
"Type": "סוג",
"Description": "תיאור",
"Recipe": "מתכון",
"tree_root": "מקור העץ",
"Icon": "צלמית",
"Unit": "ערך",
"Decimals": "דצימל",
"Default_Unit": "ערך ברירת מחדל",
"No_Results": "אין תוצאות",
"New_Unit": "יחידה חדשה",
"Create_New_Shopping Category": "צור קטגוריית קניות",
"Create_New_Food": "הוסף אוכל חדש",
"Create_New_Keyword": "הוסף מילת מפתח",
"Create_New_Unit": "הוסף יחידה",
"Create_New_Meal_Type": "הוסף סוג אוכל חדש",
"Create_New_Shopping_Category": "הוסף קטגוריות קניות חדשה",
"and_up": "ומעלה",
"and_down": "ומטה",
"Instructions": "הוראות",
"Unrated": "בלתי מדורג",
"Automate": "אוטומט",
"Empty": "ריק",
"Key_Ctrl": "Ctrl",
"Key_Shift": "Shift",
"Time": "זמן",
"Text": "כתב",
"Shopping_list": "רשימת קניות",
"Added_by": "נוסף ע\"י",
"Added_on": "נוסף ב",
"AddToShopping": "הוסף לרשימת קניות",
"IngredientInShopping": "רכיב זה ברשימת הקניות.",
"NotInShopping": "{food} אינו רשימת הקניות.",
"OnHand": "כרגע נגיש",
"FoodOnHand": "יש {food} ברשותך.",
"FoodNotOnHand": "אין {food} ברשותך.",
"Undefined": "בלתי מוגדר",
"Create_Meal_Plan_Entry": "צור רשימת תכנון אוכל",
"Edit_Meal_Plan_Entry": "ערוך רשימת תכנון אוכל",
"Title": "כותרת",
"Week": "שבוע",
"Month": "חודש",
"Year": "שנה",
"Planner": "מתכנן",
"Planner_Settings": "הגדרות מתכנן",
"Period": "תקופה",
"Plan_Period_To_Show": "הצד שבועות, חודשים או שנים",
"Periods": "תקופות",
"Plan_Show_How_Many_Periods": "כמה תקופות להציג",
"Starting_Day": "יום תחילת השבוע",
"Meal_Types": "סוגי אוכל",
"Meal_Type": "סוג אוכל",
"New_Entry": "רשומה חדשה",
"Clone": "העתיק",
"Drag_Here_To_Delete": "משוך לכאן למחיקה",
"Meal_Type_Required": "סוג אוכל נדרש",
"Title_or_Recipe_Required": "בחירת כותרת או רכיב חובה",
"Color": "צבע",
"New_Meal_Type": "סוג אוכל חדש",
"Use_Fractions": "השתמש בשברים",
"Use_Fractions_Help": "המר אוטומטית מדצמילי לשברים כאשר צופים במתכון.",
"AddFoodToShopping": "",
"RemoveFoodFromShopping": "",
"DeleteShoppingConfirm": "",
"IgnoredFood": "",
"Add_Servings_to_Shopping": "",
"Week_Numbers": "",
"Show_Week_Numbers": "",
"Export_As_ICal": "",
"Export_To_ICal": "",
"Cannot_Add_Notes_To_Shopping": "",
"Added_To_Shopping_List": "",
"Shopping_List_Empty": "",
"Next_Period": "",
"Previous_Period": "",
"Current_Period": "",
"Next_Day": "",
"Previous_Day": "",
"Inherit": "",
"InheritFields": "",
"FoodInherit": "",
"ShowUncategorizedFood": "",
"GroupBy": "",
"Language": "",
"Theme": "",
"SupermarketCategoriesOnly": "",
"MoveCategory": "",
"CountMore": "...+{count} עוד",
"IgnoreThis": "לעולם אל תוסיף {food} לרשימת הקניות",
"DelayFor": "השהה ל {hours} שעות",
"Warning": "אזהרה",
"NoCategory": "לא נבחרה קטגוריה.",
"InheritWarning": "{food} מוגדר לרשת, שינויים עלולים להידרס.",
"ShowDelayed": "הצג פריטים מושהים",
"Completed": "הושלם",
"OfflineAlert": "אתה במצב מנותק, רשימת הקניות לא בהכרח מסונכרנת.",
"shopping_share": "שתף רשימת קניות",
"shopping_auto_sync": "סינכרון אוטומטי",
"one_url_per_line": "קישור בכל שורה",
"mealplan_autoadd_shopping": "הוסף תוכנית אוכל אוטומטית",
"mealplan_autoexclude_onhand": "אל תכלול מאכל נגיש",
"mealplan_autoinclude_related": "הוסף מתכון קשור",
"default_delay": "שעות השהייה ברירת מחדל",
"plan_share_desc": "רשומות תוכנית אוכל חדשות ישותפו אוטומטית עם המשתמשים שנבחרו.",
"shopping_share_desc": "משתמשים יראה את כל הפריטים ברשימת הקניות. הם חייבים להוסיף אותך בכדי שתוכל לראות את הרשימה שלהם.",
"shopping_auto_sync_desc": "הגדרת 0 יבטל את הסנכרון האוטומטי. כאשר צופים ברשימת קניות, הרשימת מתעדכנת בכל מספר שניות לשינויים שמישהו ייתכן ועשה. שימוש כאשר משתפים רשימה עם מספר אנשים שמשתמשים בחיבור נייד.",
"mealplan_autoadd_shopping_desc": "הוסף אוטומטית רכיבים מתוכנית האוכל לרשימת הקניות.",
"mealplan_autoexclude_onhand_desc": "כאשר מוסיפים רשימת אוכל לרשימת הקניות (ידנית או אוטומטית), אל תכלול מרכיבים נגישים.",
"mealplan_autoinclude_related_desc": "כאשר מוסיפים רשימת אוכל לרשימת הקניות (ידנית או אוטומטית), כלול את כל הרכיבים.",
"default_delay_desc": "ברירת מחדל של שעות שיהוי בהוספת פריט לרשימת קניות.",
"filter_to_supermarket": "סנן לסופרמרקט",
"Coming_Soon": "בקרוב",
"Auto_Planner": "מתכנן אוטומטי",
"New_Cookbook": "ספר מתכונים חדש",
"Hide_Keyword": "הסתר מילות מפתח",
"Hour": "שעה",
"Hours": "שעות",
"Day": "יום",
"Days": "ימים",
"Second": "שניה",
"Seconds": "שניות",
"Clear": "נקה",
"Users": "משתמשים",
"Invites": "הזמנות",
"err_move_self": "לא ניתן להעביר פריט לעצמו",
"nothing": "אין כלום מה לעשות",
"err_merge_self": "בלתי ניתן לאחד פריט עם עצמו",
"show_sql": "הצג SQL",
"filter_to_supermarket_desc": "בברירת המחדל, רשימת קניות כוללה רק את הקטגוריות לסופרמקט הנבחר.",
"CategoryName": "שם קטגוריה",
"SupermarketName": "שם סופרמרקט",
"CategoryInstruction": "",
"shopping_recent_days_desc": "",
"shopping_recent_days": "",
"download_pdf": "",
"download_csv": "",
"csv_delim_help": "",
"csv_delim_label": "",
"SuccessClipboard": "",
"copy_to_clipboard": "",
"csv_prefix_help": "תחילית להוספה כאשר מעתיקים את הרשימה ללוח הכתיבה.",
"csv_prefix_label": "רשימת תחיליות",
"copy_markdown_table": "העתק כטבלת Markdown",
"in_shopping": "ברשימת קניות",
"DelayUntil": "השהה עד",
"Pin": "נעץ",
"Unpin": "שחרר",
"PinnedConfirmation": "{recipe} ננעץ.",
"UnpinnedConfirmation": "{recipe} שוחרר מנעיצה.",
"mark_complete": "סמן כהסתיים",
"QuickEntry": "רשומה מהירה",
"shopping_add_onhand_desc": "סמן מאכל כנגיש לאחר שסומן ברשימת הקניות.",
"shopping_add_onhand": "נגיש ליד אוטומטי",
"related_recipes": "מתכונים קשורים",
"today_recipes": "מתכון היום",
"sql_debug": "תחקור SQL",
"remember_search": "זכור חיפוש",
"remember_hours": "זכור שעות",
"tree_select": "השתמש בבחירת עץ",
"OnHand_help": "מאכלים נמצאים במאגר ולא יתווספו אוטומטית לרשימת הקניות. מצב נגישות משותף בין משתמשי הרכישות.",
"ignore_shopping_help": "לעולם אל תוסיף מאכלים לרשימת הקניות (לדוגמא, מים)",
"shopping_category_help": "הזמנות מהסופרמרקט אפשריות וניתן לסננן על ידי קטגוריות רכישה בהתאם למעברים בחנות.",
"food_recipe_help": "קישור מתכון כאן יכלול את המתכון המקושר בכל מתכון אחר שמשתמש במאכל הזה",
"Foods": "מאכלים",
"Account": "חשבון",
"Cosmetic": "קוסמטי",
"API": "API",
"enable_expert": "אפשר מצב מתקדם",
"expert_mode": "מצב מתקדם",
"simple_mode": "מצב בסיסי",
"advanced": "מתקדם",
"fields": "שדות",
"show_keywords": "הצג מילות מפתח",
"show_foods": "הצג מאכלים",
"show_books": "הצג ספרים",
"show_rating": "הצג דירוג",
"show_units": "הצג יחידות",
"show_filters": "הצג סננים",
"not": "לא",
"save_filter": "שמור סנן",
"filter_name": "שם הסנן",
"left_handed": "מצב יד שמאל",
"left_handed_help": "יתאים את הממשק לשימוש ביד שמאל.",
"Custom Filter": "פילטר מותאם",
"shared_with": "שתף עם",
"sort_by": "סדר ע\"י",
"asc": "עולה",
"desc": "יורד",
"date_viewed": "נצפה לאחרונה",
"last_cooked": "בושל לאחרונה",
"times_cooked": "מספר הפעמים שבושל",
"date_created": "תאריך יציאה",
"show_sortby": "הצג סדר ע\"י",
"search_rank": "חיפוש דירוג",
"make_now": "עשה עכשיו",
"recipe_filter": "סנן מתכון",
"book_filter_help": "כלול מתכונים מתוך סנן המתכון בנוסף למתכונים שסומנו ידנית.",
"review_shopping": "עיין ברשימת הקניות לפני שמירה",
"view_recipe": "הצג מתכון",
"copy_to_new": "העתק למתכון חדש",
"recipe_name": "שם מתכון",
"paste_ingredients_placeholder": "הדבק רשימת רכיבים כאן...",
"paste_ingredients": "הדבק מרכיבים",
"ingredient_list": "רשימת רכיבים",
"explain": "הסבר",
"filter": "סנן",
"Website": "אתר",
"App": "אפליקציה",
"Message": "הודעה",
"Bookmarklet": "סימניה",
"Sticky_Nav": "ניווט דביק",
"Sticky_Nav_Help": "תמיד הצג את תפריט הניווט בראש העמוד.",
"Nav_Color": "צבע ניווט",
"Nav_Color_Help": "שנה את צבע הניווט.",
"Use_Kj": "השתמש בקילוג'אול במקום קילוקלוריות",
"Comments_setting": "הצג תגובות",
"click_image_import": "בחר תמונה שתרצה לייבוא למתכון זה",
"no_more_images_found": "לא נמצאו תמונות נוספות באתר.",
"import_duplicates": "למנוע מצב של מתכונים כפולים עם אותו השם. סמן כאן לייבא הכל.",
"paste_json": "הדבק JSON או HTML כאן לטעינת מתכון.",
"Click_To_Edit": "לחץ לעריכה",
"search_no_recipes": "לא נמצאו כל מתכונים!",
"search_import_help_text": "ייבא מתכון מאתר חיצוני או אפליקציה.",
"search_create_help_text": "צור מתכון חדש ישירות בTandoor.",
"warning_duplicate_filter": "אזהרה: בשל אתגרים טכנולוגיים, השימוש במספר מסננים בעל אותו צירוף עלול לגרום לתוצאות בלתי צפויות.",
"reset_children": "אפס ירושה מילדים",
"reset_children_help": "דרוס את כל ערכי הילדים עם ערכים תורשתיים. ערכים תורשתיים יוגדרו ערכים נורשים אלא אם הערך כבר קיים.",
"reset_food_inheritance": "אפס הורשה",
"reset_food_inheritance_info": "",
"substitute_help": "תחליפים נלקחים בחשבון כאשר מחשפים מתכונים שאפשר להכין עם מרכיבים נגישים.",
"substitute_siblings_help": "כל המאכלים שחולקים הורה, נחשבים תחליפים.",
"substitute_children_help": "כל המאכלים אשר מוגדרים כילדים של המאכל הזה, נחשבים תחליפים.",
"substitute_siblings": "החלפת דומים",
"substitute_children": "החלפת ילדים",
"SubstituteOnHand": "",
"ChildInheritFields": "",
"ChildInheritFields_help": "",
"InheritFields_help": "",
"show_ingredient_overview": "",
"Ingredient Overview": "",
"last_viewed": "נצפה לאחרונה",
"created_on": "נוצר ב",
"updatedon": "עודכן ב",
"Imported_From": "יובא מ",
"advanced_search_settings": "הגדרות חיפוש מתקדמות",
"nothing_planned_today": "שום דבר מתכונן היום!",
"no_pinned_recipes": "אין מתכונים נעוצים!",
"Planned": "מתוכנן",
"Pinned": "נעוץ",
"Imported": "מיובא",
"Quick actions": "פעולות מהירות",
"Ratings": "דירוג",
"Internal": "פנימי",
"Units": "יחידות",
"Manage_Emails": "נהל כתובות דואר אלקטרוני",
"Change_Password": "החלפת סיסמא",
"Social_Authentication": "",
"Random Recipes": "",
"parameter_count": "פרטמר {count}",
"select_keyword": "",
"add_keyword": "",
"select_file": "",
"select_recipe": "",
"select_unit": "",
"select_food": "בחר מאכל",
"remove_selection": "הסר בחירה",
"empty_list": "הרשימה ריקה.",
"Select": "בחר",
"Supermarkets": "סופרמרקטים",
"User": "משתמש",
"Username": "שם משתמש",
"First_name": "שם פרטי",
"Last_name": "שם משפחה",
"Keyword": "מילת מפתח",
"Advanced": "מתקדם",
"Page": "עמוד",
"Single": "בודד",
"Multiple": "מרובה",
"Reset": "אפס",
"Disabled": "מושבת",
"Disable": "השבת",
"Options": "אפשרויות",
"Create Food": "צור מאכל",
"create_food_desc": "צור מאכל וקשרו למתכון.",
"additional_options": "אפשרויות נוספות",
"Importer_Help": "עוד מידע ועזרה על כלי ייבוא זה:",
"Documentation": "תיעוד",
"Select_App_To_Import": "בחור אפליקציה לייבוא מתוך",
"Import_Supported": "ייבוא נתמך",
"Export_Supported": "ייצוא נתמך",
"Import_Not_Yet_Supported": "ייבוא לא נתמך עדיין",
"Export_Not_Yet_Supported": "ייצוא לא נתמך עדיין",
"Import_Result_Info": "{imported} מתוך {total} מתכונים יובאו",
"Recipes_In_Import": "מתכון בקובץ הייבוא",
"Toggle": "אפשר",
"total": "סך הכל",
"Import_Error": "שגיאה בעת ייבוא. הרחב את הפירוט בסוף עמוד זה לראות מידע נוסף.",
"Warning_Delete_Supermarket_Category": "מחיקת קטגורית סופרמרקט תמחוק גם את המאכלים הקשורים. האם אתה בטוח ?",
"New_Supermarket": "צור סופרמרקט חדש",
"New_Supermarket_Category": "צור קטגורית סופרמקט חדשה",
"Are_You_Sure": "בטוח?",
"Valid Until": "פעיל עד",
"Split_All_Steps": "פצל את כל השורות לצעדים נפרדים.",
"Combine_All_Steps": "אחד את כל הצעדים לשדה אחד.",
"Plural": "רבים",
"plural_short": "רבים",
"g": "גרם (g)",
"kg": "קילוגרם [kg]",
"ounce": "אונקיה [oz]",
"pound": "פאונד (משקל)",
"ml": "מיליליטר [ml]",
"l": "ליטר [l]",
"fluid_ounce": "אונקיה נוזלית [fl oz]",
"pint": "פיינט [pt]",
"quart": "קווארט [qt]",
"gallon": "גלון [gal]",
"tbsp": "כף",
"tsp": "כפית",
"imperial_fluid_ounce": "אונקיה אמפיריאלית",
"imperial_pint": "פינט אימפריאלי",
"imperial_quart": "קווארט אימפריאלי",
"imperial_gallon": "גאלון אימפריאלי",
"imperial_tbsp": "כף אימפריאלית",
"imperial_tsp": "כפית אימפריאלית",
"Choose_Category": "בחר קטגוריה",
"Back": "חזור",
"Use_Plural_Unit_Always": "תמיד השתמש ברבים ליחידות",
"Use_Plural_Unit_Simple": "השתמש ברבים ליחידות בצורה דינאמית",
"Use_Plural_Food_Always": "תמיד השתמש בצורת רבים למאכלים",
"Use_Plural_Food_Simple": "השתמש בצורת רבים למאכלים בצורה דינאמית",
"plural_usage_info": "תמיד השתמש בצורת רבים למאכלים במרחב זה.",
"Create Recipe": "צור מתכון",
"Import Recipe": "ייבא מתכון"
}

View File

@@ -145,133 +145,133 @@
"move_selection": "Velg en forelder {type} å flytte {source} til.",
"merge_selection": "Erstatt alle tilfeller av {source} med den valgte {type}.",
"Root": "Rot",
"Ignore_Shopping": "",
"Shopping_Category": "",
"Shopping_Categories": "",
"Edit_Food": "",
"Move_Food": "",
"New_Food": "",
"Hide_Food": "",
"Food_Alias": "",
"Unit_Alias": "",
"Keyword_Alias": "",
"Delete_Food": "",
"No_ID": "",
"Meal_Plan_Days": "",
"merge_title": "",
"move_title": "",
"Food": "",
"Original_Text": "",
"Recipe_Book": "",
"del_confirmation_tree": "",
"delete_title": "",
"create_title": "",
"edit_title": "",
"Name": "",
"Type": "",
"Description": "",
"Recipe": "",
"tree_root": "",
"Icon": "",
"Unit": "",
"Decimals": "",
"Default_Unit": "",
"No_Results": "",
"New_Unit": "",
"Create_New_Shopping Category": "",
"Create_New_Food": "",
"Create_New_Keyword": "",
"Create_New_Unit": "",
"Create_New_Meal_Type": "",
"Create_New_Shopping_Category": "",
"and_up": "",
"and_down": "",
"Instructions": "",
"Unrated": "",
"Automate": "",
"Empty": "",
"Key_Ctrl": "",
"Key_Shift": "",
"Time": "",
"Text": "",
"Shopping_list": "",
"Added_by": "",
"Added_on": "",
"AddToShopping": "",
"IngredientInShopping": "",
"NotInShopping": "",
"OnHand": "",
"FoodOnHand": "",
"FoodNotOnHand": "",
"Undefined": "",
"Create_Meal_Plan_Entry": "",
"Edit_Meal_Plan_Entry": "",
"Title": "",
"Week": "",
"Month": "",
"Year": "",
"Planner": "",
"Planner_Settings": "",
"Period": "",
"Plan_Period_To_Show": "",
"Periods": "",
"Plan_Show_How_Many_Periods": "",
"Starting_Day": "",
"Meal_Types": "",
"Meal_Type": "",
"New_Entry": "",
"Clone": "",
"Drag_Here_To_Delete": "",
"Meal_Type_Required": "",
"Title_or_Recipe_Required": "",
"Color": "",
"New_Meal_Type": "",
"Use_Fractions": "",
"Use_Fractions_Help": "",
"AddFoodToShopping": "",
"RemoveFoodFromShopping": "",
"DeleteShoppingConfirm": "",
"Ignore_Shopping": "Ignorer Handlekurv",
"Shopping_Category": "Butikk Kategori",
"Shopping_Categories": "Butikk Kategorier",
"Edit_Food": "Rediger Matrett",
"Move_Food": "Flytt Matrett",
"New_Food": "Ny Matrett",
"Hide_Food": "Skjul Matrett",
"Food_Alias": "Matrett Alias",
"Unit_Alias": "Enhet Alias",
"Keyword_Alias": "Nøkkelord Alias",
"Delete_Food": "Slett Matrett",
"No_ID": "ID ikke funnet, kan ikke slette.",
"Meal_Plan_Days": "Fremtidige måltidsplaner",
"merge_title": "Slå sammen {type}",
"move_title": "Flytt {type}",
"Food": "Matretter",
"Original_Text": "Orginal tekst",
"Recipe_Book": "Oppskriftsbok",
"del_confirmation_tree": "Er du sikker på at du vil slette {source} og alt under?",
"delete_title": "Slett {type}",
"create_title": "Ny {type}",
"edit_title": "Rediger {type}",
"Name": "Navn",
"Type": "Type",
"Description": "Beskrivelse",
"Recipe": "Oppskrift",
"tree_root": "Rot av tre",
"Icon": "Ikon",
"Unit": "Enhet",
"Decimals": "Desimaler",
"Default_Unit": "Standard Enhet",
"No_Results": "Ingen resultat",
"New_Unit": "Ny Enhet",
"Create_New_Shopping Category": "Opprett ny handle kategori",
"Create_New_Food": "Opprett ny matrett",
"Create_New_Keyword": "Opprett nytt nøkkelord",
"Create_New_Unit": "Opprett ny enhet",
"Create_New_Meal_Type": "Opprett ny matrett type",
"Create_New_Shopping_Category": "Opprett new handle kategori",
"and_up": "& Opp",
"and_down": "& Ned",
"Instructions": "Instruksjoner",
"Unrated": "Urangert",
"Automate": "Automatiser",
"Empty": "Tom",
"Key_Ctrl": "Ctrl",
"Key_Shift": "Shift",
"Time": "Tid",
"Text": "Tekst",
"Shopping_list": "Handleliste",
"Added_by": "Lagt til av",
"Added_on": "Lagt til",
"AddToShopping": "Legg til i handleliste",
"IngredientInShopping": "Denne ingrediensen er i handlekurven din.",
"NotInShopping": "{food} er ikke i handlelisten din.",
"OnHand": "På lager",
"FoodOnHand": "Du har {food} på lager.",
"FoodNotOnHand": "Du har ikke {food} på lager.",
"Undefined": "Udefinert",
"Create_Meal_Plan_Entry": "Opprett måltidsplanoppføring",
"Edit_Meal_Plan_Entry": "Rediger måltidsplanoppføring",
"Title": "Tittel",
"Week": "Uke",
"Month": "Måned",
"Year": "År",
"Planner": "Planlegger",
"Planner_Settings": "Planleggingsinstilliger",
"Period": "Periode",
"Plan_Period_To_Show": "Vis uke, måned eller år",
"Periods": "Perioder",
"Plan_Show_How_Many_Periods": "Hvor mange perioder skal vises",
"Starting_Day": "Dag uken skal state på",
"Meal_Types": "Måltidstyper",
"Meal_Type": "Måltidstype",
"New_Entry": "Ny oppføring",
"Clone": "Klon",
"Drag_Here_To_Delete": "Dra her for å slette",
"Meal_Type_Required": "Måltidstype er nødvendig",
"Title_or_Recipe_Required": "Tittel- eller oppskrifts-valg nødvendig",
"Color": "Farge",
"New_Meal_Type": "Ny Måltidstype",
"Use_Fractions": "Bruk deler",
"Use_Fractions_Help": "Automatisk konverter desimaler til deler når du ser på en oppskrift.",
"AddFoodToShopping": "Legg til {food] i handlelisten din",
"RemoveFoodFromShopping": "Fjern {food} fra handelisten din",
"DeleteShoppingConfirm": "Er du sikker på at du fjerne alle {food} fra handlelisten?",
"IgnoredFood": "",
"Add_Servings_to_Shopping": "",
"Week_Numbers": "",
"Show_Week_Numbers": "",
"Export_As_ICal": "",
"Export_To_ICal": "",
"Cannot_Add_Notes_To_Shopping": "",
"Added_To_Shopping_List": "",
"Add_Servings_to_Shopping": "Legg til {servings} serveringer i handlelisten",
"Week_Numbers": "Ukenummer",
"Show_Week_Numbers": "Vis ukenummer?",
"Export_As_ICal": "Eksporter gjeldende periode som iCal format",
"Export_To_ICal": "Eksporter .ics",
"Cannot_Add_Notes_To_Shopping": "Notater kan ikke legges til i handlelisten",
"Added_To_Shopping_List": "Lagt til i handlelisten",
"Shopping_List_Empty": "",
"Next_Period": "",
"Previous_Period": "",
"Current_Period": "",
"Next_Day": "",
"Previous_Day": "",
"Next_Period": "Neste periode",
"Previous_Period": "Forrige periode",
"Current_Period": "Gjeldende periode",
"Next_Day": "Neste dag",
"Previous_Day": "Forrige dag",
"Inherit": "",
"InheritFields": "",
"FoodInherit": "",
"ShowUncategorizedFood": "",
"GroupBy": "",
"Language": "",
"Theme": "",
"SupermarketCategoriesOnly": "",
"MoveCategory": "",
"ShowUncategorizedFood": "Vis udefinerte",
"GroupBy": "Grupér",
"Language": "Språk",
"Theme": "Tema",
"SupermarketCategoriesOnly": "Kun Butikkategorier",
"MoveCategory": "Flytt til: ",
"CountMore": "",
"IgnoreThis": "",
"DelayFor": "",
"Warning": "",
"NoCategory": "",
"IgnoreThis": "Aldri legg til {food} automatisk i handlelisten",
"DelayFor": "Utsett i {hours} timer",
"Warning": "Advarsel",
"NoCategory": "Ingen kategori valgt.",
"InheritWarning": "",
"ShowDelayed": "",
"Completed": "",
"OfflineAlert": "",
"shopping_share": "",
"shopping_auto_sync": "",
"one_url_per_line": "",
"mealplan_autoadd_shopping": "",
"mealplan_autoexclude_onhand": "",
"mealplan_autoinclude_related": "",
"default_delay": "",
"plan_share_desc": "",
"shopping_share_desc": "",
"ShowDelayed": "Vis Utsatte Gjenstander",
"Completed": "Fullført",
"OfflineAlert": "Du er ikke koblet til internett. Det kan hende handlelisten ikke synkroniserer.",
"shopping_share": "Del handlelisten",
"shopping_auto_sync": "Synkroniser automatisk",
"one_url_per_line": "En Lenke per linje",
"mealplan_autoadd_shopping": "Automatisk legg til måltidsplan",
"mealplan_autoexclude_onhand": "Eksluder mat på lager",
"mealplan_autoinclude_related": "Legg til relaterte oppskrifter",
"default_delay": "Standard Timer å Utsette",
"plan_share_desc": "Nye måltidsplaner vil automatisk bli delt med valgte brukere.",
"shopping_share_desc": "Brukere vil se alle gjenstander du har lagt til i handlelisten. Brukerne må legge deg til for at du kan se deres gjenstander på handlelisten.",
"shopping_auto_sync_desc": "",
"mealplan_autoadd_shopping_desc": "",
"mealplan_autoexclude_onhand_desc": "",
@@ -478,7 +478,7 @@
"Use_Plural_Food_Simple": "",
"plural_usage_info": "",
"Create Recipe": "",
"Import Recipe": "",
"Import Recipe": "Importer oppskrift",
"per_serving": "Per porsjon",
"open_data_help_text": "Tandoor Open Data prosjektet gir fra fellesskapet til Tandoor. Dette feltet fylles ut automatisk når det importeres og tillater oppdateringer i fremtiden.",
"Open_Data_Slug": "Åpne data Slug",
@@ -492,5 +492,8 @@
"base_unit": "Baseenhet",
"base_amount": "Basemengde",
"Datatype": "Data-type",
"Number of Objects": "Antall objekter"
"Number of Objects": "Antall objekter",
"Property": "Egenskap",
"Conversion": "Omregn enhet",
"Properties": "Egenskaper"
}

View File

@@ -499,5 +499,26 @@
"Property": "Właściwość",
"Conversion": "Konwersja",
"Properties": "Właściwości",
"total": "łącznie"
"total": "łącznie",
"Welcome": "Witamy",
"g": "gram [g] (metryczny, waga)",
"ml": "mililitr [ml] (metryczny, objętość)",
"quart": "kwarta [qt] (USA, objętość)",
"imperial_fluid_ounce": "imperialna uncja płynu [imp fl oz] (WB, objętość)",
"imperial_tbsp": "imperialna łyżka stołowa [imp tbsp] (WB, objętość)",
"kg": "kilogram [kg] (metryczny, waga)",
"ounce": "uncja [oz] (waga)",
"pound": "funt (waga)",
"l": "litr [l] (metryczny, objętość)",
"fluid_ounce": "uncja płynu [fl oz] (USA, objętość)",
"gallon": "galon [gal] (USA, objętość)",
"tbsp": "łyżka stołowa [tbsp] (USA, objętość)",
"tsp": "łyżeczka [tsp] (USA, objętość)",
"imperial_pint": "pinta imperialna [imp pt] (WB, objętość)",
"pint": "pinta [pt] (USA, objętość)",
"imperial_quart": "kwarta imperialna [imp qt] (WB, objętość)",
"imperial_gallon": "imperialny galon [imp gal] (WB, objętość)",
"imperial_tsp": "łyżeczka imperialna [imp tsp] (WB, objętość)",
"Choose_Category": "Wybierz kategorię",
"Back": "Z powrotem"
}

View File

@@ -291,5 +291,31 @@
"Use_Plural_Unit_Simple": "",
"Use_Plural_Food_Always": "",
"Use_Plural_Food_Simple": "",
"plural_usage_info": ""
"plural_usage_info": "",
"err_deleting_protected_resource": "Predmet, ki ga želite izbrisati, je še vedno v uporabi in ga ni mogoče izbrisati.",
"Private_Recipe": "Zasebni Recept",
"Private_Recipe_Help": "Recept je prikazan samo vam in osebam, s katerimi ga delite.",
"reusable_help_text": "Ali lahko povezavo za povabilo uporabi več kot en uporabnik.",
"Auto_Sort": "Samodejno Razvrščanje",
"Auto_Sort_Help": "Vse sestavine prestavi v najprimernejši korak.",
"food_inherit_info": "Polja za živila, ki so privzeto podedovana.",
"Description_Replace": "Zamenjaj Opis",
"recipe_property_info": "Živilom lahko dodate tudi lastnosti, ki se samodejno izračunajo na podlagi vašega recepta!",
"warning_space_delete": "Izbrišete lahko svoj prostor, vključno z vsemi recepti, nakupovalnimi seznami, načrti obrokov in vsem drugim, kar ste ustvarili. Tega ni mogoče preklicati! Ste prepričani, da želite to storiti?",
"facet_count_info": "Prikaži število receptov v iskalnih filtrih.",
"per_serving": "na porcijo",
"Ingredient Editor": "Urejevalnik Sestavin",
"Instruction_Replace": "Zamenjaj Navodila",
"open_data_help_text": "Projekt Tandoor Open Data zagotavlja podatke, ki jih je prispeva skupnost. To polje se samodejno izpolni ob uvozu in omogoča posodobitve v prihodnosti.",
"Open_Data_Slug": "Open Data Identifikator",
"Open_Data_Import": "Open Data Uvoz",
"Data_Import_Info": "Izboljšajte svoj prostor z uvozom seznama živil, enot in drugega, ker je pripravila skupnost, ter s tem izboljšajte svojo zbirko receptov.",
"Update_Existing_Data": "Posodobitev Obstoječih Podatkov",
"Use_Metric": "Uporaba Metričnih Enot",
"Learn_More": "Preberite Več",
"converted_unit": "Pretvorjena Enota",
"converted_amount": "Pretvorjena Količina",
"base_unit": "Osnovna Enota",
"base_amount": "Osnovna Količina",
"Amount": "Količina"
}

View File

@@ -258,12 +258,14 @@ export class Models {
field: "description",
label: "Description",
placeholder: "",
optional: true,
},
icon: {
form_field: true,
type: "emoji",
field: "icon",
label: "Icon",
optional: true,
},
full_name: {
form_field: true,
@@ -279,7 +281,7 @@ export class Models {
apiName: "Unit",
paginated: true,
create: {
params: [["name", "plural_name", "description", "open_data_slug",]],
params: [["name", "plural_name", "description", "base_unit","open_data_slug",]],
form: {
show_help: true,
name: {
@@ -295,6 +297,7 @@ export class Models {
field: "plural_name",
label: "Plural name",
placeholder: "",
optional: true,
},
description: {
form_field: true,
@@ -302,6 +305,35 @@ export class Models {
field: "description",
label: "Description",
placeholder: "",
optional: true,
},
base_unit: {
form_field: true,
type: "choice",
options: [
{value: "g", text: "g"},
{value: "kg", text: "kg"},
{value: "ounce", text: "ounce"},
{value: "pound", text: "pound"},
{value: "ml", text: "ml"},
{value: "l", text: "l"},
{value: "fluid_ounce", text: "fluid_ounce"},
{value: "pint", text: "pint"},
{value: "quart", text: "quart"},
{value: "gallon", text: "gallon"},
{value: "tbsp", text: "tbsp"},
{value: "tsp", text: "tsp"},
{value: "imperial_fluid_ounce", text: "imperial_fluid_ounce"},
{value: "imperial_pint", text: "imperial_pint"},
{value: "imperial_quart", text: "imperial_quart"},
{value: "imperial_gallon", text: "imperial_gallon"},
{value: "imperial_tbsp", text: "imperial_tbsp"},
{value: "imperial_tsp", text: "imperial_tsp"},
],
field: "base_unit",
label: "Base Unit",
placeholder: "",
optional: true,
},
open_data_slug: {
form_field: true,
@@ -310,6 +342,7 @@ export class Models {
disabled: true,
label: "Open_Data_Slug",
help_text: "open_data_help_text",
optional: true,
},
},
},
@@ -364,12 +397,14 @@ export class Models {
field: "description",
label: "Description",
placeholder: "",
optional: true,
},
icon: {
form_field: true,
type: "emoji",
field: "icon",
label: "Icon",
optional: true,
},
filter: {
form_field: true,
@@ -377,6 +412,7 @@ export class Models {
field: "filter",
label: "Custom Filter",
list: "CUSTOM_FILTER",
optional: true,
},
},
},
@@ -401,6 +437,7 @@ export class Models {
field: "description",
label: "Description",
placeholder: "",
optional: true,
},
},
},
@@ -451,6 +488,7 @@ export class Models {
field: "description",
label: "Description",
placeholder: "",
optional: true,
},
categories: {
form_field: true,
@@ -461,6 +499,7 @@ export class Models {
field: "category_to_supermarket",
label: "Categories", // form.label always translated in utils.getForm()
placeholder: "",
optional: true,
},
open_data_slug: {
form_field: true,
@@ -469,6 +508,7 @@ export class Models {
disabled: true,
label: "Open_Data_Slug",
help_text: "open_data_help_text",
optional: true,
},
},
config: {
@@ -507,6 +547,7 @@ export class Models {
field: "description",
label: "Description",
placeholder: "",
optional: true,
},
type: {
form_field: true,
@@ -652,6 +693,7 @@ export class Models {
disabled: true,
label: "Open_Data_Slug",
help_text: "open_data_help_text",
optional: true,
},
},
@@ -685,6 +727,7 @@ export class Models {
field: "icon",
label: "Icon",
placeholder: "",
optional: true,
},
unit: {
form_field: true,
@@ -692,6 +735,7 @@ export class Models {
field: "unit",
label: "Unit",
placeholder: "",
optional: true,
},
description: {
form_field: true,
@@ -699,6 +743,7 @@ export class Models {
field: "description",
label: "Description",
placeholder: "",
optional: true,
},
open_data_slug: {
form_field: true,
@@ -707,6 +752,7 @@ export class Models {
disabled: true,
label: "Open_Data_Slug",
help_text: "open_data_help_text",
optional: true,
},
},
@@ -853,15 +899,8 @@ export class Models {
apiName: "InviteLink",
paginated: false,
create: {
params: [["email", "group", "valid_until", "reusable"]],
params: [["email", "group", "valid_until", "reusable", "internal_note"]],
form: {
email: {
form_field: true,
type: "text",
field: "email",
label: "Email",
placeholder: "",
},
group: {
form_field: true,
type: "lookup",
@@ -878,6 +917,14 @@ export class Models {
label: "Valid Until",
placeholder: "",
},
email: {
form_field: true,
type: "text",
field: "email",
label: "Email",
placeholder: "",
optional: true,
},
reusable: {
form_field: true,
type: "checkbox",
@@ -886,6 +933,15 @@ export class Models {
help_text: "reusable_help_text",
placeholder: "",
},
internal_note: {
form_field: true,
type: "textarea",
field: "internal_note",
label: "Note",
placeholder: "",
optional: true,
},
form_function: "InviteLinkDefaultValid",
},
},
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@ import {BToast} from "bootstrap-vue"
// * */
import Vue from "vue"
import {Actions, Models} from "./models"
import moment from "moment";
export const ToastMixin = {
name: "ToastMixin",
@@ -125,10 +126,13 @@ export class StandardToasts {
let DEBUG = localStorage.getItem("DEBUG") === "True" || always_show_errors
if (DEBUG){
console.log('ERROR ', err, JSON.stringify(err?.response?.data))
console.trace();
}
if (err !== undefined && 'response' in err && 'headers' in err.response) {
if (DEBUG && err.response.headers['content-type'] === 'application/json' && err.response.status < 500) {
console.log('ERROR ', JSON.stringify(err.response.data))
msg = context.$createElement('div', {}, [
context.$createElement('span', {}, [msg]),
context.$createElement('br', {}, []),
@@ -721,6 +725,10 @@ export const formFunctions = {
form.fields.filter((x) => x.field === "inherit_fields")[0].value = getUserPreference("food_inherit_default")
return form
},
InviteLinkDefaultValid: function (form){
form.fields.filter((x) => x.field === "valid_until")[0].value = moment().add(7, "days").format('yyyy-MM-DD')
return form
},
AutomationOrderDefault: function (form) {
if (form.fields.filter((x) => x.field === "order")[0].value === undefined) {
form.fields.filter((x) => x.field === "order")[0].value = 1000

View File

@@ -9769,19 +9769,19 @@ selfsigned@^2.1.1:
node-forge "^1"
"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
version "5.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
version "6.3.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8:
version "7.5.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.2.tgz#5b851e66d1be07c1cdaf37dfc856f543325a2beb"
integrity sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
@@ -11623,9 +11623,9 @@ wildcard@^2.0.0:
integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
word-wrap@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
version "1.2.4"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"
integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==
workbox-background-sync@6.6.1, workbox-background-sync@^6.5.4:
version "6.6.1"