Compare commits

...

608 Commits
1.0.7 ... 1.2.7

Author SHA1 Message Date
vabene1111
0e2a27ad41 Merge branch 'develop' 2022-05-25 18:53:18 +02:00
vabene1111
c064e8970f compiled messages 2022-05-25 17:58:29 +02:00
Krisztian Doka
b8ef7ae39d Translated using Weblate (Hungarian)
Currently translated at 92.2% (487 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2022-05-24 20:32:14 +00:00
Krisztian Doka
702f3de061 Added translation using Weblate (Hungarian) 2022-05-23 19:50:50 +00:00
Ramon Aixa Juan
f278d7f6d0 Translated using Weblate (Spanish)
Currently translated at 8.2% (34 of 414 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/es/
2022-05-23 11:32:17 +00:00
Ramon Aixa Juan
221c1b523b Translated using Weblate (Spanish)
Currently translated at 52.2% (276 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/es/
2022-05-23 11:32:17 +00:00
Ramon Aixa Juan
d00b6a2e85 Translated using Weblate (Catalan)
Currently translated at 91.0% (481 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ca/
2022-05-22 11:20:51 +00:00
César Blanco Guillamon
e03c285f14 Translated using Weblate (Spanish)
Currently translated at 5.3% (22 of 414 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/es/
2022-05-21 17:32:19 +00:00
Tomasz Klimczak
0ec1f334c0 Translated using Weblate (Polish)
Currently translated at 100.0% (414 of 414 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2022-05-21 17:32:19 +00:00
Laura
b637cbeabc Translated using Weblate (French)
Currently translated at 90.3% (374 of 414 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2022-05-21 17:32:18 +00:00
César Blanco Guillamon
943f873855 Translated using Weblate (Spanish)
Currently translated at 51.3% (271 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/es/
2022-05-19 10:10:33 +00:00
César Blanco Guillamon
49cebb400a Added translation using Weblate (Spanish) 2022-05-19 10:10:33 +00:00
vabene1111
991fbdad3a fixed localization of create shopping auto form 2022-05-18 16:49:25 +02:00
vabene1111
34e95cd25b improved mobile rendering on ingerdient editor 2022-05-18 16:44:27 +02:00
vabene1111
8bc06fef34 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2022-05-18 16:27:11 +02:00
vabene1111
6aba5c3661 fixed plan to eat tag delimeter 2022-05-18 16:27:07 +02:00
vabene1111
876bd49ee5 Merge pull request #1793 from smilerz/url_import_test
fixed spuce eats test
2022-05-18 16:25:30 +02:00
vabene1111
9435c5a380 changed order for reverse auth middleware 2022-05-18 16:09:37 +02:00
vabene1111
94c915e23a fixed advanced search field configuration cookie expiery 2022-05-18 16:06:55 +02:00
vabene1111
9ac8641c13 dont make first step header as default if others are not 2022-05-18 15:55:58 +02:00
vabene1111
0fe06cf2df fixed random search ordering 2022-05-18 15:54:02 +02:00
vabene1111
f872f994f1 fixed import failure with leading commas in input strings 2022-05-18 15:29:03 +02:00
vabene1111
87c2ff73e8 Merge branch 'develop' 2022-05-18 14:38:01 +02:00
Gabriel Tapias
27bb4c9bb8 Translated using Weblate (Spanish)
Currently translated at 48.1% (254 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/es/
2022-05-17 21:32:15 +00:00
vabene1111
ac647c5ee8 more JS nonsense 2022-05-17 22:00:36 +02:00
vabene1111
3cec891aa1 added missing dependency 2022-05-17 21:57:43 +02:00
vabene1111
3633b9724b fixed image deletion error 2022-05-17 21:53:10 +02:00
vabene1111
420b5c093f updated some dependencies 2022-05-17 21:43:52 +02:00
vabene1111
9bb55dd746 Merge pull request #1758 from TandoorRecipes/dependabot/npm_and_yarn/vue/kangc/v-md-editor-1.7.11
Bump @kangc/v-md-editor from 1.7.9 to 1.7.11 in /vue
2022-05-17 21:38:00 +02:00
dependabot[bot]
1759ad3587 Bump @kangc/v-md-editor from 1.7.9 to 1.7.11 in /vue
Bumps [@kangc/v-md-editor](https://github.com/code-farmer-i/vue-markdown-editor) from 1.7.9 to 1.7.11.
- [Release notes](https://github.com/code-farmer-i/vue-markdown-editor/releases)
- [Changelog](https://github.com/code-farmer-i/vue-markdown-editor/blob/dev/docs/changelog.md)
- [Commits](https://github.com/code-farmer-i/vue-markdown-editor/compare/v1.7.9...v1.7.11)

---
updated-dependencies:
- dependency-name: "@kangc/v-md-editor"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-17 19:30:34 +00:00
vabene1111
956693b7ca changed view mode of file viewer downloadable files
changed it so that the file is always downloaded so that opened files do not open in the application context (to prevent possible XSS issues)
2022-05-17 21:27:40 +02:00
vabene1111
7b2117c019 improved output sanitization of several views 2022-05-17 21:24:27 +02:00
vabene1111
d48fe26a35 added url validation to all server requests 2022-05-17 18:04:43 +02:00
Kaibu
7fd5fca0cf changed mobile logo to png version aswell 2022-05-13 15:11:04 +02:00
smilerz
37e215a4ea fixed spuce eats test 2022-05-11 14:18:14 -05:00
vabene1111
378938812c update recipe scrapers 2022-05-11 20:42:28 +02:00
vabene1111
60b494abeb workflow name 2022-05-11 20:30:17 +02:00
vabene1111
34be1dc1d7 removed notification from raspi build 2022-05-11 20:14:53 +02:00
vabene1111
d89a4620f0 meal plan remove old add to shopping 2022-05-11 19:59:04 +02:00
vabene1111
dea83b5720 fixed duplication of values in recipe editor 2022-05-11 19:31:44 +02:00
vabene1111
d9ebe3e0fb fixed original text rendering in recipe edito view 2022-05-11 19:25:48 +02:00
vabene1111
135dde247f fixed static path generation 2022-05-11 19:17:40 +02:00
vabene1111
eb7a667202 fixed cookmate importer 2022-05-11 19:10:56 +02:00
Kaibu
b3cc9967f5 Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2022-05-11 17:10:18 +02:00
Kaibu
7276cea3d5 multiple ux fixes 2022-05-11 17:10:12 +02:00
vabene1111
c0c996622e made shopping new entry translatable 2022-05-11 17:06:34 +02:00
vabene1111
5556555bca fixed paprika servings import 2022-05-11 17:05:47 +02:00
vabene1111
55a84494c9 fixed issue with plan to eat importer 2022-05-11 16:53:20 +02:00
vabene1111
74d778dcb8 compiled messages 2022-05-11 16:45:34 +02:00
vabene1111
156d68f1b8 added link to shopping recipes 2022-05-11 16:42:52 +02:00
vabene1111
cb59a6340d Merge pull request #1788 from gloriousDan/fix-import
Fix import with recipe-scrapers
2022-05-11 16:37:41 +02:00
vabene1111
5eb013cc2f Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2022-05-11 16:22:18 +02:00
vabene1111
dafb26b500 updated raspi docs 2022-05-11 16:22:13 +02:00
vabene1111
d9416a42dc Merge pull request #1786 from gloriousDan/dockerfile-armv7
Build pillow for armv7/ raspi
2022-05-11 16:17:45 +02:00
Jesse
ad88eff9e3 Translated using Weblate (Dutch)
Currently translated at 100.0% (528 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/nl/
2022-05-10 15:32:17 +00:00
zeon
4d4f623adf Translated using Weblate (Bulgarian)
Currently translated at 100.0% (412 of 412 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/bg/
2022-05-10 15:32:16 +00:00
Mathias Rasmussen
ac9c9cd4e3 Translated using Weblate (Danish)
Currently translated at 100.0% (528 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/da/
2022-05-10 15:32:15 +00:00
Jesse
580eeef6b7 Translated using Weblate (Dutch)
Currently translated at 100.0% (412 of 412 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nl/
2022-05-10 15:32:13 +00:00
zeon
f25f5a26cf Translated using Weblate (Bulgarian)
Currently translated at 100.0% (528 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/bg/
2022-05-10 15:32:11 +00:00
Mathias Rasmussen
972d43c2a2 Translated using Weblate (Danish)
Currently translated at 100.0% (412 of 412 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/da/
2022-05-10 15:32:09 +00:00
Daniel Schulz
2a7475c435 Call scrape_me first when scraping from url 2022-05-10 00:08:37 +02:00
Daniel Schulz
71b41efe6c Build pillow for armv7/ raspi 2022-05-09 13:24:59 +02:00
zeon
33a7fee1cc Added translation using Weblate (Bulgarian) 2022-05-08 21:25:53 +00:00
zeon
fa7fb644ea Added translation using Weblate (Bulgarian) 2022-05-08 20:44:02 +00:00
Mathias Rasmussen
13b996171a Translated using Weblate (Danish)
Currently translated at 1.9% (8 of 412 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/da/
2022-05-07 16:49:26 +00:00
Kim Dannemand
77bb3870bf Translated using Weblate (Danish)
Currently translated at 1.9% (8 of 412 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/da/
2022-05-07 16:49:26 +00:00
vabene1111
9863303a5e Merge remote-tracking branch 'origin/develop' into develop 2022-05-06 20:32:14 +02:00
vabene1111
0caccc3da8 updated it and ru languages 2022-05-06 20:31:57 +02:00
vabene1111
b75427b86d Added translation using Weblate (Danish) 2022-05-06 18:30:41 +00:00
vabene1111
054c4ec61a Added translation using Weblate (Danish) 2022-05-06 18:30:05 +00:00
vabene1111
8da21f9914 added specific build files for raspi (armv7) 2022-05-06 20:28:20 +02:00
vabene1111
99ba512862 Merge branch 'beta' into develop 2022-05-06 20:24:27 +02:00
vabene1111
eab59fcbd8 Update docker-publish-latest-raspi.yml 2022-05-06 16:08:13 +02:00
vabene1111
484da2200e added some debug to auto add shopping signal 2022-05-06 15:34:28 +02:00
vabene1111
330bb6d954 testing extra raspi build 2022-05-06 15:07:54 +02:00
axeron2036
d4b6c8da04 Translated using Weblate (Russian)
Currently translated at 80.3% (331 of 412 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/ru/
2022-05-06 06:32:14 +00:00
Tomasz Klimczak
a5ef438cfe Translated using Weblate (Polish)
Currently translated at 100.0% (412 of 412 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2022-05-04 19:32:09 +00:00
vabene1111
de196c716b build test openssl 2022-05-04 20:33:27 +02:00
vabene1111
cb248a1f19 beta build test libressl 2022-05-04 20:33:10 +02:00
vabene1111
df2f1b2b7c testing armv7 build solutuin
taken from https://github.com/healthchecks/healthchecks/issues/568#issuecomment-942047344
2022-05-04 17:18:25 +02:00
vabene1111
36e26d8009 Merge branch 'master' into beta 2022-05-04 17:18:08 +02:00
vabene1111
a5973de02b Merge branch 'develop' 2022-05-04 17:11:35 +02:00
vabene1111
68f272bc25 fixed adding supermarket category to supermarket frontend desync 2022-05-04 15:20:40 +02:00
vabene1111
b66a5c1ee9 Merge branch 'develop' 2022-05-04 15:01:14 +02:00
vabene1111
bfc42638a4 fixed supermarket category ordering 2022-05-04 15:00:39 +02:00
vabene1111
a8c9689b43 fixed ability to disabled auto sync 2022-05-04 14:47:53 +02:00
vabene1111
26ff3f56ea Merge branch 'develop' into beta 2022-05-03 16:58:44 +02:00
vabene1111
a49993e399 testing new cryptography version 2022-05-03 16:58:39 +02:00
Tomasz Klimczak
9f42226224 Translated using Weblate (Polish)
Currently translated at 100.0% (395 of 395 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2022-05-02 22:32:09 +00:00
vabene1111
8f4c00df0b use old property as other sometimes fails 2022-05-02 15:52:15 +02:00
vabene1111
6cebec86c5 Merge branch 'master' into develop 2022-05-02 15:25:47 +02:00
vabene1111
8f5b017857 dont build arm 2022-05-01 21:51:57 +02:00
vabene1111
9915a3eebf Merge branch 'develop' 2022-05-01 13:09:48 +02:00
vabene1111
19c2d3bcf1 shopping description 2022-05-01 13:03:36 +02:00
vabene1111
9259f306ec final importer touches 2022-05-01 12:51:37 +02:00
vabene1111
483bc8f1b7 Merge branch 'develop' into beta 2022-04-29 21:58:13 +02:00
vabene1111
4f33101319 fixed empty step time error 2022-04-29 21:57:05 +02:00
vabene1111
3cef470134 made and compiled messages 2022-04-29 18:42:33 +02:00
vabene1111
ba493e3e19 Merge branch 'develop' into beta 2022-04-25 09:40:04 +02:00
Kaibu
93c53e5fc8 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2022-04-24 12:52:06 +02:00
Kaibu
d931feadf5 supermarkets rework mostly done 2022-04-24 12:52:00 +02:00
vabene1111
fe32ff15b3 another toast fix 2022-04-24 12:46:17 +02:00
vabene1111
a44dea64b8 fixed toast error 2022-04-23 20:55:01 +02:00
Kaibu
54af76e9cf Merge branch 'develop' of https://github.com/vabene1111/recipes into develop
# Conflicts:
#	vue/src/apps/ShoppingListView/ShoppingListView.vue
2022-04-23 20:45:35 +02:00
Kaibu
fcfef255c1 shopping list supermarket rework 2022-04-23 20:44:46 +02:00
vabene1111
2914c20522 added space tier banner 2022-04-23 20:18:10 +02:00
vabene1111
825b7b7cf9 ingredient editor and parser 2022-04-23 19:58:40 +02:00
vabene1111
b9fb78c24d Merge pull request #1739 from ndbeals/develop
Fix image upload handler to use content-type
2022-04-23 19:55:08 +02:00
vabene1111
2fbce7d84d Merge pull request #1734 from Drumstickx/develop
Fix link in German locale
2022-04-23 19:53:47 +02:00
vabene1111
69a23f34b4 updated tests ingredient pagination 2022-04-23 18:54:23 +02:00
vabene1111
9f90306f6c at least basic ui for ingredient editor 2022-04-23 17:13:27 +02:00
vabene1111
1fb6f96571 minor shopping tweaks 2022-04-23 16:51:04 +02:00
vabene1111
0b8dd63510 small fixes 2022-04-23 15:27:21 +02:00
Kaibu
b79bc0d9a8 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2022-04-23 14:47:14 +02:00
Kaibu
8149192455 shopping list and import view ux 2022-04-23 14:47:10 +02:00
vabene1111
66c0cc070a removed old shopping list 2022-04-23 14:43:03 +02:00
vabene1111
e2ab3a0efb fixed ingredient parser length issues 2022-04-23 14:15:06 +02:00
vabene1111
e0b7d1a8f0 added support for unit/amount at end of ingredient 2022-04-23 13:53:04 +02:00
vabene1111
012a1a7915 ingredient parser produces expected results again 2022-04-23 13:03:15 +02:00
Nathan Beals
2af36a3db4 Merge branch 'develop' of github.com:ndbeals/tandoor_recipes into develop 2022-04-23 00:11:08 -04:00
Nathan Beals
8df3009cb2 Update image upload handler to be content-type aware
Update handle_image: made filetype required and not optional
Updated handle_image usage to reflect changes
2022-04-23 00:11:04 -04:00
Kaibu
161ae9879a import app view refactor 2022-04-23 03:02:46 +02:00
vabene1111
71a60a46be Translated using Weblate (German)
Currently translated at 96.8% (372 of 384 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-04-23 00:54:22 +00:00
Kaibu
93acac1f3b Translated using Weblate (German)
Currently translated at 96.8% (372 of 384 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-04-23 00:54:22 +00:00
vabene1111
b4ebd98ee8 ingredient editor paginatio 2022-04-23 02:28:26 +02:00
vabene1111
78c0c5c213 ingredient editor improve merge/delete add edit 2022-04-23 02:17:40 +02:00
vabene1111
30d5587fbe added err msg to all standard toasts 2022-04-23 01:41:08 +02:00
vabene1111
e4223787be updated standard toast function 2022-04-23 01:31:15 +02:00
vabene1111
3850287deb WSL docs 2022-04-23 01:28:56 +02:00
Kaibu
7fae95e248 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2022-04-23 01:28:25 +02:00
Kaibu
b037203b8f ui improvements (shopping and meal plan)
- fixed content scaling for meal plan and shopping
- style fixes on shopping list
- touch based swipe actions for shopping list
- better mobile experience overall
2022-04-23 01:28:20 +02:00
vabene1111
9b132e71f2 screw up ingredient parser 2022-04-23 01:21:13 +02:00
vabene1111
1a21659b5e Merge pull request #1737 from TandoorRecipes/dependabot/pip/django-3.2.13
Bump django from 3.2.12 to 3.2.13
2022-04-23 01:01:40 +02:00
dependabot[bot]
1a1dd092d0 Bump django from 3.2.12 to 3.2.13
Bumps [django](https://github.com/django/django) from 3.2.12 to 3.2.13.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.12...3.2.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-22 22:45:49 +00:00
vabene1111
9adc1f7266 small fixes and tests 2022-04-22 22:27:17 +02:00
vabene1111
6953f763d2 improved source url field rendering 2022-04-22 21:13:00 +02:00
vabene1111
4ecf77f431 Merge branch 'feature/importer_to_vue' into develop
# Conflicts:
#	vue/src/apps/RecipeView/RecipeView.vue
2022-04-22 21:07:02 +02:00
vabene1111
c4f5b160a6 show original text in recipe editor 2022-04-22 21:05:23 +02:00
vabene1111
d8f6dbc58f import list to textarea 2022-04-22 21:00:59 +02:00
vabene1111
8d3747a304 added missing doc entries 2022-04-22 20:30:05 +02:00
vabene1111
1740913a14 improve experience when importing multiple recipes 2022-04-22 20:19:39 +02:00
vabene1111
3cf0395a18 lots of small fixes 2022-04-22 19:26:49 +02:00
Kaibu
42dfc9d126 source url added 2022-04-22 18:53:23 +02:00
Kaibu
d7bd731c73 minor ui fix in recipe view 2022-04-22 17:43:23 +02:00
Kaibu
9e86abb004 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2022-04-22 17:33:33 +02:00
Kaibu
dc8ce0f6a4 recipe image max-width based on ingredient table 2022-04-22 17:33:27 +02:00
vabene1111
2ddb0c719a Merge branch 'develop' into feature/importer_to_vue
# Conflicts:
#	vue/src/apps/RecipeEditView/RecipeEditView.vue
#	vue/src/utils/openapi/api.ts
2022-04-22 16:41:13 +02:00
Tomasz Klimczak
05383a2bc3 Translated using Weblate (Polish)
Currently translated at 100.0% (384 of 384 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2022-04-21 19:14:53 +00:00
Drumstickx
48c0252893 Fix link in German locale 2022-04-21 18:51:38 +02:00
Tomasz Klimczak
82fd6f1860 Translated using Weblate (Polish)
Currently translated at 100.0% (383 of 383 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2022-04-19 04:18:02 +00:00
Kaibu
694022506d Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2022-04-18 14:13:30 +02:00
Kaibu
45a86a22e3 recipe switcher and navbar fixes
also added left_hand to global preferences
2022-04-18 14:13:23 +02:00
vabene1111
1100826ed8 fixed NC importer importing empty keywords 2022-04-18 12:52:32 +02:00
vabene1111
d1065c8ac4 Merge pull request #1710 from hendrikbl/feature/navbar-tweaks
Navbar tweaks
2022-04-18 12:37:45 +02:00
vabene1111
2fdd9edde1 Merge pull request #1731 from parkroland/enhancement/clickable-keywords-recipe-card
Add clickable keywords to recipe card
2022-04-18 12:33:10 +02:00
Roland Park
a84ab0c049 Add clickable keywords to recipe card 2022-04-17 19:56:36 -04:00
vabene1111
d9dd0a594e show recipe and allow delete in ingredient editor 2022-04-17 23:25:22 +02:00
vabene1111
f0d59a8c9c added ability to open ingredient editor from food/unit list 2022-04-17 22:43:33 +02:00
vabene1111
d50fb69ce9 fixed errro message in meal plan when adding notes with add to shopping 2022-04-17 15:48:18 +02:00
vabene1111
8bc13fc91f fixed env template email settings 2022-04-17 15:35:41 +02:00
vabene1111
2ce06a8154 fixed too small fractions dissappearing 2022-04-17 15:35:32 +02:00
vabene1111
0a0c0b069f fixed space management page template error 2022-04-17 15:03:50 +02:00
vabene1111
47b62aa390 Merge pull request #1714 from gloriousDan/docs_nginx_read_only
Docs: nginx mount volumes read-only
2022-04-17 14:59:57 +02:00
vabene1111
9a2f91d3d4 Merge pull request #1709 from gloriousDan/develop
Docs: Reintroduce restart-always to web_recipes service
2022-04-17 14:58:55 +02:00
vabene1111
2df940ee40 improved rezkonv importer 2022-04-17 14:55:30 +02:00
Oskar Stenberg
67a5d8f1bd Translated using Weblate (Swedish)
Currently translated at 100.0% (371 of 371 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/sv/
2022-04-17 00:32:01 +00:00
vabene1111
297a8d4c8b ingredient editor basics done 2022-04-14 22:45:31 +02:00
vabene1111
976bce5fdd add merge capability to ingredient editor 2022-04-14 22:10:48 +02:00
vabene1111
8c89438b97 allow delete in ingredient editor 2022-04-14 14:40:15 +02:00
vabene1111
7ca7bd6111 improve generic form delete 2022-04-14 14:31:34 +02:00
vabene1111
3159868ba4 moved generic multiselect create function into component 2022-04-14 14:08:16 +02:00
vabene1111
7befa4a084 added basic ingredient editor 2022-04-14 13:01:27 +02:00
vabene1111
2ee96c2ea4 docs run on master, update contrib. docs 2022-04-14 08:53:16 +02:00
vabene1111
74b67e5549 Merge pull request #1719 from tristanlins/develop
Remove namespace vom k8s templates
2022-04-14 08:40:51 +02:00
vabene1111
1e24161d4c Merge pull request #1711 from Makanz/add-swedish-language-support
Add swedish language support
2022-04-14 08:39:29 +02:00
Tristan Lins
a839fb0bfc Remove namespace vom k8s templates 2022-04-12 20:43:58 +02:00
cesar ferreira
46267a135b Translated using Weblate (Portuguese)
Currently translated at 7.8% (30 of 381 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt/
2022-04-12 18:32:03 +00:00
Tomasz Klimczak
f7ab0400a3 Translated using Weblate (Polish)
Currently translated at 100.0% (381 of 381 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2022-04-12 18:32:02 +00:00
Marcus Alsterfjord
74863117c5 Translated using Weblate (Swedish)
Currently translated at 100.0% (381 of 381 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sv/
2022-04-12 18:32:01 +00:00
Marcus Alsterfjord
e872272fbd Translated using Weblate (Swedish)
Currently translated at 100.0% (371 of 371 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/sv/
2022-04-12 18:32:00 +00:00
Daniel
9ae7d591cc Merge branch 'TandoorRecipes:develop' into docs_nginx_read_only 2022-04-10 20:46:46 +02:00
Daniel Schulz
c3c697f4a8 Mount all volumes in nginx read-only 2022-04-10 20:45:34 +02:00
Tomasz Klimczak
60e8b95593 Translated using Weblate (Polish)
Currently translated at 88.1% (336 of 381 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2022-04-10 09:51:32 +00:00
Marcus Alsterfjord
1636710099 Translated using Weblate (Swedish)
Currently translated at 61.7% (229 of 371 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/sv/
2022-04-10 09:51:31 +00:00
Rubens
4296c3d136 Translated using Weblate (Catalan)
Currently translated at 96.4% (542 of 562 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ca/
2022-04-10 09:51:31 +00:00
Marcus Alsterfjord
bcda5eea93 Update CONTRIBUTERS.md 2022-04-09 16:52:18 +02:00
Marcus Alsterfjord
a63ede0e3a Add swedish support in frontend ui and in search 2022-04-09 16:51:16 +02:00
hendrikbl
a9414065b5 changed navbar logo size and order 2022-04-09 16:15:10 +02:00
Daniel Schulz
fa79adf931 Reintroduce restart-always to web_recipes service 2022-04-09 14:56:00 +02:00
Marcus Alsterfjord
cd5f752d26 Translated using Weblate (Swedish)
Currently translated at 85.8% (327 of 381 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sv/
2022-04-08 22:32:07 +00:00
Rubens
6a41b182f5 Translated using Weblate (Catalan)
Currently translated at 79.8% (449 of 562 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ca/
2022-04-08 22:32:07 +00:00
vabene1111
0011ce26d3 Merge pull request #1705 from amillerr/patch-1
Update CONTRIBUTERS.md
2022-04-08 08:03:29 +02:00
Artem Aksenov
1ef92df83c Translated using Weblate (Russian)
Currently translated at 8.8% (44 of 496 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ru/
2022-04-07 19:32:01 +00:00
Artem Aksenov
3e8ef33402 Translated using Weblate (Russian)
Currently translated at 54.3% (207 of 381 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/ru/
2022-04-07 19:32:00 +00:00
Rubens
4d4c3bea92 Translated using Weblate (Catalan)
Currently translated at 56.5% (318 of 562 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ca/
2022-04-07 19:32:00 +00:00
Artyom Aksyonov
9ecbfb0655 Update CONTRIBUTERS.md 2022-04-07 21:58:39 +03:00
Jesse
944492168e Translated using Weblate (Dutch)
Currently translated at 100.0% (378 of 378 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nl/
2022-04-05 10:32:03 +00:00
Jesse
1c39befa0f Translated using Weblate (Dutch)
Currently translated at 100.0% (562 of 562 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/nl/
2022-04-05 10:32:03 +00:00
vabene1111
57ec6a2b3d import servings text 2022-04-04 23:21:13 +02:00
vabene1111
3653d6b911 added source url to nextcloud cookbook 2022-04-04 22:55:00 +02:00
Kaibu
82c2cc0f40 ui improvements 2022-04-04 22:53:26 +02:00
vabene1111
48e9f3f8a9 added cookmate importer 2022-04-04 22:49:50 +02:00
vabene1111
12865437d7 copy me that improvements 2022-04-04 21:44:51 +02:00
vabene1111
090e18e405 paprika importer improvements 2022-04-04 21:30:00 +02:00
vabene1111
7db49b1528 Merge pull request #1698 from HarHarLinks/patch-1
fix links in german locale
2022-04-04 21:16:06 +02:00
vabene1111
85aad42529 added mela recipes importer 2022-04-04 21:09:47 +02:00
Kim Brose
9c254be4b5 fix links in german locale 2022-04-04 20:34:01 +02:00
vabene1111
5bd9a15e4b small fixes 2022-04-04 20:11:22 +02:00
vabene1111
3cedab45ee fixed copy recipe nutrition link 2022-04-04 19:45:37 +02:00
vabene1111
56f3fe2d12 fixed deprecated model attribute on exporters 2022-04-04 19:27:14 +02:00
vabene1111
a2954554b5 fixed description length limit 2022-04-04 19:26:47 +02:00
vabene1111
528ada7d32 Merge branch 'develop' into feature/importer_to_vue
# Conflicts:
#	vue/package.json
2022-04-04 19:16:20 +02:00
vabene1111
b7e6e7b1b0 fixed s3 check 2022-04-04 19:15:11 +02:00
vabene1111
e17da08a74 Merge pull request #1679 from TandoorRecipes/dependabot/pip/jinja2-3.1.1
Bump jinja2 from 3.0.3 to 3.1.1
2022-04-04 19:07:34 +02:00
vabene1111
32cedf1078 Merge pull request #1680 from TandoorRecipes/dependabot/pip/boto3-1.21.31
Bump boto3 from 1.21.28 to 1.21.31
2022-04-04 19:07:29 +02:00
vabene1111
60bb3fd4aa Merge pull request #1633 from smilerz/recipe_as_food
allow marking recipe as food
2022-04-04 19:06:10 +02:00
dependabot[bot]
f421990ae0 Bump jinja2 from 3.0.3 to 3.1.1
Bumps [jinja2](https://github.com/pallets/jinja) from 3.0.3 to 3.1.1.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.0.3...3.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 17:05:40 +00:00
vabene1111
f9333d2b82 Merge pull request #1681 from TandoorRecipes/dependabot/pip/recipe-scrapers-13.25.0
Bump recipe-scrapers from 13.19.0 to 13.25.0
2022-04-04 19:04:58 +02:00
vabene1111
dfa5475ecb Merge pull request #1690 from kettenbach-it/develop
Get image from S3-storage if configured
2022-04-04 19:02:35 +02:00
Volker Kettenbach
b6e5425bd3 Get image from S3-Storage if configured 2022-04-02 11:35:35 +02:00
dependabot[bot]
1b7347f1d9 Bump recipe-scrapers from 13.19.0 to 13.25.0
Bumps [recipe-scrapers](https://github.com/hhursev/recipe-scrapers) from 13.19.0 to 13.25.0.
- [Release notes](https://github.com/hhursev/recipe-scrapers/releases)
- [Commits](https://github.com/hhursev/recipe-scrapers/compare/13.19.0...13.25.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-01 00:04:59 +00:00
dependabot[bot]
2ef23d2cb3 Bump boto3 from 1.21.28 to 1.21.31
Bumps [boto3](https://github.com/boto/boto3) from 1.21.28 to 1.21.31.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.21.28...1.21.31)

---
updated-dependencies:
- dependency-name: boto3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-01 00:04:51 +00:00
Lucas Declercq
bba81f6594 Translated using Weblate (French)
Currently translated at 87.3% (330 of 378 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2022-03-31 06:01:57 +00:00
Marcus Alsterfjord
3a4f08f2f7 Translated using Weblate (Swedish)
Currently translated at 57.6% (218 of 378 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sv/
2022-03-31 06:01:56 +00:00
Marcus Alsterfjord
f8ad465113 Translated using Weblate (Swedish)
Currently translated at 55.0% (208 of 378 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sv/
2022-03-29 20:36:24 +00:00
Marcus Alsterfjord
6df993ce29 Translated using Weblate (Swedish)
Currently translated at 54.7% (203 of 371 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/sv/
2022-03-29 20:36:24 +00:00
Adrian M
6009eae42d Translated using Weblate (Hungarian)
Currently translated at 100.0% (568 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2022-03-29 20:36:24 +00:00
vabene1111
7bed9963ff fixed vue cli pwa version and admin comment search 2022-03-28 22:56:45 +02:00
vabene1111
a0610ac05f Merge pull request #1676 from TandoorRecipes/dependabot/npm_and_yarn/vue/vue/cli-plugin-eslint-5.0.4
Bump @vue/cli-plugin-eslint from 4.5.15 to 5.0.4 in /vue
2022-03-28 22:15:58 +02:00
dependabot[bot]
afd063a2b9 Bump @vue/cli-plugin-eslint from 4.5.15 to 5.0.4 in /vue
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.15 to 5.0.4.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v5.0.4/packages/@vue/cli-plugin-eslint)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-eslint"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 20:01:08 +00:00
vabene1111
6b92dcbb2a Merge pull request #1606 from TandoorRecipes/dependabot/npm_and_yarn/vue/workbox-routing-6.5.0
Bump workbox-routing from 6.4.2 to 6.5.0 in /vue
2022-03-28 21:59:22 +02:00
vabene1111
12af99f546 Merge pull request #1668 from TandoorRecipes/dependabot/pip/cryptography-36.0.2
Bump cryptography from 36.0.1 to 36.0.2
2022-03-28 21:59:08 +02:00
vabene1111
68501d646d Merge pull request #1675 from TandoorRecipes/dependabot/npm_and_yarn/vue/axios-0.26.1
Bump axios from 0.24.0 to 0.26.1 in /vue
2022-03-28 21:58:52 +02:00
vabene1111
d215d236f0 Merge pull request #1669 from TandoorRecipes/dependabot/pip/boto3-1.21.28
Bump boto3 from 1.20.47 to 1.21.28
2022-03-28 21:58:41 +02:00
dependabot[bot]
459cf79ef3 Bump axios from 0.24.0 to 0.26.1 in /vue
Bumps [axios](https://github.com/axios/axios) from 0.24.0 to 0.26.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.24.0...v0.26.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:58:40 +00:00
dependabot[bot]
1d357eca4e Bump cryptography from 36.0.1 to 36.0.2
Bumps [cryptography](https://github.com/pyca/cryptography) from 36.0.1 to 36.0.2.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/36.0.1...36.0.2)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:58:38 +00:00
vabene1111
ca8a7c3bc9 Merge pull request #1626 from TandoorRecipes/dependabot/pip/whitenoise-6.0.0
Bump whitenoise from 5.3.0 to 6.0.0
2022-03-28 21:58:30 +02:00
vabene1111
3b936eca3f Merge pull request #1674 from TandoorRecipes/dependabot/pip/python-dotenv-0.20.0
Bump python-dotenv from 0.19.2 to 0.20.0
2022-03-28 21:58:18 +02:00
vabene1111
2f06e9bc1c Merge pull request #1673 from TandoorRecipes/dependabot/pip/django-autocomplete-light-3.9.4
Bump django-autocomplete-light from 3.8.2 to 3.9.4
2022-03-28 21:57:25 +02:00
dependabot[bot]
e25c0705c6 Bump python-dotenv from 0.19.2 to 0.20.0
Bumps [python-dotenv](https://github.com/theskumar/python-dotenv) from 0.19.2 to 0.20.0.
- [Release notes](https://github.com/theskumar/python-dotenv/releases)
- [Changelog](https://github.com/theskumar/python-dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/theskumar/python-dotenv/compare/v0.19.2...v0.20.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:57:19 +00:00
vabene1111
d4e9526c75 Merge pull request #1670 from TandoorRecipes/dependabot/npm_and_yarn/vue/minimist-1.2.6
Bump minimist from 1.2.5 to 1.2.6 in /vue
2022-03-28 21:56:52 +02:00
dependabot[bot]
2e2e81638b Bump django-autocomplete-light from 3.8.2 to 3.9.4
Bumps [django-autocomplete-light](https://github.com/yourlabs/django-autocomplete-light) from 3.8.2 to 3.9.4.
- [Release notes](https://github.com/yourlabs/django-autocomplete-light/releases)
- [Changelog](https://github.com/yourlabs/django-autocomplete-light/blob/master/CHANGELOG)
- [Commits](https://github.com/yourlabs/django-autocomplete-light/compare/3.8.2...3.9.4)

---
updated-dependencies:
- dependency-name: django-autocomplete-light
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:56:46 +00:00
vabene1111
baf5c9700f Merge pull request #1671 from TandoorRecipes/dependabot/pip/django-allauth-0.50.0
Bump django-allauth from 0.47.0 to 0.50.0
2022-03-28 21:56:39 +02:00
dependabot[bot]
dff7daefc7 Bump django-allauth from 0.47.0 to 0.50.0
Bumps [django-allauth](https://github.com/pennersr/django-allauth) from 0.47.0 to 0.50.0.
- [Release notes](https://github.com/pennersr/django-allauth/releases)
- [Changelog](https://github.com/pennersr/django-allauth/blob/master/ChangeLog.rst)
- [Commits](https://github.com/pennersr/django-allauth/compare/0.47.0...0.50.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:56:33 +00:00
vabene1111
7e27d704ca Merge pull request #1672 from TandoorRecipes/dependabot/pip/pytest-7.1.1
Bump pytest from 7.0.1 to 7.1.1
2022-03-28 21:56:27 +02:00
vabene1111
9722f22837 Merge pull request #1604 from TandoorRecipes/dependabot/npm_and_yarn/vue/vue/cli-plugin-pwa-5.0.1
Bump @vue/cli-plugin-pwa from 4.5.15 to 5.0.1 in /vue
2022-03-28 21:56:09 +02:00
dependabot[bot]
707a12f8c1 Bump pytest from 7.0.1 to 7.1.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.0.1 to 7.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.0.1...7.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:55:38 +00:00
vabene1111
b9b8864631 Merge pull request #1603 from TandoorRecipes/dependabot/npm_and_yarn/vue/popperjs/core-2.11.2
Bump @popperjs/core from 2.11.0 to 2.11.2 in /vue
2022-03-28 21:55:37 +02:00
vabene1111
31bdc0589e Merge pull request #1602 from TandoorRecipes/dependabot/pip/lxml-4.8.0
Bump lxml from 4.7.1 to 4.8.0
2022-03-28 21:55:26 +02:00
dependabot[bot]
cb29caf88c Bump whitenoise from 5.3.0 to 6.0.0
Bumps [whitenoise](https://github.com/evansd/whitenoise) from 5.3.0 to 6.0.0.
- [Release notes](https://github.com/evansd/whitenoise/releases)
- [Changelog](https://github.com/evansd/whitenoise/blob/master/docs/changelog.rst)
- [Commits](https://github.com/evansd/whitenoise/compare/v5.3.0...6.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:55:05 +00:00
dependabot[bot]
dd044eba36 Bump minimist from 1.2.5 to 1.2.6 in /vue
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:54:50 +00:00
dependabot[bot]
b8518884b0 Bump boto3 from 1.20.47 to 1.21.28
Bumps [boto3](https://github.com/boto/boto3) from 1.20.47 to 1.21.28.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.20.47...1.21.28)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 19:54:47 +00:00
vabene1111
ed20a54137 Merge pull request #1601 from TandoorRecipes/dependabot/pip/django-allauth-0.49.0
Bump django-allauth from 0.47.0 to 0.49.0
2022-03-28 21:54:30 +02:00
vabene1111
7781bf1444 Merge pull request #1598 from TandoorRecipes/dependabot/pip/pytest-7.0.1
Bump pytest from 6.2.5 to 7.0.1
2022-03-28 21:54:16 +02:00
vabene1111
14db4179b9 Merge pull request #1660 from MaxJa4/patch-1
Add POSTGRES_USER to psql health check during boot
2022-03-28 21:53:27 +02:00
Adrian M
37eab3ece2 Translated using Weblate (Hungarian)
Currently translated at 57.3% (326 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2022-03-28 01:56:10 +00:00
Adrian M
768b483351 Translated using Weblate (Hungarian)
Currently translated at 12.1% (69 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2022-03-27 18:00:28 +00:00
MaxJa4
59d277da3d Add POSTGRES_USER to psql health check during boot
Add POSTGRES_USER to psql health check during boot to support external psql instances better.

Fixes #1656
2022-03-20 00:08:41 +01:00
Stefan Werner
f68fd0fa94 Translated using Weblate (Finnish)
Currently translated at 56.3% (213 of 378 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fi/
2022-03-18 16:31:49 +00:00
Stefan Werner
dd1fcc21e0 Translated using Weblate (Finnish)
Currently translated at 3.2% (16 of 493 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fi/
2022-03-18 16:31:49 +00:00
vabene1111
f445722140 Merge pull request #1653 from bradpoulton/develop
Fixes the formatting
2022-03-17 20:46:41 +01:00
brad
a3def6bf4c Fixes the formatting 2022-03-16 22:00:42 -06:00
Adrian M
cbd2ac2032 Translated using Weblate (Hungarian)
Currently translated at 5.6% (32 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2022-03-16 22:31:47 +00:00
vabene1111
1d3d4e78f5 Merge branch 'develop' 2022-03-16 14:27:11 +01:00
vabene1111
0c841ec686 another improvement to shopping list item 2022-03-16 09:21:09 +01:00
ivo
f875942e79 Translated using Weblate (Portuguese)
Currently translated at 1.0% (4 of 378 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt/
2022-03-15 19:31:47 +00:00
vabene1111
e901c6708c Merge branch 'develop' into feature/importer_to_vue 2022-03-15 13:02:10 +01:00
vabene1111
c5863a5309 Merge branch 'develop' 2022-03-15 13:01:59 +01:00
vabene1111
4cf8b72e3f removed OT from sle 2022-03-15 12:50:41 +01:00
vabene1111
4dd3ba29b6 improved shopping v2 layout a little bit 2022-03-15 12:35:13 +01:00
vabene1111
96bd66f9e6 fixed telegram bot 2022-03-15 11:48:12 +01:00
vabene1111
70716bf99f Merge pull request #1643 from MaxJa4/patch-1
Updated dependencies of manual setup
2022-03-15 11:35:33 +01:00
vabene1111
16449cd078 Merge pull request #1644 from gloriousDan/develop
Update bind mounts in docker run command to use absolute paths
2022-03-15 11:34:40 +01:00
vabene1111
5459e293d1 Merge pull request #1645 from smilerz/fix_sql_debug
fix sql debug button in search
2022-03-15 11:33:23 +01:00
vabene1111
749713d698 Merge pull request #1646 from bradpoulton/develop
Updates Docker installation docs
2022-03-15 11:32:24 +01:00
ivo
4a5af48f33 Added translation using Weblate (Portuguese) 2022-03-14 18:51:14 +00:00
brad
5cf58a32dc Updates formating 2022-03-11 18:19:48 -07:00
brad
a956888355 Fixes wording 2022-03-11 18:18:09 -07:00
brad
cb835b033c Updates Docker installation docs
Adds warning that the jwilder nginx-proxy reduces file size upload to 1 MB.
2022-03-11 18:16:32 -07:00
smilerz
b9289e2685 fix sql debug button in search 2022-03-11 07:27:42 -06:00
Daniel
c0bd0d49ae Update bind mounts to use absolute paths
Docker bind mounts have to use absolute paths, so the docker run command fails when using the relative mounts ./staticfiles and ./mediafiles.
This may be supported again (https://github.com/docker/cli/issues/1203)
2022-03-11 13:40:59 +01:00
MaxJa4
36fbbed1b0 Added link to docs of nodejs installation 2022-03-11 10:21:50 +01:00
MaxJa4
34f70e4ba7 Fixed formatting 2022-03-11 10:18:51 +01:00
MaxJa4
8bc361ee7c Updated dependencies of manual setup
- apt install of nodejs installs an unsupported (V10.X) version
- dependencies for python-ldap were missing
2022-03-11 10:16:55 +01:00
vabene1111
7426bb4e76 auto import multiple urls 2022-03-10 17:35:11 +01:00
vabene1111
92b536b32c check login remember by default 2022-03-10 16:10:33 +01:00
vabene1111
5627161c5e Merge branch 'develop' into feature/importer_to_vue 2022-03-10 15:27:11 +01:00
vabene1111
091fab154a improved openid and social auth pages 2022-03-10 15:24:13 +01:00
vabene1111
c6e11f6ef2 Merge pull request #1640 from CameronJGrant/develop
Fixed typos and grammatical issues.
2022-03-10 14:43:16 +01:00
vabene1111
16b5cd75b1 Merge pull request #1641 from m42e/feature/markdown-img-tag
Allow img tag (including width/height attribute)
2022-03-10 14:41:31 +01:00
Matthias Bilger
f040b491d4 Allow img tag (including width/height attribute)
Allow using img tag in markdown and additionally allowing to specify
width and height attribute for elements.
2022-03-10 11:38:08 +01:00
karawedi
8174da31e8 Translated using Weblate (German)
Currently translated at 95.1% (535 of 562 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2022-03-09 18:31:44 +00:00
Cameron Grant
53518f4c47 Fixed typos and grammatical issues. 2022-03-08 12:12:20 -08:00
Felipe Castro
693d829946 Translated using Weblate (Portuguese (Brazil))
Currently translated at 3.0% (17 of 562 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/pt_BR/
2022-03-08 01:31:43 +00:00
Felipe Castro
5ab11eb1bc Translated using Weblate (Portuguese (Brazil))
Currently translated at 0.5% (2 of 378 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt_BR/
2022-03-08 01:31:43 +00:00
smilerz
486d197854 allow marking recipe as food 2022-03-06 23:12:59 -06:00
Felipe Castro
332f518774 Added translation using Weblate (Portuguese (Brazil)) 2022-03-07 01:00:09 +00:00
Felipe Castro
ed33114947 Added translation using Weblate (Portuguese (Brazil)) 2022-03-07 00:56:04 +00:00
Kaibu
aeb38cd2e9 Merge branch 'develop-weblate' into develop
# Conflicts:
#	cookbook/locale/de/LC_MESSAGES/django.po
#	cookbook/locale/hu_HU/LC_MESSAGES/django.po
#	vue/src/locales/de.json
2022-03-06 20:45:35 +01:00
Adrian M
17cf5f48a1 Translated using Weblate (Hungarian)
Currently translated at 2.9% (17 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2022-03-06 19:35:42 +00:00
vabene1111
22ca482458 super very basics of manual mapping page working 2022-03-05 16:02:42 +01:00
vabene1111
2565ab30a4 lots of improvements and bookmarklet import working again 2022-03-05 15:16:58 +01:00
vabene1111
1caabef56a step functions 2022-03-04 16:54:59 +01:00
vabene1111
edde8c8b8f Merge branch 'develop' 2022-03-04 15:54:16 +01:00
vabene1111
6d8fe3c162 wip 2022-03-04 15:54:11 +01:00
vabene1111
bdccdf0893 Merge branch 'develop' into feature/importer_to_vue
# Conflicts:
#	cookbook/helper/recipe_url_import.py
2022-03-04 14:33:59 +01:00
dependabot[bot]
f0927bf065 Bump django-allauth from 0.47.0 to 0.49.0
Bumps [django-allauth](https://github.com/pennersr/django-allauth) from 0.47.0 to 0.49.0.
- [Release notes](https://github.com/pennersr/django-allauth/releases)
- [Changelog](https://github.com/pennersr/django-allauth/blob/master/ChangeLog.rst)
- [Commits](https://github.com/pennersr/django-allauth/compare/0.47.0...0.49.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-04 13:30:25 +00:00
dependabot[bot]
ed1fb9a95e Bump pytest from 6.2.5 to 7.0.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.5 to 7.0.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.5...7.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-04 13:30:07 +00:00
vabene1111
c950e6dabb Merge pull request #1625 from TandoorRecipes/dependabot/pip/recipe-scrapers-13.19.0
Bump recipe-scrapers from 13.18.0 to 13.19.0
2022-03-04 14:29:18 +01:00
vabene1111
e27a64f52c Merge pull request #1623 from gloriousDan/develop
Improve recipe import for non schema.org recipes
2022-03-04 14:28:34 +01:00
vabene1111
f02b6f29db Merge pull request #1620 from ratheile/ratheile-patch-boot-nonstandard-ports
Update boot.sh
2022-03-04 14:27:31 +01:00
dependabot[bot]
a3ba516587 Bump recipe-scrapers from 13.18.0 to 13.19.0
Bumps [recipe-scrapers](https://github.com/hhursev/recipe-scrapers) from 13.18.0 to 13.19.0.
- [Release notes](https://github.com/hhursev/recipe-scrapers/releases)
- [Commits](https://github.com/hhursev/recipe-scrapers/compare/13.18.0...13.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-04 13:27:30 +00:00
vabene1111
a15f5895f5 Merge pull request #1622 from MaxJa4/fix/ldap_dockerfile
Added ldap as runtime dependency to Dockerfile
2022-03-04 14:27:01 +01:00
vabene1111
c6e36b802c Merge pull request #1617 from smilerz/fix_sqlite_search
remove unaccent from sqlite search
2022-03-04 14:26:32 +01:00
vabene1111
f91ca28638 Merge pull request #1611 from smilerz/missing_preptime
missing prepTime assignment
2022-03-04 14:26:21 +01:00
Daniel Schulz
cfcf354d59 Improve recipe import for non schema.org recipes 2022-03-03 23:47:50 +01:00
MaxJa4
6813077113 Added ldap as runtime dependency to Dockerfile 2022-03-03 22:27:41 +01:00
Raffael Theiler
581ee762b6 Update boot.sh
Add port to pg_isready to allow non-standard ports.
2022-03-03 19:27:51 +01:00
smilerz
08c1a8f2ab fix loading children in treeselect 2022-03-02 14:56:33 -06:00
smilerz
ba25e463ad added uritemplate requirement back 2022-03-02 10:13:40 -06:00
smilerz
f2211da9bb remove unaccent from sqlite search 2022-03-02 09:42:10 -06:00
vabene1111
030d977a8c Merge branch 'develop' 2022-03-02 13:11:57 +01:00
vabene1111
8d3419952c movbed pg password check 2022-03-02 13:11:52 +01:00
vabene1111
8010ee3dca logical fix 2022-03-02 12:22:54 +01:00
vabene1111
0f3d82a5e6 fixing boot script 2022-03-02 12:22:12 +01:00
vabene1111
5e67e735db Merge branch 'beta' into develop 2022-03-02 12:17:40 +01:00
vabene1111
f9f6ca05a4 Merge pull request #1612 from smilerz/mealplan_modal_shopping
trigger shopping modal
2022-03-02 09:43:46 +01:00
vabene1111
d7379d8ab6 testing with setuptools_rust 2022-03-02 09:39:54 +01:00
vabene1111
51f44e4926 testing with py dev 2022-03-02 09:37:11 +01:00
vabene1111
447a16dcd5 re enabled disabled architectures 2022-03-02 09:28:28 +01:00
vabene1111
f15922ceb5 testing cryptography builds with rustc 2022-03-02 09:25:29 +01:00
vabene1111
a5cc218b56 Merge branch 'develop' into beta 2022-03-02 09:24:09 +01:00
vabene1111
640d7305c7 Merge branch 'master' into develop 2022-03-02 09:24:02 +01:00
vabene1111
fdf98932e2 exchanged deprecated vars 2022-03-02 09:20:35 +01:00
vabene1111
29e44e7101 dont build arm v7 2022-03-02 08:38:42 +01:00
smilerz
2993c7e688 trigger shopping modal 2022-03-01 17:17:35 -06:00
smilerz
d6db3fe65b missing prepTime assignment 2022-03-01 16:31:18 -06:00
vabene1111
36099b80ab docker dont pip install cryptography
dont install cryptography wheel in alpine docker build as py-cryptography already takes care of this.
2022-03-01 19:50:31 +01:00
vabene1111
9a795a7f60 docker dont pip install cryptography
dont install cryptography wheel in alpine docker build as py-cryptography already takes care of this.
2022-03-01 19:50:17 +01:00
vabene1111
7ef67cdadd Merge branch 'develop' 2022-03-01 16:37:03 +01:00
vabene1111
55539c83c9 fixed supermarket category creation 2022-03-01 16:26:36 +01:00
vabene1111
c5df241ec3 Merge pull request #1597 from MaxJa4/improvement/multiselect_localization
Multiselect controls are now fully localized in RecipeEditView
2022-03-01 15:55:35 +01:00
vabene1111
8ea882e5b3 Merge branch 'develop' into improvement/multiselect_localization 2022-03-01 15:55:27 +01:00
vabene1111
aaecd479ad Merge pull request #1594 from MaxJa4/improvement/minor_translation_fixes
Added a few more strings to be localized and fixed one ui alignment
2022-03-01 15:54:48 +01:00
vabene1111
65432895ba Merge branch 'develop' into improvement/minor_translation_fixes 2022-03-01 15:54:44 +01:00
vabene1111
b730acc06a Merge pull request #1596 from MaxJa4/improvement/select_amount
Auto selects amount of ingredient when adding new ingredient.
2022-03-01 15:52:10 +01:00
vabene1111
6b430abe3a Merge pull request #1591 from MaxJa4/improvement/ux_improv
Optimized advanced search settings UX
2022-03-01 15:51:11 +01:00
dependabot[bot]
5f25df7d19 Bump workbox-routing from 6.4.2 to 6.5.0 in /vue
Bumps [workbox-routing](https://github.com/googlechrome/workbox) from 6.4.2 to 6.5.0.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.4.2...v6.5.0)

---
updated-dependencies:
- dependency-name: workbox-routing
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-01 00:12:01 +00:00
dependabot[bot]
e55f78c767 Bump @vue/cli-plugin-pwa from 4.5.15 to 5.0.1 in /vue
Bumps [@vue/cli-plugin-pwa](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-pwa) from 4.5.15 to 5.0.1.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v5.0.1/packages/@vue/cli-plugin-pwa)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-pwa"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-01 00:10:36 +00:00
dependabot[bot]
6d257d2455 Bump @popperjs/core from 2.11.0 to 2.11.2 in /vue
Bumps [@popperjs/core](https://github.com/popperjs/popper-core) from 2.11.0 to 2.11.2.
- [Release notes](https://github.com/popperjs/popper-core/releases)
- [Commits](https://github.com/popperjs/popper-core/compare/v2.11.0...v2.11.2)

---
updated-dependencies:
- dependency-name: "@popperjs/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-01 00:09:44 +00:00
dependabot[bot]
693a5214ef Bump lxml from 4.7.1 to 4.8.0
Bumps [lxml](https://github.com/lxml/lxml) from 4.7.1 to 4.8.0.
- [Release notes](https://github.com/lxml/lxml/releases)
- [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt)
- [Commits](https://github.com/lxml/lxml/compare/lxml-4.7.1...lxml-4.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-01 00:03:39 +00:00
MaxJa4
cebd47a639 Fixed json format after merge 2022-02-28 21:21:06 +01:00
MaxJa4
1e3a6fadf0 More localization of recipe search and view 2022-02-28 21:19:00 +01:00
MaxJa4
47723673d0 Multiselect controls are now fully localized in RecipeEditView 2022-02-28 20:28:41 +01:00
MaxJa4
429d381f63 Auto selects amount of ingredient when adding new ingredient. 2022-02-28 19:43:37 +01:00
MaxJa4
b393d026f7 Added a few more strings to be localized and fixed one ui alignment 2022-02-27 22:40:03 +01:00
MaxJa4
09804de809 Optimized advanced search settings UX 2022-02-27 21:53:22 +01:00
vabene1111
9ecb087cd6 Merge branch 'develop' into beta 2022-02-27 12:37:26 +01:00
vabene1111
089e634d69 fixed mobile emoji select 2022-02-27 11:39:24 +01:00
vabene1111
028ee4a861 fixed file filter regex for importers 2022-02-27 11:37:12 +01:00
vabene1111
561c2106ce fixed nextcloud import first item 2022-02-27 11:27:23 +01:00
vabene1111
429607e1fe fixed shoppoing v2 list container size 2022-02-27 11:07:06 +01:00
vabene1111
802242f54e Merge pull request #1586 from smilerz/genericmodal_translations
fix translations in helper libraries models.js and utils.js
2022-02-27 09:50:37 +01:00
vabene1111
cd58b6681b Merge pull request #1588 from TandoorRecipes/dependabot/npm_and_yarn/vue/url-parse-1.5.10
Bump url-parse from 1.5.7 to 1.5.10 in /vue
2022-02-26 17:37:00 +01:00
dependabot[bot]
c7f5975c22 Bump url-parse from 1.5.7 to 1.5.10 in /vue
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.7 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.7...1.5.10)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-26 09:30:47 +00:00
vabene1111
03e32dba90 Merge pull request #1587 from TandoorRecipes/dependabot/npm_and_yarn/vue/prismjs-1.27.0
Bump prismjs from 1.25.0 to 1.27.0 in /vue
2022-02-26 10:30:09 +01:00
dependabot[bot]
739c2ecc53 Bump prismjs from 1.25.0 to 1.27.0 in /vue
Bumps [prismjs](https://github.com/PrismJS/prism) from 1.25.0 to 1.27.0.
- [Release notes](https://github.com/PrismJS/prism/releases)
- [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PrismJS/prism/compare/v1.25.0...v1.27.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-26 02:26:31 +00:00
smilerz
56c553c35d load language_code to new shopping list 2022-02-25 13:52:56 -06:00
smilerz
dae49ec5f3 fix translations in helper libraries models.js and utils.js 2022-02-25 13:16:34 -06:00
vabene1111
90d477a0fd small change to be able to retain large texts 2022-02-25 16:19:49 +01:00
vabene1111
fc6268b7ff Merge pull request #1564 from smilerz/retain_original_ingredient_text
retain original text when parsing ingredients
2022-02-25 16:17:44 +01:00
vabene1111
425a38f030 Merge pull request #1584 from smilerz/fix_duplicate_entry
return distinct shopping entries
2022-02-25 16:15:41 +01:00
vabene1111
d94e0523b0 Merge pull request #1582 from MaxJa4/fix/member_count
[PR cleanup] Add translations as in #1580
2022-02-25 15:52:09 +01:00
vabene1111
e824c9bff2 improved rezkonv parser 2022-02-25 15:51:37 +01:00
vabene1111
38ad246dc1 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2022-02-25 15:51:28 +01:00
vabene1111
1bde4e81b7 fixed duplicate returns from tree manager get or create 2022-02-25 15:42:33 +01:00
smilerz
18e53aa03f return distinct shopping entries 2022-02-25 07:59:20 -06:00
vabene1111
e0b9b9caa2 Merge pull request #1583 from TandoorRecipes/expanded-contributors
Update CONTRIBUTERS.md
2022-02-25 14:49:08 +01:00
smilerz
25db5946bf Update CONTRIBUTERS.md 2022-02-25 07:47:36 -06:00
Maximilian Jannack
715e301a4d Revert "Revert "Added some translations in meal plan, recipe search and recipe switcher.""
This reverts commit 391c45b8be.
2022-02-25 10:43:34 +01:00
vabene1111
581f950e33 Merge pull request #1578 from smilerz/remove_stale_requirements
remove stale requirements
2022-02-25 08:01:24 +01:00
vabene1111
97eadfc39a Merge pull request #1577 from smilerz/email_confrm_ignores_ScriptName
fix bad redirect after email confirmation when using script_name
2022-02-25 08:00:47 +01:00
vabene1111
f7a3e2371a Merge pull request #1581 from MaxJa4/fix/member_count
Fix member count in space settings
2022-02-25 07:58:10 +01:00
MaxJa4
391c45b8be Revert "Added some translations in meal plan, recipe search and recipe switcher."
This reverts commit b2fa1db4f9.
2022-02-24 20:53:52 +01:00
MaxJa4
95b63d882b Fixed member count in space settings. 2022-02-24 19:31:42 +01:00
MaxJa4
b2fa1db4f9 Added some translations in meal plan, recipe search and recipe switcher. 2022-02-24 19:19:25 +01:00
smilerz
3b0b756a30 remove stale requirements 2022-02-24 09:58:14 -06:00
smilerz
896be70a77 fix bad redirect after email confirmation when using script_name 2022-02-24 09:03:29 -06:00
vabene1111
bedbc255b3 Merge pull request #1574 from smilerz/export_from_filter
fix serializer using food name instead of supermarket name
2022-02-24 07:50:18 +01:00
smilerz
c8dcca8630 fix recipe search in export form (converted to change safe genericAPI) 2022-02-23 17:24:06 -06:00
Kaibu
05305c46ca shopping list mobile detail fix 2022-02-23 23:23:37 +01:00
Kaibu
6d5195f0d3 improved cookbook detail loading 2022-02-23 22:44:37 +01:00
smilerz
abeeac838b fix serializer using food name instead of supermarket name 2022-02-23 14:31:43 -06:00
vabene1111
f2c543ac15 Merge pull request #1572 from smilerz/export_from_filter
Export from filter
2022-02-23 17:59:19 +01:00
smilerz
081edfd2d6 fix errors on Tandoor recipe import 2022-02-22 16:33:09 -06:00
smilerz
f9a4521ca1 redirect export using djangoResolveUrl 2022-02-22 16:00:55 -06:00
smilerz
a7d66fa850 export recipes from saved filter 2022-02-22 15:18:39 -06:00
vabene1111
b9597a3333 fixed keyword names including labels during import 2022-02-22 21:21:25 +01:00
vabene1111
5424702dff Merge pull request #1570 from smilerz/trigram_fullltext_fix
fix combined fulltext search and trigram generating error
2022-02-22 21:17:35 +01:00
smilerz
9b5a9b87e9 fix combined fulltext search and trigram generating error 2022-02-22 11:28:30 -06:00
vabene1111
52c16ab7dd all types bascially working (lacking bookmark) 2022-02-22 17:00:30 +01:00
vabene1111
0d98c77301 some small ui stuff 2022-02-21 18:29:23 +01:00
smilerz
e52054e732 retain original text when parsing ingredients 2022-02-21 09:47:27 -06:00
vabene1111
e04d672750 import with image working 2022-02-21 15:59:30 +01:00
vabene1111
c06c511dc9 changed unit default in ingredient parser to none
because empty name units are not accepted by unit serializer but null values can be handled by the ingredient serializer (as a unit can be null)
2022-02-21 15:35:36 +01:00
vabene1111
c8fc67fa2b changed source import to match field structure of recipe model
first imports working
2022-02-19 17:54:00 +01:00
vabene1111
89348f69f1 basics of new import page 2022-02-19 16:55:17 +01:00
vabene1111
c1605454dd only show create/import on search when not loading 2022-02-19 09:37:57 +01:00
vabene1111
55b035eaaa first boilerplate for new import view 2022-02-19 09:34:42 +01:00
vabene1111
b19ff3dca4 added import/create buttons to empty search 2022-02-19 09:16:54 +01:00
vabene1111
8361f4f692 Merge branch 'feature/custom_filters' into develop
# Conflicts:
#	cookbook/helper/recipe_search.py
2022-02-19 08:54:14 +01:00
vabene1111
1b6863683f rename to prevent shadowing 2022-02-19 08:53:25 +01:00
vabene1111
7fa5c2d987 changed defaults for multiple kw/book/food filters 2022-02-19 08:51:11 +01:00
smilerz
3b08b1406f filters are automatically shared when part of shared book 2022-02-19 08:51:11 +01:00
smilerz
6dddcadf41 calculate child/sibling subsitutes correctly 2022-02-19 08:50:55 +01:00
vabene1111
a843f94ea1 Merge pull request #1560 from TandoorRecipes/dependabot/npm_and_yarn/vue/url-parse-1.5.7
Bump url-parse from 1.5.3 to 1.5.7 in /vue
2022-02-19 08:42:55 +01:00
dependabot[bot]
c1297285f3 Bump url-parse from 1.5.3 to 1.5.7 in /vue
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.3 to 1.5.7.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.3...1.5.7)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-19 07:39:44 +00:00
vabene1111
43252a941b Merge pull request #1558 from smilerz/better_get_minutes
handle fractions and decimals in get_minutes() during import
2022-02-19 08:39:00 +01:00
smilerz
3e2fb6f814 Update recipe_url_import.py 2022-02-18 16:31:48 -06:00
smilerz
8e28247f17 handle fractions and decimals in get_minutes() during import 2022-02-18 15:31:55 -06:00
smilerz
f082a2f2cc filters are automatically shared when part of shared book 2022-02-18 11:33:04 -06:00
smilerz
cc1aed948a calculate child/sibling subsitutes correctly 2022-02-18 11:25:31 -06:00
vabene1111
e081d823ed fix book share permission 2022-02-18 17:52:32 +01:00
vabene1111
3cbc96b8b7 Merge pull request #1471 from TandoorRecipes/feature/custom_filters
Feature/custom filters
2022-02-18 17:30:29 +01:00
vabene1111
d6fa02cc9e Merge branch 'develop' into feature/custom_filters 2022-02-18 17:25:15 +01:00
vabene1111
d28cf681a3 Merge pull request #1555 from MaxJa4/improvement/startup_error_page
Added 502 error page for system startup
2022-02-18 17:03:37 +01:00
Maxi
21df09d0ba Added 502 error page for system startup 2022-02-18 16:35:27 +01:00
smilerz
2b5aec5d0a resolved loading custom filter when not in expert mode 2022-02-18 09:08:36 -06:00
vabene1111
9021bcd222 Merge pull request #1554 from MaxJa4/patch-1
[Docs] Add syntax highlighting for nginx subpath example
2022-02-18 13:46:08 +01:00
MaxJa4
e691eaf72f Update docker.md 2022-02-18 13:25:20 +01:00
MaxJa4
9e7a908136 Add syntax highlighting for nginx subpath example 2022-02-18 13:23:51 +01:00
smilerz
6b5a099ba0 removed case insensitive get_or_create for units 2022-02-17 12:49:41 -06:00
smilerz
1c18c8faac fix expert mode 2022-02-17 10:59:53 -06:00
smilerz
f1fa5e32bf fix case insensitive get_or_create 2022-02-17 10:50:38 -06:00
smilerz
d49818ae6a change default trigram threshold 2022-02-17 10:27:15 -06:00
smilerz
1b7f97dc64 case insensitive get_or_create 2022-02-17 10:23:31 -06:00
vabene1111
26a5c665de fixed instructions rendering next to ingredients on small devices 2022-02-17 15:30:08 +01:00
vabene1111
6a73ac0a33 fixed editor leave warning 2022-02-17 15:20:42 +01:00
vabene1111
7e5019eed3 fixed share write permission for meal plan 2022-02-17 14:57:28 +01:00
vabene1111
f23b566689 changed feature request template 2022-02-17 14:53:40 +01:00
vabene1111
e9431b5ff2 changed warning stylin 2022-02-17 14:53:27 +01:00
vabene1111
a54d08c9e2 Merge branch 'develop' into feature/custom_filters 2022-02-17 14:23:47 +01:00
vabene1111
d342e12363 show warning for multiple identical filter 2022-02-17 14:23:35 +01:00
vabene1111
a7aa458a85 Merge pull request #1548 from FHantke/develop
fix file path checks
2022-02-17 13:31:04 +01:00
florian hantke
d135c755c8 fix file path checks 2022-02-17 13:26:35 +01:00
vabene1111
3292c596ff Merge branch 'develop' into feature/custom_filters
# Conflicts:
#	vue/src/components/MealPlanEditModal.vue
#	vue/src/locales/en.json
2022-02-17 10:57:35 +01:00
vabene1111
caeaab22ce Merge pull request #1543 from smilerz/feature/copy-to-new-recipe
copy to new recipe
2022-02-17 10:56:03 +01:00
vabene1111
4fa5b28328 Merge branch 'develop' into feature/copy-to-new-recipe 2022-02-17 10:55:59 +01:00
vabene1111
f916e38da8 Merge pull request #1539 from smilerz/auto_add_shopping_fix
fix duplicate shopping recipes when auto-add enabled
2022-02-17 10:55:06 +01:00
vabene1111
f77b45725b Merge pull request #1538 from smilerz/feature/paste_ingredients
paste list of ingredients
2022-02-17 10:54:25 +01:00
vabene1111
8aedb80140 Merge pull request #1535 from MaxJa4/improvement/check_nginx_config
Added existence check for Nginx config file and mandatory parameters
2022-02-17 10:52:58 +01:00
smilerz
a76c4365ea mealplan showing on search when filtered instead of vice versa 2022-02-16 16:49:36 -06:00
smilerz
21c6f819a0 start counting at zero 2022-02-16 14:19:58 -06:00
smilerz
5f3d5afc37 typo 2022-02-16 14:18:23 -06:00
smilerz
57dec86b06 handle empty ingredient list when pasting 2022-02-16 14:17:41 -06:00
smilerz
d68a89a32c catch empty lines in paste_ingredients 2022-02-16 14:07:56 -06:00
smilerz
8b94bf1333 retain order of pasted ingredients 2022-02-16 13:22:53 -06:00
MaxJa4
539578c965 Add check for SECRET_KEY and POSTGRES_PASSWORD 2022-02-16 18:57:25 +01:00
MaxJa4
124a8687f1 Merge branch 'TandoorRecipes:develop' into improvement/check_nginx_config 2022-02-16 18:16:01 +01:00
smilerz
42a6f8457a remove console messages 2022-02-16 10:58:05 -06:00
smilerz
4c9ddee55c restrict get_or_create to name & space 2022-02-16 10:50:01 -06:00
vabene1111
de1efcb81e Merge pull request #1540 from TandoorRecipes/dependabot/npm_and_yarn/vue/follow-redirects-1.14.8
Bump follow-redirects from 1.14.7 to 1.14.8 in /vue
2022-02-16 17:04:46 +01:00
smilerz
501f56ffd5 copy to new recipe 2022-02-16 09:16:51 -06:00
smilerz
ad6d99800e include note from ingredient API 2022-02-16 08:35:04 -06:00
smilerz
bd973ec3a9 always sort count attributes to end 2022-02-15 16:19:41 -06:00
smilerz
b5c6c7cf2b sort cooked date fix 2022-02-15 12:00:59 -06:00
smilerz
f9ae48e23c fix Vue cookedon sort 2022-02-15 09:14:27 -06:00
smilerz
4e8bbefc17 minor cleanup 2022-02-15 06:42:57 -06:00
dependabot[bot]
90b4ecb599 Bump follow-redirects from 1.14.7 to 1.14.8 in /vue
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-15 02:38:12 +00:00
smilerz
57658e76f5 fix duplicate shopping recipes when auto-add enabled 2022-02-14 17:47:17 -06:00
smilerz
19708dbc64 paste list of ingredients 2022-02-14 17:28:16 -06:00
smilerz
444e0c1918 include new filters in ResetSearch() 2022-02-14 15:35:56 -06:00
smilerz
8fa00b50b1 added update_at filter 2022-02-14 15:13:34 -06:00
MaxJa4
b9f16c3f66 Inverted truth check for GUNICORN_MEDIA 2022-02-14 16:45:37 +01:00
MaxJa4
c90de725b0 Only show warning if not using gunicorn 2022-02-14 16:16:45 +01:00
MaxJa4
c0b43987dd Added extistence check for nginx config file. 2022-02-14 16:13:16 +01:00
smilerz
c2fa86e388 fixed typo 2022-02-13 14:35:38 -06:00
smilerz
3b8be24630 merge RecipeSearch with upstream 2022-02-13 14:15:01 -06:00
smilerz
e72f6e4ac4 Merge remote-tracking branch 'upstream/feature/custom_filters' into feature/custom_filters 2022-02-13 14:14:28 -06:00
smilerz
ef81700c05 add created filter, viewed filter and viewed sort 2022-02-13 14:07:43 -06:00
smilerz
bf54680178 more recipe search tests 2022-02-13 13:53:07 -06:00
A. L
a522f9879f Translated using Weblate (German)
Currently translated at 100.0% (298 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-02-12 21:31:35 +00:00
Dirk
4ee32b3263 Translated using Weblate (German)
Currently translated at 100.0% (298 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-02-12 21:31:35 +00:00
Ghostfighter
c339b4fef8 Translated using Weblate (German)
Currently translated at 99.6% (566 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2022-02-12 21:31:35 +00:00
Dirk
9ff981f34f Translated using Weblate (German)
Currently translated at 99.6% (566 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2022-02-12 21:31:35 +00:00
vabene1111
3db55cd82b added sub path nginx example 2022-02-11 14:16:22 +01:00
vabene1111
f4bfcdab2e improved on explain and some tweaks 2022-02-11 14:15:46 +01:00
vabene1111
f320651cf8 Merge branch 'develop' into feature/custom_filters 2022-02-11 09:31:59 +01:00
vabene1111
3e9de4c392 compiled translations 2022-02-11 09:31:37 +01:00
vabene1111
1e9f7af017 updated translations and django version 2022-02-11 09:29:28 +01:00
vabene1111
cd99b9dc34 Merge pull request #849 from cschmatzler/develop
Allow specifying port through TANDOOR_PORT environment variable
2022-02-11 09:17:46 +01:00
vabene1111
b182a9962c Merge branch 'develop' into develop 2022-02-11 09:17:31 +01:00
vabene1111
9b5cc3deaa Merge pull request #1496 from poggenpower/develop
K8s deployment: Small fix for dupplicate entries.
2022-02-11 09:05:36 +01:00
vabene1111
7e7c7a3841 Merge pull request #1499 from xMAC94x/update_base_image
Update the baseimage of dockerfile as alpine 3.12 has some security v…
2022-02-11 09:04:29 +01:00
vabene1111
6ae1365505 Merge pull request #1512 from smilerz/additional_fixes
various fixes
2022-02-11 09:01:56 +01:00
vabene1111
dd2f27cfd4 Merge pull request #1513 from MaxJa4/improvement/ping_db
Ping DB instead of trying migration
2022-02-11 08:59:51 +01:00
vabene1111
1a38b54e4f Merge pull request #1520 from smilerz/LDAP-debug-logging
enable logging for LDAP
2022-02-11 08:59:04 +01:00
vabene1111
fffb0e0d07 Merge pull request #1525 from TandoorRecipes/revert-1516-patch-2
Revert "Update de.json"
2022-02-11 08:54:31 +01:00
vabene1111
de505dc8cc Revert "Update de.json" 2022-02-11 08:53:37 +01:00
vabene1111
9a735b75dc Merge pull request #1516 from hyperbit00/patch-2
Update de.json
2022-02-11 08:53:31 +01:00
smilerz
f933226c5d enable logging for LDAP 2022-02-09 16:19:51 -06:00
smilerz
baa2aa51da more recipe search tests 2022-02-09 16:18:45 -06:00
vabene1111
32a8cc9a69 proof of concept for recipe search explain 2022-02-09 18:44:29 +01:00
smilerz
c2961eede4 stub out receip search tests 2022-02-08 20:23:49 -06:00
Marion Kämpfer
13ed297fb9 Translated using Weblate (French)
Currently translated at 95.9% (286 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2022-02-09 01:31:35 +00:00
Jesse
4c259e6b9c Translated using Weblate (Dutch)
Currently translated at 95.2% (541 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/nl/
2022-02-09 01:31:35 +00:00
Marion Kämpfer
faf51d0455 Translated using Weblate (French)
Currently translated at 94.7% (538 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fr/
2022-02-09 01:31:35 +00:00
hyperbit00
ed1585caed Update de.json
typo
2022-02-08 23:00:57 +01:00
hyperbit00
3917521ed6 Update de.json
typo in ressource
2022-02-08 22:56:33 +01:00
smilerz
924ffc473b fix recipe sharing 2022-02-08 14:59:54 -06:00
smilerz
0e258a49fb reload book recipes when adding filter 2022-02-08 12:30:11 -06:00
MaxJa4
a1063ce922 Merge branch 'improvement/ping_db' of https://github.com/MaxJa4/recipes into improvement/ping_db 2022-02-08 19:00:56 +01:00
MaxJa4
2471bb21f6 Fixed dep. position and used smaller package 2022-02-08 19:00:54 +01:00
smilerz
b3a830c319 fix missing pill when loading CustomFilter 2022-02-08 11:41:57 -06:00
MaxJa4
45942dfa7f Fixed indentation 2022-02-08 18:20:19 +01:00
MaxJa4
cb755a47bc Remove wrong code comment 2022-02-08 18:19:32 +01:00
MaxJa4
a35aa953b4 Ping DB instead of trying migration 2022-02-08 18:15:04 +01:00
smilerz
62adc5a91f make +/- search fields not clickable 2022-02-08 09:57:23 -06:00
smilerz
dc71260baa Merge branch 'additional_fixes' into feature/custom_filters 2022-02-08 09:05:07 -06:00
smilerz
88b3ba1427 various fixes 2022-02-08 08:13:16 -06:00
smilerz
93b7e5790d merge clashing commits 2022-02-07 18:11:38 -06:00
smilerz
286c6344ec Merge branch 'feature/custom_filters' into feature/custom_filtersv2 2022-02-07 17:47:53 -06:00
smilerz
1be5889923 tests for makenow filter 2022-02-07 17:46:04 -06:00
Marcel Märtens
542b656bea fix python-ldap bugs according to https://github.com/TandoorRecipes/recipes/pull/1499\#issuecomment-1031627178 2022-02-07 19:21:35 +01:00
vabene1111
4c5994ee7f Merge branch 'develop' into feature/custom_filters
# Conflicts:
#	cookbook/serializer.py
#	cookbook/views/api.py
#	vue/src/utils/openapi/api.ts
2022-02-07 18:56:19 +01:00
vabene1111
f1bbe16606 Merge pull request #1498 from MaxJa4/improvement/retry_migrations
Moved DB-waiting from docker-level to container-level
2022-02-07 18:42:41 +01:00
vabene1111
74e30c79d5 Merge branch 'develop' 2022-02-07 18:41:57 +01:00
MaxJa4
d28a2f81a2 Remove always-restart so the container doesn't boot-loop on error 2022-02-07 18:14:03 +01:00
MaxJa4
855f1e4ee7 Remove always-restart so the container doesn't boot-loop on error 2022-02-07 18:13:58 +01:00
MaxJa4
b53a9a1c07 Remove always-restart so the container doesn't boot-loop on error 2022-02-07 18:13:50 +01:00
MaxJa4
20cc4b93a9 Add max amount of retries for web container boot 2022-02-07 18:13:19 +01:00
vabene1111
c92c3e7d85 improved comment formatting 2022-02-07 17:43:57 +01:00
smilerz
d6af318c21 tests for single food reset inherit and additional inheritted fields 2022-02-07 09:16:48 -06:00
vabene1111
969df37e28 fixed sharing and added additional tests 2022-02-07 15:43:06 +01:00
vabene1111
f37790a24a changed to vue 2 lifecycle hook 2022-02-07 14:48:52 +01:00
vabene1111
5f9820ed30 Merge pull request #1469 from benscobie/issue/1434
Keep screen awake when viewing recipe
2022-02-07 14:48:21 +01:00
vabene1111
543fbfc120 Merge pull request #1490 from murphy83/develop
Added docker compose file for IPv6 native
2022-02-07 14:42:53 +01:00
vabene1111
bcd85ff7d6 Merge pull request #1501 from besendorf/patch-1
add instructions for pwa for Android/Chrome browsers
2022-02-07 14:42:03 +01:00
vabene1111
0dbb9457a1 fixed test 2022-02-07 14:41:36 +01:00
vabene1111
5cc81d977f updated translations 2022-02-07 14:41:00 +01:00
vabene1111
39ca3ac1ad no system page for non superuser 2022-02-07 13:08:18 +01:00
Marcel Märtens
bd8633c630 Update the baseimage of dockerfile as alpine 3.12 has some security vunerabilities.
According to:
https://artifacthub.io/packages/helm/truecharts/recipes?modal=security-report&image=tccr.io%2Ftruecharts%2Frecipes%3Av1.0.5%40sha256%3Ac74923879e7d2bf5bff4d1e953a100307462ad191a79908165f3364b97446833
There are at least 4 Chritical ones with a total of 47.
So updating the base should prob be a good thing and help here.
2022-02-06 23:57:40 +01:00
besendorf
cec74d77ec add instructions for pwa for Android/Chrome browsers
fixes #1349
2022-02-06 22:50:48 +01:00
Dersim Özdag
7dcc38b5b2 Translated using Weblate (German)
Currently translated at 100.0% (298 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-02-06 21:31:33 +00:00
Dirk
6068496240 Translated using Weblate (German)
Currently translated at 100.0% (298 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-02-06 21:31:33 +00:00
Marion Kämpfer
2b6e365f0b Translated using Weblate (French)
Currently translated at 91.0% (517 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fr/
2022-02-06 21:31:32 +00:00
David Laukamp
2f045e6e0d Translated using Weblate (German)
Currently translated at 96.6% (549 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2022-02-06 21:31:32 +00:00
Christian
8dffc58ca6 Translated using Weblate (German)
Currently translated at 96.6% (549 of 568 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2022-02-06 21:31:32 +00:00
MaxJa4
fd5de4e47c Included error code in log message 2022-02-06 19:22:46 +01:00
MaxJa4
bb131ef16a Improved wording of log message upon retry 2022-02-06 19:12:52 +01:00
MaxJa4
773d2eff37 Moved db-waiting from docker-level to container-level 2022-02-06 18:54:42 +01:00
thl@deb030
9f9cc766c6 Small fix for dupplicate entries. 2022-02-06 17:42:04 +01:00
Dirk
65003175ce Translated using Weblate (German)
Currently translated at 99.6% (297 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-02-05 21:06:28 +00:00
A. L
72d29cc88a Translated using Weblate (German)
Currently translated at 99.6% (297 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-02-05 21:06:28 +00:00
Dersim Özdag
bc8131ac56 Translated using Weblate (German)
Currently translated at 99.6% (297 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-02-05 21:06:28 +00:00
Dirk
1c27f2f9b1 Translated using Weblate (German)
Currently translated at 99.6% (297 of 298 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2022-02-05 21:06:28 +00:00
Kai Schlachter
80965c5462 Added docker compose file for IPv6 native 2022-02-05 13:14:04 +01:00
Chris Scoggins
ab52bd1a07 fix makenow/fulltext search duplicate results 2022-02-04 08:40:20 -06:00
Chris Scoggins
f9244a93a5 fix MakeNow filter 2022-02-03 17:19:38 -06:00
Chris Scoggins
6ef25b604b add food substitutions 2022-02-03 15:04:46 -06:00
Chris Scoggins
5e3f94fcf7 fix after rebase 2022-02-03 12:21:35 -06:00
Chris Scoggins
dcad389010 food edit modal - reset children inheritance 2022-02-03 12:15:04 -06:00
Chris Scoggins
a0508684d9 cleaned up console messages 2022-02-03 12:14:43 -06:00
Chris Scoggins
9ffae0da7b rebuild openapi 2022-02-03 12:14:42 -06:00
Chris Scoggins
04c4182b24 WIP 2022-02-03 12:14:42 -06:00
Chris Scoggins
583aee204e fix view recipes in Model View 2022-02-03 12:14:18 -06:00
Chris Scoggins
e05fd02c65 recipecoontextmenu 2022-02-03 12:14:17 -06:00
Chris Scoggins
c45bf3a994 WIP 2022-02-03 12:14:17 -06:00
Chris Scoggins
203ff1a6ec WIP 2022-02-03 12:14:04 -06:00
Chris Scoggins
07d5ead128 load RecipeFilter cookbook entries 2022-02-03 12:14:04 -06:00
Chris Scoggins
c042ab08c7 fix after rebase 2022-02-03 12:13:36 -06:00
Chris Scoggins
598f53f3d4 removeMissingItem disabled 2022-02-03 12:13:35 -06:00
Chris Scoggins
ec2cbc9b1b Fix after rebase 2022-02-03 12:13:16 -06:00
Chris Scoggins
fcb8e520b7 WIP 2022-02-03 12:11:32 -06:00
Chris Scoggins
5959914932 makenow filter 2022-02-03 12:11:32 -06:00
Chris Scoggins
ebb0b3a5ea sort by menu 2022-02-03 12:10:00 -06:00
Chris Scoggins
a72fc46d40 improved interaction between saved filter and filter fields 2022-02-03 12:10:00 -06:00
Chris Scoggins
8d78d15e21 implement sort order via API 2022-02-03 12:09:32 -06:00
Chris Scoggins
890e9e7242 created CustomFilter model and api 2022-02-03 12:09:14 -06:00
Chris Scoggins
492febe626 add saveSearch() 2022-02-03 12:08:10 -06:00
Chris Scoggins
d0549bcb6d complex book filters 2022-02-03 12:07:51 -06:00
Chris Scoggins
5e36bd0c27 complex food filters 2022-02-03 12:07:51 -06:00
Chris Scoggins
28d3d8a1e0 complex keyword filters 2022-02-03 12:07:50 -06:00
Chris Scoggins
bb226a221e WIP 2022-02-03 12:07:14 -06:00
smilerz
0ac369423c WIP 2022-02-03 12:07:13 -06:00
smilerz
a6a136c892 fix multiselect 2022-02-03 12:07:13 -06:00
smilerz
97224fa6a0 expert search settings 2022-02-03 12:06:57 -06:00
smilerz
5210bb6fbf added expert search settings 2022-02-03 12:06:30 -06:00
smilerz
918577a9a0 refactored cookies 2022-02-03 12:06:30 -06:00
smilerz
0e89723eab Squashed commit of the following:
commit ba1f10cd3a
Merge: 4e0cc34d4 ef4ce62f5
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Tue Jan 18 07:59:32 2022 +0100

    Merge branch 'develop' into facet-fix

commit 4e0cc34d41
Author: smilerz <smilerz@gmail.com>
Date:   Mon Jan 17 17:18:43 2022 -0600

    better fix for counting facets

commit ef4ce62f5b
Author: Kaibu <notkaibu@gmail.com>
Date:   Mon Jan 17 23:48:57 2022 +0100

    custom class selection for lookupinput comp

commit b990462bdb
Merge: c60141940 5e34c6ddf
Author: Kaibu <notkaibu@gmail.com>
Date:   Mon Jan 17 23:48:12 2022 +0100

    Merge branch 'develop' of https://github.com/vabene1111/recipes into develop

commit 5e34c6ddf0
Merge: 532d32c19 d8d76ae9e
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 23:29:49 2022 +0100

    Merge pull request #1353 from smilerz/supermarket-category

    fix missing label on first supermarket category

commit d8d76ae9e0
Author: smilerz <smilerz@gmail.com>
Date:   Mon Jan 17 16:12:54 2022 -0600

    fix missing label supermarket category

commit c60141940d
Author: Kaibu <notkaibu@gmail.com>
Date:   Mon Jan 17 23:02:42 2022 +0100

    shopping list ux improvements

commit 532d32c194
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 22:41:38 2022 +0100

    fixed shopping user save setting would not work

commit 54721a0a62
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 22:37:14 2022 +0100

    also added space to bot

commit c27933548d
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 22:28:02 2022 +0100

    fixed order of delete

commit d04e9518cb
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 22:13:36 2022 +0100

    fixed telegram shopping bot

commit b9065f7052
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 22:03:57 2022 +0100

    added space deletion feature

commit c8c29e1b5a
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 21:14:22 2022 +0100

    fixed performance issue

commit 5724ef9511
Author: smilerz <smilerz@gmail.com>
Date:   Mon Jan 17 14:02:58 2022 -0600

    fix boolean directive

commit 2595a26fb4
Merge: e1c7305c0 437296415
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 20:26:02 2022 +0100

    Merge pull request #1351 from MaxJa4/patch-1

    Add hint about trailing slashes for subpath setups

commit e1c7305c07
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 20:22:37 2022 +0100

    switcher basically working again

commit 418c38423f
Merge: 90b6f9ad0 cc5be844d
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 20:15:01 2022 +0100

    Merge pull request #1352 from smilerz/fix-search

    force list params to list

commit cc5be844d5
Author: smilerz <smilerz@gmail.com>
Date:   Mon Jan 17 13:13:26 2022 -0600

    force list params to list

commit 90b6f9ad06
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 19:54:16 2022 +0100

    fixed sub recipe issue

commit 437296415e
Author: MaxJa4 <74194322+MaxJa4@users.noreply.github.com>
Date:   Mon Jan 17 18:43:14 2022 +0100

    Update .env.template

commit a8c885bd21
Author: MaxJa4 <74194322+MaxJa4@users.noreply.github.com>
Date:   Mon Jan 17 18:41:41 2022 +0100

    Remove newline at the end

commit a539d14aad
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 18:15:23 2022 +0100

    wip switcher

commit 2b0541bd74
Author: MaxJa4 <74194322+MaxJa4@users.noreply.github.com>
Date:   Mon Jan 17 18:05:39 2022 +0100

    Add hint about trailing slashes for subpath setups

    Add hint about trailing slashes for subpath setups due to recent issue on Discord.

commit 3f53a924e1
Merge: d23158839 0ed9100fb
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 18:01:47 2022 +0100

    Merge branch 'develop' of https://github.com/vabene1111/recipes into develop

commit 0ed9100fb1
Merge: d2b796ddd 85ecac3a1
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 17:59:19 2022 +0100

    Merge pull request #1350 from TandoorRecipes/patch-empty-recipe_list

    Update recipe_search.py

commit d23158839b
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 17:58:09 2022 +0100

    Revert "temporarily disable recipe switcher"

    This reverts commit d2b796ddd2.

commit d2b796ddd2
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 17:58:04 2022 +0100

    temporarily disable recipe switcher

commit 8b1e80efeb
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 17:51:29 2022 +0100

    wip

commit 85ecac3a17
Author: smilerz <smilerz@gmail.com>
Date:   Mon Jan 17 10:10:38 2022 -0600

    Update recipe_search.py

commit e0b8d6fcc3
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 17:00:08 2022 +0100

    added exception catch to nextcloud importer

    to handle empty folders in sync

commit edd47873f7
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 16:51:04 2022 +0100

    fixed signup button and autofocus on user input fields

commit c14dd04261
Merge: a37672812 769365d62
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 16:50:36 2022 +0100

    Merge pull request #1348 from smilerz/fuzzy_search

    Fuzzy search

commit 769365d624
Merge: ddb9e70d3 30421d067
Author: smilerz <smilerz@gmail.com>
Date:   Mon Jan 17 09:46:33 2022 -0600

    Merge branch 'fuzzy_search' of github.com:smilerz/recipes into fuzzy_search

commit ddb9e70d31
Author: smilerz <smilerz@gmail.com>
Date:   Mon Jan 17 09:46:26 2022 -0600

    fix url_import

commit a376728120
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 16:29:29 2022 +0100

    fixed keyword creation in exporter #1213

commit 306f90aa98
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 16:27:10 2022 +0100

    recipe editor decimal fixes

commit a19ad706ce
Merge: 4af6de742 8f3044dbe
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 16:22:18 2022 +0100

    Merge branch 'develop' of https://github.com/vabene1111/recipes into develop

commit 4af6de7425
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 16:22:11 2022 +0100

    Revert "Merge pull request #1280 from MarcusWolschon/feature1275_readable_export_file_names"

    This reverts commit c4f40b9639, reversing
    changes made to 93b868bc69.

commit 8f3044dbee
Merge: 7c5ffdaef 51620a34d
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 16:04:40 2022 +0100

    Merge pull request #1316 from tomtjes/docs-swag-example

    add swag config example

commit 7c5ffdaef4
Merge: d3b71e40c 30421d067
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 15:51:54 2022 +0100

    Merge pull request #1347 from smilerz/fuzzy_search

    Fuzzy search

commit 30421d067e
Merge: dde350c8a d3b71e40c
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 15:51:23 2022 +0100

    Merge branch 'develop' into fuzzy_search

commit d3b71e40c7
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 15:43:35 2022 +0100

    cleand up context menu code

commit 1a84a8fe80
Merge: 16cb99f91 934eeee5c
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 15:39:11 2022 +0100

    Merge pull request #1289 from MarcusWolschon/features/1093_recipe_link_in_plan

commit 16cb99f915
Merge: a451f722a f07690d7e
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 15:37:48 2022 +0100

    Merge pull request #1317 from mheiland/patch-1

    Example for third-party authentication

commit a451f722a1
Merge: f12196d1c 99b3ed846
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 15:35:43 2022 +0100

    Merge pull request #1327 from tomtjes/docs-faq-amendments

    FAQ amendments

commit dde350c8af
Author: smilerz <smilerz@gmail.com>
Date:   Mon Jan 17 08:35:19 2022 -0600

    prettier cleanup

commit f12196d1c6
Merge: d4242a244 b3e971fe0
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Mon Jan 17 15:20:45 2022 +0100

    Merge pull request #1343 from MatthiasLohr/feature/db-url-path

    Allow to specify an actual path using DATABASE_URL

commit d4242a244d
Merge: 0c603e366 8a7c4e11c
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 15:16:37 2022 +0100

    Merge branch 'master' into develop

commit 8a7c4e11c9
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Mon Jan 17 15:16:13 2022 +0100

    fixed invite link counting

commit 745bb58c7e
Author: vabene1111 <vabene1234@googlemail.com>
Date:   Sun Jan 9 18:25:38 2022 +0100

    fixed valid filter on invite link counter

commit b3e971fe09
Author: Matthias Lohr <mail@mlohr.com>
Date:   Mon Jan 17 11:21:36 2022 +0100

    allow to specify an actual path using DATABASE_URL

commit 0c603e3665
Author: Oliver Cervera <olivercervera@yahoo.it>
Date:   Sun Jan 16 15:21:49 2022 +0000

    Translated using Weblate (Italian)

    Currently translated at 84.1% (239 of 284 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/

commit fed9cfeeb7
Author: Oliver Cervera <olivercervera@yahoo.it>
Date:   Sun Jan 16 15:44:28 2022 +0000

    Translated using Weblate (Italian)

    Currently translated at 96.6% (492 of 509 strings)

    Translation: Tandoor/Recipes Backend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/it/

commit 5a65fd2231
Merge: c2a763fa4 24e42496a
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Sun Jan 16 17:29:35 2022 +0100

    Merge pull request #1331 from TandoorRecipes/dependabot/npm_and_yarn/vue/follow-redirects-1.14.7

    Bump follow-redirects from 1.14.6 to 1.14.7 in /vue

commit c2a763fa4c
Author: SMunos <smunos@synos.ovh>
Date:   Fri Jan 14 23:19:21 2022 +0000

    Translated using Weblate (French)

    Currently translated at 100.0% (284 of 284 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/

commit 528767a835
Author: Josselin du PLESSIS <josse@du-plessis.fr>
Date:   Fri Jan 14 23:20:10 2022 +0000

    Translated using Weblate (French)

    Currently translated at 100.0% (284 of 284 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/

commit 9b182f6076
Author: 糖多 <1365143958@qq.com>
Date:   Sat Jan 15 06:09:40 2022 +0000

    Translated using Weblate (Chinese (Simplified))

    Currently translated at 32.0% (91 of 284 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/zh_Hans/

commit 968b710b49
Author: 糖多 <1365143958@qq.com>
Date:   Sat Jan 15 06:19:48 2022 +0000

    Translated using Weblate (Chinese (Simplified))

    Currently translated at 28.6% (146 of 509 strings)

    Translation: Tandoor/Recipes Backend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/zh_Hans/

commit f11e07d347
Author: Josselin du PLESSIS <josse@du-plessis.fr>
Date:   Fri Jan 14 23:23:05 2022 +0000

    Translated using Weblate (French)

    Currently translated at 100.0% (509 of 509 strings)

    Translation: Tandoor/Recipes Backend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fr/

commit 24e42496a7
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Sun Jan 16 01:02:54 2022 +0000

    Bump follow-redirects from 1.14.6 to 1.14.7 in /vue

    Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.6 to 1.14.7.
    - [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
    - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.6...v1.14.7)

    ---
    updated-dependencies:
    - dependency-name: follow-redirects
      dependency-type: indirect
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

commit 9da496cb6d
Merge: 8cebc98d3 9221533ae
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Sat Jan 15 21:46:04 2022 +0100

    Merge pull request #1323 from MaxJa4/patch-1

    Added Apache2 in the bug report template

commit 99b3ed8464
Author: tomtjes <nesiofnqwe@mailbox.org>
Date:   Sat Jan 15 13:58:40 2022 -0500

    add FAQ for PWA

commit 281535e756
Author: tomtjes <nesiofnqwe@mailbox.org>
Date:   Sat Jan 15 13:57:20 2022 -0500

    phrase FAQ as questions

commit 9221533ae7
Author: MaxJa4 <74194322+MaxJa4@users.noreply.github.com>
Date:   Sat Jan 15 12:56:01 2022 +0100

    Added Apache2 in the bug report template

    Added Apache2 as selectable option in the bug report template

commit f07690d7e3
Author: mheiland <15824364+mheiland@users.noreply.github.com>
Date:   Sat Jan 15 00:24:56 2022 +0100

    Example for third-party authentication

    Providing an example to integrate Keycloak as IAM for Tandoor. Hinting that both SOCIAL* variables are required.

commit 8cebc98d3b
Author: SMunos <smunos@synos.ovh>
Date:   Fri Jan 14 23:18:38 2022 +0000

    Translated using Weblate (French)

    Currently translated at 100.0% (284 of 284 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/

commit 965d2c05e7
Author: FrenchAnon <qdskyhwfeu@email.ucms.edu.pk>
Date:   Fri Jan 14 23:17:50 2022 +0000

    Translated using Weblate (French)

    Currently translated at 100.0% (284 of 284 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/

commit 17ad01ae8c
Author: Josselin du PLESSIS <josse@du-plessis.fr>
Date:   Fri Jan 14 22:42:42 2022 +0000

    Translated using Weblate (French)

    Currently translated at 100.0% (284 of 284 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/

commit 51620a34d9
Author: tomtjes <nesiofnqwe@mailbox.org>
Date:   Fri Jan 14 15:10:22 2022 -0500

    add swag config example

commit 91fcb1b822
Author: Tomasz Klimczak <klemensble@gmail.com>
Date:   Thu Jan 6 12:50:29 2022 +0000

    Translated using Weblate (Polish)

    Currently translated at 80.9% (225 of 278 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/

commit 01d5ab92c5
Author: Tiago Rascazzi <t.d77@hotmail.com>
Date:   Thu Jan 6 16:30:49 2022 +0000

    Translated using Weblate (French)

    Currently translated at 72.6% (202 of 278 strings)

    Translation: Tandoor/Recipes Frontend
    Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/

commit 79c8d26e8c
Merge: 9486b08e2 0e1153ce3
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Fri Jan 14 17:18:30 2022 +0100

    Merge pull request #1311 from smilerz/patch-2

    fix bug creating food with create form

commit 9486b08e20
Merge: d36033a8b ffa91863d
Author: vabene1111 <vabene1111@users.noreply.github.com>
Date:   Fri Jan 14 16:57:10 2022 +0100

    Merge pull request #1309 from MaxJa4/develop

    Disabled old issue templates and added new ones with new GitHub issues format

commit 934eeee5c4
Author: Marcus Wolschon <Marcus@Wolschon.biz>
Date:   Fri Jan 14 13:56:46 2022 +0100

commit 2927333bf1
Author: Marcus Wolschon <Marcus@Wolschon.biz>
Date:   Fri Jan 14 13:52:42 2022 +0100

commit 0e1153ce3a
Author: smilerz <smilerz@gmail.com>
Date:   Thu Jan 13 17:40:26 2022 -0600

    deleted extraneous emit

commit b3f05b0bfd
Author: smilerz <smilerz@gmail.com>
Date:   Thu Jan 13 16:50:15 2022 -0600

    fix bug creating food with create form

commit ffa91863dd
Author: Maximilian Jannack <maxijannack@t-online.de>
Date:   Thu Jan 13 21:26:15 2022 +0100

    Added config.yml for FAQ link

commit cf2d33daad
Author: Maximilian Jannack <maxijannack@t-online.de>
Date:   Thu Jan 13 21:17:08 2022 +0100

    Disabled old issue templates and added new ones with new GitHub issues format

commit 8f08ba7114
Author: Marcus Wolschon <Marcus@Wolschon.biz>
Date:   Wed Jan 12 16:15:55 2022 +0100

commit 8a4f35e592
Author: Marcus Wolschon <Marcus@Wolschon.biz>
Date:   Wed Jan 12 11:37:08 2022 +0100
2022-02-03 12:05:33 -06:00
smilerz
1fe027b313 WIP 2022-02-03 12:04:11 -06:00
smilerz
cdb7c7854d initial TreeSearch component 2022-02-03 12:04:11 -06:00
smilerz
ab68a60480 WIP 2022-02-03 12:04:10 -06:00
Ben Scobie
74e88218d5 Keep screen awake when viewing recipe 2022-02-01 21:05:04 +00:00
vabene1111
559fee0ffe Merge branch 'develop' into beta 2022-01-23 12:51:07 +01:00
vabene1111
e15fec9845 Merge branch 'develop' into beta 2022-01-18 22:51:51 +01:00
vabene1111
2073158e1f Merge branch 'develop' into beta 2022-01-18 16:18:19 +01:00
vabene1111
7e2ee0300c Merge branch 'develop' into beta 2022-01-18 07:57:17 +01:00
vabene1111
79f6e27959 Merge branch 'develop' into beta 2022-01-17 17:00:16 +01:00
vabene1111
450923c0a4 Merge branch 'develop' into beta 2021-12-23 15:55:42 +01:00
vabene1111
7537c1a908 Merge branch 'develop' into beta 2021-11-15 08:41:15 +01:00
vabene1111
6cfd1a495e Merge branch 'develop' into beta 2021-10-29 14:56:41 +02:00
vabene1111
17d4619c31 Merge branch 'develop' into beta 2021-10-29 11:49:17 +02:00
vabene1111
2c05e7e282 Merge branch 'develop' into beta 2021-10-26 14:53:31 +02:00
vabene1111
928be086e4 Merge branch 'develop' into beta 2021-10-14 09:03:26 +02:00
vabene1111
e3c86e8685 Merge branch 'develop' into beta 2021-10-11 16:30:28 +02:00
Christoph Schmatzler
e5607aff90 Add TANDOOR_PORT to .env.template 2021-09-02 16:08:39 +02:00
Christoph Schmatzler
a47d9d00fd Allow specifying port through TANDOOR_PORT environment variable 2021-09-01 19:46:55 +02:00
254 changed files with 86787 additions and 23503 deletions

View File

@@ -3,6 +3,9 @@
DEBUG=0
SQL_DEBUG=0
# HTTP port to bind to
# TANDOOR_PORT=8080
# hosts the application can run under e.g. recipes.mydomain.com,cooking.mydomain.com,...
ALLOWED_HOSTS=*
@@ -83,8 +86,10 @@ GUNICORN_MEDIA=0
# EMAIL_HOST_PASSWORD=
# EMAIL_USE_TLS=0
# EMAIL_USE_SSL=0
# DEFAULT_FROM_EMAIL= # email sender address (default 'webmaster@localhost')
# ACCOUNT_EMAIL_SUBJECT_PREFIX= # prefix used for account related emails (default "[Tandoor Recipes] ")
# email sender address (default 'webmaster@localhost')
# DEFAULT_FROM_EMAIL=
# prefix used for account related emails (default "[Tandoor Recipes] ")
# ACCOUNT_EMAIL_SUBJECT_PREFIX=
# allow authentication via reverse proxy (e.g. authelia), leave off if you dont know what you are doing
# see docs for more information https://vabene1111.github.io/recipes/features/authentication/

View File

@@ -29,11 +29,3 @@ body:
attributes:
label: "Additional context"
description: "Add any other context or screenshots about the feature request here."
- type: checkboxes
attributes:
label: "Contribute"
description: "Are you willing and able to help develop this feature?"
options:
- label: "Yes"
- label: "Partly"
- label: "No"

View File

@@ -0,0 +1,48 @@
name: publish beta raspi image docker
on:
push:
branches:
- 'beta'
jobs:
build:
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
# Update Version number
- name: Update version file
uses: DamianReeves/write-file-action@v1.0
with:
path: recipes/version.py
contents: |
VERSION_NUMBER = 'beta'
BUILD_REF = '${{ github.sha }}'
write-mode: overwrite
# Build Vue frontend
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
working-directory: ./vue
run: yarn install
- name: Build dependencies
working-directory: ./vue
run: yarn build
# Build container
- name: Build and publish image
uses: ilteoood/docker_buildx@master
with:
publish: true
imageName: vabene1111/recipes
tag: beta-raspi
dockerFile: Dockerfile-raspi
platform: linux/arm/v7
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
# Send discord notification
- name: Discord notification
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_BETA_WEBHOOK }}
uses: Ilshidur/action-discord@0.3.2
with:
args: '🚀 The BETA Image has been updated! 🥳'

View File

@@ -35,8 +35,9 @@ jobs:
publish: true
imageName: vabene1111/recipes
tag: beta
dockerHubUser: ${{ secrets.DOCKER_USERNAME }}
dockerHubPassword: ${{ secrets.DOCKER_PASSWORD }}
platform: linux/amd64,linux/arm64
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
# Send discord notification
- name: Discord notification
env:

View File

@@ -0,0 +1,45 @@
name: publish latest raspi image docker
on:
push:
tags:
- '*'
jobs:
build:
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Get version number
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}-raspi
# Update Version number
- name: Update version file
uses: DamianReeves/write-file-action@v1.0
with:
path: recipes/version.py
contents: |
VERSION_NUMBER = '${{ steps.get_version.outputs.VERSION }}-raspi'
BUILD_REF = '${{ github.sha }}'
write-mode: overwrite
# Build Vue frontend
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
working-directory: ./vue
run: yarn install
- name: Build dependencies
working-directory: ./vue
run: yarn build
# Build container
- name: Build and publish image
uses: ilteoood/docker_buildx@master
with:
publish: true
imageName: vabene1111/recipes
dockerFile: Dockerfile-raspi
platform: linux/arm/v7
tag: latest-raspi
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}

View File

@@ -38,6 +38,7 @@ jobs:
with:
publish: true
imageName: vabene1111/recipes
platform: linux/amd64,linux/arm64
tag: latest
dockerHubUser: ${{ secrets.DOCKER_USERNAME }}
dockerHubPassword: ${{ secrets.DOCKER_PASSWORD }}
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}

View File

@@ -0,0 +1,47 @@
name: publish tagged raspi release docker
on:
release:
types: [published]
jobs:
build:
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
name: Build image job
steps:
- name: Checkout master
uses: actions/checkout@master
- name: Get version number
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
# Update Version number
- name: Update version file
uses: DamianReeves/write-file-action@v1.0
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@v2
with:
node-version: '14'
- name: Install dependencies
working-directory: ./vue
run: yarn install
- name: Build dependencies
working-directory: ./vue
run: yarn build
# Build container
- name: Build and publish image
uses: ilteoood/docker_buildx@master
with:
publish: true
imageName: vabene1111/recipes
dockerFile: Dockerfile-raspi
platform: linux/arm/v7
tag: ${{ steps.get_version.outputs.VERSION }}-raspi
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}

View File

@@ -40,9 +40,10 @@ jobs:
with:
publish: true
imageName: vabene1111/recipes
platform: linux/amd64,linux/arm64
tag: ${{ steps.get_version.outputs.VERSION }}
dockerHubUser: ${{ secrets.DOCKER_USERNAME }}
dockerHubPassword: ${{ secrets.DOCKER_PASSWORD }}
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
# Send discord notification
- name: Discord notification
env:

View File

@@ -3,7 +3,6 @@ on:
push:
branches:
- master
- develop
jobs:
deploy:

View File

@@ -1,58 +1,83 @@
# Contributers
Many thanks to everyone who contributed to this project! If you add something or help out feel free to add yourself
to this list.
## Code/Features
Please have a look at the [list of pull requests](https://github.com/vabene1111/recipes/pulls) for
a complete list of contributions.
Below are some of the larger contributions made yet.
- @tourn provided the serving feature and **several** other improvements!
- @l0c4lh057 provided a much improved ingredient text parser in [#277](https://github.com/vabene1111/recipes/pull/277)
- @sebimarkgraf added nutritional information [#199](https://github.com/vabene1111/recipes/pull/199)
- @cazier added reverse proxy authentication [#88](https://github.com/vabene1111/recipes/pull/88)
- [vabene1111]
- [Kaibu]
- [smilerz]
- [MaxJa4] Docker builds and other improvements
- [tourn] provided the serving feature and **several** other improvements!
- [l0c4lh057] provided a much improved ingredient text parser in [#277](https://github.com/vabene1111/recipes/pull/277)
- [sebimarkgraf] added nutritional information [#199](https://github.com/vabene1111/recipes/pull/199)
- [cazier] added reverse proxy authentication [#88](https://github.com/vabene1111/recipes/pull/88)
- [murphy83] added support for IPv6 #1490
- [TheHaf] added custom serving size component #1411
- [lostlont] added LDAP support #960
## Translations
### Catalan
### Catalan
[Rubenix](https://www.transifex.com/user/profile/rubenix/)
### Dutch
[D0T1X](https://www.transifex.com/user/profile/D0T1X/)
[ikbenfrank](https://www.transifex.com/user/profile/ikbenfrank/)
[kampsj](https://www.transifex.com/user/profile/kampsj/)
[D0T1X](https://www.transifex.com/user/profile/D0T1X/)
[ikbenfrank](https://www.transifex.com/user/profile/ikbenfrank/)
[kampsj](https://www.transifex.com/user/profile/kampsj/)
### French
[jt117](https://www.transifex.com/user/profile/jt117/)
[nerdinator](https://www.transifex.com/user/profile/nerdinator/)
[agaume](https://www.transifex.com/user/profile/agaume/)
[jt117](https://www.transifex.com/user/profile/jt117/)
[nerdinator](https://www.transifex.com/user/profile/nerdinator/)
[agaume](https://www.transifex.com/user/profile/agaume/)
### German
[eTaurus](https://www.transifex.com/user/profile/eTaurus/)
[l0c4lh057](https://www.transifex.com/user/profile/l0c4lh057/)
[hyperbit00](https://github.com/hyperbit00)
### Hungarian
[igazka](https://www.transifex.com/user/profile/igazka/)
### Italian
[SK3LA](https://www.transifex.com/user/profile/SK3LA/)
[auanasgheps](https://www.transifex.com/user/profile/auanasgheps/)
[SK3LA](https://www.transifex.com/user/profile/SK3LA/)
[auanasgheps](https://www.transifex.com/user/profile/auanasgheps/)
### Latvian
[melkypie](https://github.com/melkypie)
### Portuguese
[hds](https://www.transifex.com/user/profile/hds/)
[mlopezifu](https://www.transifex.com/user/profile/mlopezifu/)
[stormsz](https://www.transifex.com/user/profile/stormsz/)
[hds](https://www.transifex.com/user/profile/hds/)
[mlopezifu](https://www.transifex.com/user/profile/mlopezifu/)
[stormsz](https://www.transifex.com/user/profile/stormsz/)
### Russian
[amillerr](https://github.com/amillerr)
### Spanish
[albertocp](https://www.transifex.com/user/profile/albertocp/)
[alfa5](https://www.transifex.com/user/profile/alfa5/)
[mlopezifu](https://www.transifex.com/user/profile/mlopezifu/)
[sergio.laya](https://www.transifex.com/user/profile/sergio.laya/)
[albertocp](https://www.transifex.com/user/profile/albertocp/)
[alfa5](https://www.transifex.com/user/profile/alfa5/)
[mlopezifu](https://www.transifex.com/user/profile/mlopezifu/)
[sergio.laya](https://www.transifex.com/user/profile/sergio.laya/)
### Swedish
[makanz](https://github.com/makanz)
### Turkish
@@ -60,4 +85,4 @@ Below are some of the larger contributions made yet.
### Vietnamese
[vuongtrunghieu](https://www.transifex.com/user/profile/vuongtrunghieu/)
[vuongtrunghieu](https://www.transifex.com/user/profile/vuongtrunghieu/)

View File

@@ -1,7 +1,7 @@
FROM python:3.9-alpine3.12
FROM python:3.10-alpine3.15
#Install all dependencies.
RUN apk add --no-cache postgresql-libs gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography openldap
#Print all logs without buffering it.
ENV PYTHONUNBUFFERED 1
@@ -15,10 +15,12 @@ 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 libressl-dev libffi-dev cargo openssl-dev openldap-dev && \
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 && \
venv/bin/pip install wheel==0.36.2 && \
venv/bin/pip install wheel==0.37.1 && \
venv/bin/pip install setuptools_rust==1.1.2 && \
venv/bin/pip install -r requirements.txt --no-cache-dir &&\
apk --purge del .build-deps

33
Dockerfile-raspi Normal file
View File

@@ -0,0 +1,33 @@
# 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 && \
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"]

58
boot.sh
View File

@@ -1,12 +1,66 @@
#!/bin/sh
source venv/bin/activate
echo "Updating database"
TANDOOR_PORT="${TANDOOR_PORT:-8080}"
NGINX_CONF_FILE=/opt/recipes/nginx/conf.d/Recipes.conf
display_warning() {
echo "[WARNING]"
echo -e "$1"
}
echo "Checking configuration..."
# Nginx config file must exist if gunicorn is not active
if [ ! -f "$NGINX_CONF_FILE" ] && [ $GUNICORN_MEDIA -eq 0 ]; then
display_warning "Nginx configuration file could not be found at the default location!\nPath: ${NGINX_CONF_FILE}"
fi
# SECRET_KEY must be set in .env file
if [ -z "${SECRET_KEY}" ]; then
display_warning "The environment variable 'SECRET_KEY' is not set but REQUIRED for running Tandoor!"
fi
echo "Waiting for database to be ready..."
attempt=0
max_attempts=20
if [ "${DB_ENGINE}" != 'django.db.backends.sqlite3' ]; then
# POSTGRES_PASSWORD must be set in .env file
if [ -z "${POSTGRES_PASSWORD}" ]; then
display_warning "The environment variable 'POSTGRES_PASSWORD' is not set but REQUIRED for running Tandoor!"
fi
while pg_isready --host=${POSTGRES_HOST} --port=${POSTGRES_PORT} --user=${POSTGRES_USER} -q; status=$?; attempt=$((attempt+1)); [ $status -ne 0 ] && [ $attempt -le $max_attempts ]; do
sleep 5
done
fi
if [ $attempt -gt $max_attempts ]; then
echo -e "\nDatabase not reachable. Maximum attempts exceeded."
echo "Please check logs above - misconfiguration is very likely."
echo "Make sure the DB container is up and POSTGRES_HOST is set properly."
echo "Shutting down container."
exit 1 # exit with error to make the container stop
fi
echo "Database is ready"
echo "Migrating database"
python manage.py migrate
echo "Generating static files"
python manage.py collectstatic_js_reverse
python manage.py collectstatic --noinput
echo "Done"
chmod -R 755 /opt/recipes/mediafiles
exec gunicorn -b :8080 --access-logfile - --error-logfile - --log-level INFO recipes.wsgi
exec gunicorn -b :$TANDOOR_PORT --access-logfile - --error-logfile - --log-level INFO recipes.wsgi

View File

@@ -237,7 +237,7 @@ admin.site.register(Ingredient, IngredientAdmin)
class CommentAdmin(admin.ModelAdmin):
list_display = ('recipe', 'name', 'created_at')
search_fields = ('text', 'user__username')
search_fields = ('text', 'created_by__username')
date_hierarchy = 'created_at'
@staticmethod

View File

@@ -6,7 +6,7 @@ from django.utils.translation import gettext as _
from django_scopes import scopes_disabled
from cookbook.forms import MultiSelectWidget
from cookbook.models import Food, Keyword, Recipe, ShoppingList
from cookbook.models import Food, Keyword, Recipe
with scopes_disabled():
class RecipeFilter(django_filters.FilterSet):
@@ -60,22 +60,3 @@ with scopes_disabled():
class Meta:
model = Recipe
fields = ['name', 'keywords', 'foods', 'internal']
# class FoodFilter(django_filters.FilterSet):
# name = django_filters.CharFilter(lookup_expr='icontains')
# class Meta:
# model = Food
# fields = ['name']
class ShoppingListFilter(django_filters.FilterSet):
def __init__(self, data=None, *args, **kwargs):
if data is not None:
data = data.copy()
data.setdefault("finished", False)
super().__init__(data, *args, **kwargs)
class Meta:
model = ShoppingList
fields = ['finished']

View File

@@ -49,7 +49,7 @@ class UserPreferenceForm(forms.ModelForm):
fields = (
'default_unit', 'use_fractions', 'use_kj', 'theme', 'nav_color',
'sticky_navbar', 'default_page', 'show_recent', 'search_style',
'plan_share', 'ingredient_decimals', 'comments',
'plan_share', 'ingredient_decimals', 'comments', 'left_handed',
)
labels = {
@@ -65,7 +65,8 @@ class UserPreferenceForm(forms.ModelForm):
'plan_share': _('Plan sharing'),
'ingredient_decimals': _('Ingredient decimal places'),
'shopping_auto_sync': _('Shopping list auto sync period'),
'comments': _('Comments')
'comments': _('Comments'),
'left_handed': _('Left-handed mode')
}
help_texts = {
@@ -89,6 +90,7 @@ class UserPreferenceForm(forms.ModelForm):
'sticky_navbar': _('Makes the navbar stick to the top of the page.'), # noqa: E501
'mealplan_autoadd_shopping': _('Automatically add meal plan ingredients to shopping list.'),
'mealplan_autoexclude_onhand': _('Exclude ingredients that are on hand.'),
'left_handed': _('Will optimize the UI for use with your left hand.')
}
widgets = {
@@ -153,11 +155,13 @@ class ImportExportBase(forms.Form):
RECIPESAGE = 'RECIPESAGE'
DOMESTICA = 'DOMESTICA'
MEALMASTER = 'MEALMASTER'
MELARECIPES = 'MELARECIPES'
REZKONV = 'REZKONV'
OPENEATS = 'OPENEATS'
PLANTOEAT = 'PLANTOEAT'
COOKBOOKAPP = 'COOKBOOKAPP'
COPYMETHAT = 'COPYMETHAT'
COOKMATE = 'COOKMATE'
PDF = 'PDF'
type = forms.ChoiceField(choices=(
@@ -165,7 +169,8 @@ class ImportExportBase(forms.Form):
(MEALIE, 'Mealie'), (CHOWDOWN, 'Chowdown'), (SAFFRON, 'Saffron'), (CHEFTAP, 'ChefTap'),
(PEPPERPLATE, 'Pepperplate'), (RECETTETEK, 'RecetteTek'), (RECIPESAGE, 'Recipe Sage'), (DOMESTICA, 'Domestica'),
(MEALMASTER, 'MealMaster'), (REZKONV, 'RezKonv'), (OPENEATS, 'Openeats'), (RECIPEKEEPER, 'Recipe Keeper'),
(PLANTOEAT, 'Plantoeat'), (COOKBOOKAPP, 'CookBookApp'), (COPYMETHAT, 'CopyMeThat'), (PDF, 'PDF'),
(PLANTOEAT, 'Plantoeat'), (COOKBOOKAPP, 'CookBookApp'), (COPYMETHAT, 'CopyMeThat'), (PDF, 'PDF'), (MELARECIPES, 'Melarecipes'),
(COOKMATE, 'Cookmate')
))
@@ -179,6 +184,7 @@ class ImportForm(ImportExportBase):
class ExportForm(ImportExportBase):
recipes = forms.ModelMultipleChoiceField(widget=MultiSelectWidget, queryset=Recipe.objects.none(), required=False)
all = forms.BooleanField(required=False)
custom_filter = forms.IntegerField(required=False)
def __init__(self, *args, **kwargs):
space = kwargs.pop('space')

View File

@@ -38,10 +38,12 @@ def get_filetype(name):
# TODO this whole file needs proper documentation, refactoring, and testing
# TODO also add env variable to define which images sizes should be compressed
def handle_image(request, image_object, filetype='.jpeg'):
# filetype argument can not be optional, otherwise this function will treat all images as if they were a jpeg
# Because it's no longer optional, no reason to return it
def handle_image(request, image_object, filetype):
if (image_object.size / 1000) > 500: # if larger than 500 kb compress
if filetype == '.jpeg' or filetype == '.jpg':
return rescale_image_jpeg(image_object), filetype
return rescale_image_jpeg(image_object)
if filetype == '.png':
return rescale_image_png(image_object), filetype
return image_object, filetype
return rescale_image_png(image_object)
return image_object

View File

@@ -4,7 +4,7 @@ import unicodedata
from django.core.cache import caches
from cookbook.models import Unit, Food, Automation
from cookbook.models import Unit, Food, Automation, Ingredient
class IngredientParser:
@@ -46,7 +46,7 @@ class IngredientParser:
def apply_food_automation(self, food):
"""
Apply food alias automations to passed foood
Apply food alias automations to passed food
:param food: unit as string
:return: food as string (possibly changed by automation)
"""
@@ -124,7 +124,7 @@ class IngredientParser:
def parse_amount(self, x):
amount = 0
unit = ''
unit = None
note = ''
did_check_frac = False
@@ -155,33 +155,36 @@ class IngredientParser:
except ValueError:
unit = x[end:]
if unit.startswith('(') or unit.startswith('-'): # i dont know any unit that starts with ( or - so its likely an alternative like 1L (500ml) Water or 2-3
unit = ''
if unit is not None and unit.strip() == '':
unit = None
if unit is not None and (unit.startswith('(') or unit.startswith('-')): # i dont know any unit that starts with ( or - so its likely an alternative like 1L (500ml) Water or 2-3
unit = None
note = x
return amount, unit, note
def parse_ingredient_with_comma(self, tokens):
ingredient = ''
def parse_food_with_comma(self, tokens):
food = ''
note = ''
start = 0
# search for first occurrence of an argument ending in a comma
while start < len(tokens) and not tokens[start].endswith(','):
start += 1
if start == len(tokens):
# no token ending in a comma found -> use everything as ingredient
ingredient = ' '.join(tokens)
# no token ending in a comma found -> use everything as food
food = ' '.join(tokens)
else:
ingredient = ' '.join(tokens[:start + 1])[:-1]
food = ' '.join(tokens[:start + 1])[:-1]
note = ' '.join(tokens[start + 1:])
return ingredient, note
return food, note
def parse_ingredient(self, tokens):
ingredient = ''
def parse_food(self, tokens):
food = ''
note = ''
if tokens[-1].endswith(')'):
# Check if the matching opening bracket is in the same token
if (not tokens[-1].startswith('(')) and ('(' in tokens[-1]):
return self.parse_ingredient_with_comma(tokens)
return self.parse_food_with_comma(tokens)
# last argument ends with closing bracket -> look for opening bracket
start = len(tokens) - 1
while not tokens[start].startswith('(') and not start == 0:
@@ -191,33 +194,51 @@ class IngredientParser:
raise ValueError
elif start < 0:
# no opening bracket anywhere -> just ignore the last bracket
ingredient, note = self.parse_ingredient_with_comma(tokens)
food, note = self.parse_food_with_comma(tokens)
else:
# opening bracket found -> split in ingredient and note, remove brackets from note # noqa: E501
# opening bracket found -> split in food and note, remove brackets from note # noqa: E501
note = ' '.join(tokens[start:])[1:-1]
ingredient = ' '.join(tokens[:start])
food = ' '.join(tokens[:start])
else:
ingredient, note = self.parse_ingredient_with_comma(tokens)
return ingredient, note
food, note = self.parse_food_with_comma(tokens)
return food, note
def parse(self, x):
def parse(self, ingredient):
"""
Main parsing function, takes an ingredient string (e.g. '1 l Water') and extracts amount, unit, food, ...
:param ingredient: string ingredient
:return: amount, unit (can be None), food, note (can be empty)
"""
# initialize default values
amount = 0
unit = ''
ingredient = ''
unit = None
food = ''
note = ''
unit_note = ''
if len(ingredient) == 0:
raise ValueError('string to parse cannot be empty')
# some people/languages put amount and unit at the end of the ingredient string
# if something like this is detected move it to the beginning so the parser can handle it
if len(ingredient) < 1000 and re.search(r'^([A-z])+(.)*[1-9](\d)*\s([A-z])+', ingredient):
match = re.search(r'[1-9](\d)*\s([A-z])+', ingredient)
print(f'reording from {ingredient} to {ingredient[match.start():match.end()] + " " + ingredient.replace(ingredient[match.start():match.end()], "")}')
ingredient = ingredient[match.start():match.end()] + ' ' + ingredient.replace(ingredient[match.start():match.end()], '')
# if the string contains parenthesis early on remove it and place it at the end
# because its likely some kind of note
if re.match('(.){1,6}\s\((.[^\(\)])+\)\s', x):
match = re.search('\((.[^\(])+\)', x)
x = x[:match.start()] + x[match.end():] + ' ' + x[match.start():match.end()]
if re.match('(.){1,6}\s\((.[^\(\)])+\)\s', ingredient):
match = re.search('\((.[^\(])+\)', ingredient)
ingredient = ingredient[:match.start()] + ingredient[match.end():] + ' ' + ingredient[match.start():match.end()]
tokens = x.split()
# leading spaces before commas result in extra tokens, clean them out
ingredient = ingredient.replace(' ,', ',')
tokens = ingredient.split() # split at each space into tokens
if len(tokens) == 1:
# there only is one argument, that must be the ingredient
ingredient = tokens[0]
# there only is one argument, that must be the food
food = tokens[0]
else:
try:
# try to parse first argument as amount
@@ -227,48 +248,65 @@ class IngredientParser:
# a fraction for the amount
if len(tokens) > 2:
try:
if not unit == '':
if unit is not None:
# a unit is already found, no need to try the second argument for a fraction
# probably not the best method to do it, but I didn't want to make an if check and paste the exact same thing in the else as already is in the except # noqa: E501
# probably not the best method to do it, but I didn't want to make an if check and paste the exact same thing in the else as already is in the except
raise ValueError
# try to parse second argument as amount and add that, in case of '2 1/2' or '2 ½'
amount += self.parse_fraction(tokens[1])
# assume that units can't end with a comma
if len(tokens) > 3 and not tokens[2].endswith(','):
# try to use third argument as unit and everything else as ingredient, use everything as ingredient if it fails # noqa: E501
# try to use third argument as unit and everything else as food, use everything as food if it fails
try:
ingredient, note = self.parse_ingredient(tokens[3:])
food, note = self.parse_food(tokens[3:])
unit = tokens[2]
except ValueError:
ingredient, note = self.parse_ingredient(tokens[2:])
food, note = self.parse_food(tokens[2:])
else:
ingredient, note = self.parse_ingredient(tokens[2:])
food, note = self.parse_food(tokens[2:])
except ValueError:
# assume that units can't end with a comma
if not tokens[1].endswith(','):
# try to use second argument as unit and everything else as ingredient, use everything as ingredient if it fails # noqa: E501
# try to use second argument as unit and everything else as food, use everything as food if it fails
try:
ingredient, note = self.parse_ingredient(tokens[2:])
if unit == '':
food, note = self.parse_food(tokens[2:])
if unit is None:
unit = tokens[1]
else:
note = tokens[1]
except ValueError:
ingredient, note = self.parse_ingredient(tokens[1:])
food, note = self.parse_food(tokens[1:])
else:
ingredient, note = self.parse_ingredient(tokens[1:])
food, note = self.parse_food(tokens[1:])
else:
# only two arguments, first one is the amount
# which means this is the ingredient
ingredient = tokens[1]
# which means this is the food
food = tokens[1]
except ValueError:
try:
# can't parse first argument as amount
# -> no unit -> parse everything as ingredient
ingredient, note = self.parse_ingredient(tokens)
# -> no unit -> parse everything as food
food, note = self.parse_food(tokens)
except ValueError:
ingredient = ' '.join(tokens[1:])
food = ' '.join(tokens[1:])
if unit_note not in note:
note += ' ' + unit_note
return amount, self.apply_unit_automation(unit.strip()), self.apply_food_automation(ingredient.strip()), note.strip()
if unit:
unit = self.apply_unit_automation(unit.strip())
food = self.apply_food_automation(food.strip())
if len(food) > Food._meta.get_field('name').max_length: # test if food name is to long
# try splitting it at a space and taking only the first arg
if len(food.split()) > 1 and len(food.split()[0]) < Food._meta.get_field('name').max_length:
note = ' '.join(food.split()[1:]) + ' ' + note
food = food.split()[0]
else:
note = food + ' ' + note
food = food[:Food._meta.get_field('name').max_length]
if len(food.strip()) == 0:
raise ValueError(f'Error parsing string {ingredient}, food cannot be empty')
return amount, unit, food, note[:Ingredient._meta.get_field('note').max_length].strip()

View File

@@ -1,6 +1,3 @@
"""
Source: https://djangosnippets.org/snippets/1703/
"""
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import user_passes_test
@@ -12,7 +9,7 @@ from django.utils.translation import gettext as _
from rest_framework import permissions
from rest_framework.permissions import SAFE_METHODS
from cookbook.models import ShareLink
from cookbook.models import ShareLink, Recipe, UserPreference
def get_allowed_groups(groups_required):
@@ -262,3 +259,38 @@ class CustomIsShare(permissions.BasePermission):
if share:
return share_link_valid(obj, share)
return False
def above_space_limit(space): # TODO add file storage limit
"""
Test if the space has reached any limit (e.g. max recipes, users, ..)
:param space: Space to test for limits
:return: Tuple (True if above or equal any limit else false, message)
"""
r_limit, r_msg = above_space_recipe_limit(space)
u_limit, u_msg = above_space_user_limit(space)
return r_limit or u_limit, (r_msg + ' ' + u_msg).strip()
def above_space_recipe_limit(space):
"""
Test if a space has reached its recipe limit
:param space: Space to test for limits
:return: Tuple (True if above or equal limit else false, message)
"""
limit = space.max_recipes != 0 and Recipe.objects.filter(space=space).count() >= space.max_recipes
if limit:
return True, _('You have reached the maximum number of recipes for your space.')
return False, ''
def above_space_user_limit(space):
"""
Test if a space has reached its user limit
:param space: Space to test for limits
:return: Tuple (True if above or equal limit else false, message)
"""
limit = space.max_users != 0 and UserPreference.objects.filter(space=space).count() > space.max_users
if limit:
return True, _('You have more users than allowed in your space.')
return False, ''

View File

@@ -9,6 +9,8 @@ from recipe_scrapers._utils import get_host_name, normalize_string
from cookbook.helper import recipe_url_import as helper
from cookbook.helper.scrapers.scrapers import text_scraper
from recipe_scrapers import scrape_me
from recipe_scrapers._exceptions import NoSchemaFoundInWildMode
def get_recipe_from_source(text, url, request):
@@ -58,51 +60,46 @@ def get_recipe_from_source(text, url, request):
})
return kid_list
recipe_json = {
'name': '',
'url': '',
'description': '',
'image': '',
'keywords': [],
'recipeIngredient': [],
'recipeInstructions': '',
'servings': '',
'prepTime': '',
'cookTime': ''
}
recipe_tree = []
parse_list = []
html_data = []
images = []
text = unquote(text)
scrape = None
try:
parse_list.append(remove_graph(json.loads(text)))
if not url and 'url' in parse_list[0]:
url = parse_list[0]['url']
scrape = text_scraper("<script type='application/ld+json'>" + text + "</script>", url=url)
if url:
try:
scrape = scrape_me(url_path=url, wild_mode=True)
except(NoSchemaFoundInWildMode):
pass
if not scrape:
try:
parse_list.append(remove_graph(json.loads(text)))
if not url and 'url' in parse_list[0]:
url = parse_list[0]['url']
scrape = text_scraper("<script type='application/ld+json'>" + text + "</script>", url=url)
except JSONDecodeError:
soup = BeautifulSoup(text, "html.parser")
html_data = get_from_html(soup)
images += get_images_from_source(soup, url)
for el in soup.find_all('script', type='application/ld+json'):
el = remove_graph(el)
if not url and 'url' in el:
url = el['url']
if type(el) == list:
for le in el:
parse_list.append(le)
elif type(el) == dict:
parse_list.append(el)
for el in soup.find_all(type='application/json'):
el = remove_graph(el)
if type(el) == list:
for le in el:
parse_list.append(le)
elif type(el) == dict:
parse_list.append(el)
scrape = text_scraper(text, url=url)
except JSONDecodeError:
soup = BeautifulSoup(text, "html.parser")
html_data = get_from_html(soup)
images += get_images_from_source(soup, url)
for el in soup.find_all('script', type='application/ld+json'):
el = remove_graph(el)
if not url and 'url' in el:
url = el['url']
if type(el) == list:
for le in el:
parse_list.append(le)
elif type(el) == dict:
parse_list.append(el)
for el in soup.find_all(type='application/json'):
el = remove_graph(el)
if type(el) == list:
for le in el:
parse_list.append(le)
elif type(el) == dict:
parse_list.append(el)
scrape = text_scraper(text, url=url)
recipe_json = helper.get_from_scraper(scrape, request)

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,10 @@
import random
import re
from html import unescape
from unicodedata import decomposition
from django.utils.dateparse import parse_duration
from django.utils.translation import gettext as _
from isodate import parse_duration as iso_parse_duration
from isodate.isoerror import ISO8601Error
from recipe_scrapers._utils import get_minutes
@@ -12,6 +14,9 @@ from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.models import Keyword
# from recipe_scrapers._utils import get_minutes ## temporary until/unless upstream incorporates get_minutes() PR
def get_from_scraper(scrape, request):
# converting the scrape_me object to the existing json format based on ld+json
recipe_json = {}
@@ -26,11 +31,16 @@ def get_from_scraper(scrape, request):
recipe_json['name'] = ''
try:
description = scrape.schema.data.get("description") or ''
description = scrape.description() or None
except Exception:
description = ''
description = None
if not description:
try:
description = scrape.schema.data.get("description") or ''
except Exception:
description = ''
recipe_json['description'] = parse_description(description)
recipe_json['internal'] = True
try:
servings = scrape.yields() or None
@@ -41,28 +51,31 @@ def get_from_scraper(scrape, request):
servings = scrape.schema.data.get('recipeYield') or 1
except Exception:
servings = 1
if type(servings) != int:
recipe_json['servings'] = parse_servings(servings)
recipe_json['servings_text'] = parse_servings_text(servings)
try:
recipe_json['working_time'] = get_minutes(scrape.prep_time()) or 0
except Exception:
try:
servings = int(re.findall(r'\b\d+\b', servings)[0])
recipe_json['working_time'] = get_minutes(scrape.schema.data.get("prepTime")) or 0
except Exception:
servings = 1
recipe_json['servings'] = max(servings, 1)
recipe_json['working_time'] = 0
try:
recipe_json['prepTime'] = get_minutes(scrape.schema.data.get("prepTime")) or 0
recipe_json['waiting_time'] = get_minutes(scrape.cook_time()) or 0
except Exception:
recipe_json['prepTime'] = 0
try:
recipe_json['cookTime'] = get_minutes(scrape.schema.data.get("cookTime")) or 0
except Exception:
recipe_json['cookTime'] = 0
if recipe_json['cookTime'] + recipe_json['prepTime'] == 0:
try:
recipe_json['prepTime'] = get_minutes(scrape.total_time()) or 0
recipe_json['waiting_time'] = get_minutes(scrape.schema.data.get("cookTime")) or 0
except Exception:
recipe_json['waiting_time'] = 0
if recipe_json['working_time'] + recipe_json['waiting_time'] == 0:
try:
recipe_json['working_time'] = get_minutes(scrape.total_time()) or 0
except Exception:
try:
get_minutes(scrape.schema.data.get("totalTime")) or 0
recipe_json['working_time'] = get_minutes(scrape.schema.data.get("totalTime")) or 0
except Exception:
pass
@@ -83,15 +96,38 @@ def get_from_scraper(scrape, request):
except Exception:
pass
try:
if scrape.schema.data.get('recipeCategory'):
keywords += listify_keywords(scrape.schema.data.get("recipeCategory"))
if scrape.category():
keywords += listify_keywords(scrape.category())
except Exception:
pass
try:
if scrape.schema.data.get('recipeCategory'):
keywords += listify_keywords(scrape.schema.data.get("recipeCategory"))
except Exception:
pass
try:
if scrape.schema.data.get('recipeCuisine'):
keywords += listify_keywords(scrape.schema.data.get("recipeCuisine"))
if scrape.cuisine():
keywords += listify_keywords(scrape.cuisine())
except Exception:
pass
try:
if scrape.schema.data.get('recipeCuisine'):
keywords += listify_keywords(scrape.schema.data.get("recipeCuisine"))
except Exception:
pass
try:
source_url = scrape.canonical_url()
except Exception:
try:
source_url = scrape.url
except Exception:
pass
if source_url:
recipe_json['source_url'] = source_url
try:
keywords.append(source_url.replace('http://', '').replace('https://', '').split('/')[0])
except Exception:
pass
try:
recipe_json['keywords'] = parse_keywords(list(set(map(str.casefold, keywords))), request.space)
except AttributeError:
@@ -99,54 +135,51 @@ def get_from_scraper(scrape, request):
ingredient_parser = IngredientParser(request, True)
ingredients = []
recipe_json['steps'] = []
try:
for i in parse_instructions(scrape.instructions()):
recipe_json['steps'].append({'instruction': i, 'ingredients': [], })
except Exception:
pass
if len(recipe_json['steps']) == 0:
recipe_json['steps'].append({'instruction': '', 'ingredients': [], })
if len(parse_description(description)) > 256: # split at 256 as long descriptions dont look good on recipe cards
recipe_json['steps'][0]['instruction'] = f'*{parse_description(description)}* \n\n' + recipe_json['steps'][0]['instruction']
else:
recipe_json['description'] = parse_description(description)[:512]
try:
for x in scrape.ingredients():
try:
amount, unit, ingredient, note = ingredient_parser.parse(x)
ingredients.append(
{
'amount': amount,
'unit': {
'text': unit,
'id': random.randrange(10000, 99999)
},
'ingredient': {
'text': ingredient,
'id': random.randrange(10000, 99999)
},
'note': note,
'original': x
}
)
ingredient = {
'amount': amount,
'food': {
'name': ingredient,
},
'unit': None,
'note': note,
'original_text': x
}
if unit:
ingredient['unit'] = {'name': unit, }
recipe_json['steps'][0]['ingredients'].append(ingredient)
except Exception:
ingredients.append(
recipe_json['steps'][0]['ingredients'].append(
{
'amount': 0,
'unit': {
'text': '',
'id': random.randrange(10000, 99999)
},
'ingredient': {
'text': x,
'id': random.randrange(10000, 99999)
'unit': None,
'food': {
'name': x,
},
'note': '',
'original': x
'original_text': x
}
)
recipe_json['recipeIngredient'] = ingredients
except Exception:
recipe_json['recipeIngredient'] = ingredients
pass
try:
recipe_json['recipeInstructions'] = parse_instructions(scrape.instructions())
except Exception:
recipe_json['recipeInstructions'] = ""
if scrape.url:
recipe_json['url'] = scrape.url
recipe_json['recipeInstructions'] += "\n\nImported from " + scrape.url
return recipe_json
@@ -159,102 +192,46 @@ def parse_name(name):
return normalize_string(name)
def parse_ingredients(ingredients):
# some pages have comma separated ingredients in a single array entry
try:
if type(ingredients[0]) == dict:
return ingredients
except (KeyError, IndexError):
pass
if (len(ingredients) == 1 and type(ingredients) == list):
ingredients = ingredients[0].split(',')
elif type(ingredients) == str:
ingredients = ingredients.split(',')
for x in ingredients:
if '\n' in x:
ingredients.remove(x)
for i in x.split('\n'):
ingredients.insert(0, i)
ingredient_list = []
for x in ingredients:
if x.replace(' ', '') != '':
x = x.replace('&frac12;', "0.5").replace('&frac14;', "0.25").replace('&frac34;', "0.75")
try:
amount, unit, ingredient, note = parse_single_ingredient(x)
if ingredient:
ingredient_list.append(
{
'amount': amount,
'unit': {
'text': unit,
'id': random.randrange(10000, 99999)
},
'ingredient': {
'text': ingredient,
'id': random.randrange(10000, 99999)
},
'note': note,
'original': x
}
)
except Exception:
ingredient_list.append(
{
'amount': 0,
'unit': {
'text': '',
'id': random.randrange(10000, 99999)
},
'ingredient': {
'text': x,
'id': random.randrange(10000, 99999)
},
'note': '',
'original': x
}
)
ingredients = ingredient_list
else:
ingredients = []
return ingredients
def parse_description(description):
return normalize_string(description)
def parse_instructions(instructions):
instruction_text = ''
# flatten instructions if they are in a list
if type(instructions) == list:
for i in instructions:
if type(i) == str:
instruction_text += i
else:
if 'text' in i:
instruction_text += i['text'] + '\n\n'
elif 'itemListElement' in i:
for ile in i['itemListElement']:
if type(ile) == str:
instruction_text += ile + '\n\n'
elif 'text' in ile:
instruction_text += ile['text'] + '\n\n'
else:
instruction_text += str(i)
instructions = instruction_text
normalized_string = normalize_string(instructions)
def clean_instruction_string(instruction):
normalized_string = normalize_string(instruction)
normalized_string = normalized_string.replace('\n', ' \n')
normalized_string = normalized_string.replace(' \n \n', '\n\n')
return normalized_string
def parse_instructions(instructions):
"""
Convert arbitrary instructions object from website import and turn it into a flat list of strings
:param instructions: any instructions object from import
:return: list of strings (from one to many elements depending on website)
"""
instruction_list = []
if type(instructions) == list:
for i in instructions:
if type(i) == str:
instruction_list.append(clean_instruction_string(i))
else:
if 'text' in i:
instruction_list.append(clean_instruction_string(i['text']))
elif 'itemListElement' in i:
for ile in i['itemListElement']:
if type(ile) == str:
instruction_list.append(clean_instruction_string(ile))
elif 'text' in ile:
instruction_list.append(clean_instruction_string(ile['text']))
else:
instruction_list.append(clean_instruction_string(str(i)))
else:
instruction_list.append(clean_instruction_string(instructions))
return instruction_list
def parse_image(image):
# check if list of images is returned, take first if so
if not image:
@@ -289,40 +266,31 @@ def parse_servings(servings):
return servings
def parse_cooktime(cooktime):
if type(cooktime) not in [int, float]:
def parse_servings_text(servings):
if type(servings) == str:
try:
cooktime = float(re.search(r'\d+', cooktime).group())
servings = re.sub("\d+", '', servings).strip()
except Exception:
servings = ''
return servings
def parse_time(recipe_time):
if type(recipe_time) not in [int, float]:
try:
recipe_time = float(re.search(r'\d+', recipe_time).group())
except (ValueError, AttributeError):
try:
cooktime = round(iso_parse_duration(cooktime).seconds / 60)
recipe_time = round(iso_parse_duration(recipe_time).seconds / 60)
except ISO8601Error:
try:
if (type(cooktime) == list and len(cooktime) > 0):
cooktime = cooktime[0]
cooktime = round(parse_duration(cooktime).seconds / 60)
if (type(recipe_time) == list and len(recipe_time) > 0):
recipe_time = recipe_time[0]
recipe_time = round(parse_duration(recipe_time).seconds / 60)
except AttributeError:
cooktime = 0
recipe_time = 0
return cooktime
def parse_preptime(preptime):
if type(preptime) not in [int, float]:
try:
preptime = float(re.search(r'\d+', preptime).group())
except ValueError:
try:
preptime = round(iso_parse_duration(preptime).seconds / 60)
except ISO8601Error:
try:
if (type(preptime) == list and len(preptime) > 0):
preptime = preptime[0]
preptime = round(parse_duration(preptime).seconds / 60)
except AttributeError:
preptime = 0
return preptime
return recipe_time
def parse_keywords(keyword_json, space):
@@ -332,9 +300,9 @@ def parse_keywords(keyword_json, space):
kw = normalize_string(kw)
if len(kw) != 0:
if k := Keyword.objects.filter(name=kw, space=space).first():
keywords.append({'id': str(k.id), 'text': str(k)})
keywords.append({'label': str(k), 'name': k.name, 'id': k.id})
else:
keywords.append({'id': random.randrange(1111111, 9999999, 1), 'text': kw})
keywords.append({'label': kw, 'name': kw})
return keywords

View File

@@ -1,6 +1,6 @@
from bs4 import BeautifulSoup
from json import JSONDecodeError
from recipe_scrapers import SCRAPERS, get_host_name
from recipe_scrapers import SCRAPERS
from recipe_scrapers._factory import SchemaScraperFactory
from recipe_scrapers._schemaorg import SchemaOrg
@@ -15,13 +15,7 @@ SCRAPERS.update(CUSTOM_SCRAPERS)
def text_scraper(text, url=None):
domain = None
if url:
domain = get_host_name(url)
if domain in SCRAPERS:
scraper_class = SCRAPERS[domain]
else:
scraper_class = SchemaScraperFactory.SchemaScraper
scraper_class = SchemaScraperFactory.SchemaScraper
class TextScraper(scraper_class):
def __init__(

View File

@@ -35,7 +35,7 @@ def shopping_helper(qs, request):
qs = qs.filter(Q(checked=False) | Q(completed_at__gte=week_ago))
supermarket_order = ['checked'] + supermarket_order
return qs.order_by(*supermarket_order).select_related('unit', 'food', 'ingredient', 'created_by', 'list_recipe', 'list_recipe__mealplan', 'list_recipe__recipe')
return qs.distinct().order_by(*supermarket_order).select_related('unit', 'food', 'ingredient', 'created_by', 'list_recipe', 'list_recipe__mealplan', 'list_recipe__recipe')
class RecipeShoppingEditor():
@@ -65,9 +65,13 @@ class RecipeShoppingEditor():
except (ValueError, TypeError):
self.servings = getattr(self._shopping_list_recipe, 'servings', None) or getattr(self.mealplan, 'servings', None) or getattr(self.recipe, 'servings', None)
@property
def _recipe_servings(self):
return getattr(self.recipe, 'servings', None) or getattr(getattr(self.mealplan, 'recipe', None), 'servings', None) or getattr(getattr(self._shopping_list_recipe, 'recipe', None), 'servings', None)
@property
def _servings_factor(self):
return self.servings / self.recipe.servings
return Decimal(self.servings)/Decimal(self._recipe_servings)
@property
def _shared_users(self):

View File

@@ -1,11 +1,14 @@
from gettext import gettext as _
import bleach
import markdown as md
from bleach_allowlist import markdown_attrs, markdown_tags
from jinja2 import Template, TemplateSyntaxError, UndefinedError
from markdown.extensions.tables import TableExtension
from cookbook.helper.mdx_attributes import MarkdownFormatExtension
from cookbook.helper.mdx_urlize import UrlizeExtension
from jinja2 import Template, TemplateSyntaxError, UndefinedError
from gettext import gettext as _
from markdown.extensions.tables import TableExtension
class IngredientObject(object):
amount = ""
@@ -36,7 +39,7 @@ def render_instructions(step): # TODO deduplicate markdown cleanup code
instructions = step.instruction
tags = markdown_tags + [
'pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead'
'pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead', 'img'
]
parsed_md = md.markdown(
instructions,
@@ -45,7 +48,7 @@ def render_instructions(step): # TODO deduplicate markdown cleanup code
UrlizeExtension(), MarkdownFormatExtension()
]
)
markdown_attrs['*'] = markdown_attrs['*'] + ['class']
markdown_attrs['*'] = markdown_attrs['*'] + ['class', 'width', 'height']
instructions = bleach.clean(parsed_md, tags, markdown_attrs)

View File

@@ -2,14 +2,14 @@ import re
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient
from cookbook.models import Ingredient, Recipe, Step
class ChefTap(Integration):
def import_file_name_filter(self, zip_info_object):
print("testing", zip_info_object.filename)
return re.match(r'^cheftap_export/([A-Za-z\d\w\s-])+.txt$', zip_info_object.filename) or re.match(r'^([A-Za-z\d\w\s-])+.txt$', zip_info_object.filename)
return re.match(r'^cheftap_export/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.txt$', zip_info_object.filename) or re.match(r'^([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.txt$', zip_info_object.filename)
def get_recipe_from_file(self, file):
source_url = ''
@@ -45,11 +45,11 @@ class ChefTap(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
if len(ingredient.strip()) > 0:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)

View File

@@ -5,14 +5,14 @@ from zipfile import ZipFile
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class Chowdown(Integration):
def import_file_name_filter(self, zip_info_object):
print("testing", zip_info_object.filename)
return re.match(r'^(_)*recipes/([A-Za-z\d\s-])+.md$', zip_info_object.filename)
return re.match(r'^(_)*recipes/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.md$', zip_info_object.filename)
def get_recipe_from_file(self, file):
ingredient_mode = False
@@ -60,12 +60,13 @@ class Chowdown(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
))
if len(ingredient.strip()) > 0:
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)
for f in self.files:

View File

@@ -2,17 +2,18 @@ import base64
import gzip
import json
import re
from gettext import gettext as _
from io import BytesIO
import requests
import validators
import yaml
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_html_import import get_recipe_from_source
from cookbook.helper.recipe_url_import import iso_duration_to_minutes
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from gettext import gettext as _
from cookbook.models import Ingredient, Keyword, Recipe, Step
class CookBookApp(Integration):
@@ -51,16 +52,18 @@ class CookBookApp(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in recipe_json['recipeIngredient']:
f = ingredient_parser.get_food(ingredient['ingredient']['text'])
u = ingredient_parser.get_unit(ingredient['unit']['text'])
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=ingredient['amount'], note=ingredient['note'], space=self.request.space,
))
f = ingredient_parser.get_food(ingredient['ingredient']['text'])
u = ingredient_parser.get_unit(ingredient['unit']['text'])
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=ingredient['amount'], note=ingredient['note'], space=self.request.space,
))
if len(images) > 0:
try:
response = requests.get(images[0])
self.import_recipe_image(recipe, BytesIO(response.content))
url = images[0]
if validators.url(url, public=True):
response = requests.get(url)
self.import_recipe_image(recipe, BytesIO(response.content))
except Exception as e:
print('failed to import image ', str(e))

View File

@@ -0,0 +1,80 @@
import base64
import json
from io import BytesIO
from gettext import gettext as _
import requests
import validators
from lxml import etree
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, parse_time, parse_servings_text
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Keyword, Recipe, Step
class Cookmate(Integration):
def import_file_name_filter(self, zip_info_object):
return zip_info_object.filename.endswith('.xml')
def get_files_from_recipes(self, recipes, el, cookie):
raise NotImplementedError('Method not implemented in storage integration')
def get_recipe_from_file(self, file):
recipe_xml = file
recipe = Recipe.objects.create(
name=recipe_xml.find('title').text.strip(),
created_by=self.request.user, internal=True, space=self.request.space)
if recipe_xml.find('preptime') is not None and recipe_xml.find('preptime').text is not None:
recipe.working_time = parse_time(recipe_xml.find('preptime').text.strip())
if recipe_xml.find('cooktime') is not None and recipe_xml.find('cooktime').text is not None:
recipe.waiting_time = parse_time(recipe_xml.find('cooktime').text.strip())
if recipe_xml.find('quantity') is not None and recipe_xml.find('quantity').text is not None:
recipe.servings = parse_servings(recipe_xml.find('quantity').text.strip())
recipe.servings_text = parse_servings_text(recipe_xml.find('quantity').text.strip())
if recipe_xml.find('url') is not None and recipe_xml.find('url').text is not None:
recipe.source_url = recipe_xml.find('url').text.strip()
if recipe_xml.find('description') is not None: # description is a list of <li>'s with text
if len(recipe_xml.find('description')) > 0:
recipe.description = recipe_xml.find('description')[0].text[:512]
for step in recipe_xml.find('recipetext').getchildren():
step = Step.objects.create(
instruction=step.text.strip(), space=self.request.space,
)
recipe.steps.add(step)
ingredient_parser = IngredientParser(self.request, True)
for ingredient in recipe_xml.find('ingredient').getchildren():
if ingredient.text.strip() != '':
amount, unit, food, note = ingredient_parser.parse(ingredient.text.strip())
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
recipe.steps.first().ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, original_text=ingredient.text.strip(), space=self.request.space,
))
if recipe_xml.find('imageurl') is not None:
try:
url = recipe_xml.find('imageurl').text.strip()
if validators.url(url, public=True):
response = requests.get(url)
self.import_recipe_image(recipe, BytesIO(response.content))
except Exception as e:
print('failed to import image ', str(e))
recipe.save()
return recipe
def get_file_from_recipe(self, recipe):
raise NotImplementedError('Method not implemented in storage integration')

View File

@@ -4,11 +4,12 @@ from zipfile import ZipFile
from bs4 import BeautifulSoup
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_html_import import get_recipe_from_source
from cookbook.helper.recipe_url_import import iso_duration_to_minutes, parse_servings
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
from recipes.settings import DEBUG
@@ -31,7 +32,14 @@ class CopyMeThat(Integration):
recipe.servings = parse_servings(file.find("a", {"id": "recipeYield"}).text.strip())
recipe.working_time = iso_duration_to_minutes(file.find("span", {"meta": "prepTime"}).text.strip())
recipe.waiting_time = iso_duration_to_minutes(file.find("span", {"meta": "cookTime"}).text.strip())
recipe.save()
recipe.description = (file.find("div ", {"id": "description"}).text.strip())[:512]
except AttributeError:
pass
try:
if len(file.find("span", {"id": "starred"}).text.strip()) > 0:
recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=_('Favorite'))[0])
except AttributeError:
pass
@@ -41,11 +49,11 @@ class CopyMeThat(Integration):
for ingredient in file.find_all("li", {"class": "recipeIngredient"}):
if ingredient.text == "":
continue
amount, unit, ingredient, note = ingredient_parser.parse(ingredient.text.strip())
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient.text.strip())
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient.text.strip(), space=self.request.space,
))
for s in file.find_all("li", {"class": "instruction"}):
@@ -60,7 +68,7 @@ class CopyMeThat(Integration):
try:
if file.find("a", {"id": "original_link"}).text != '':
step.instruction += "\n\nImported from: " + file.find("a", {"id": "original_link"}).text
step.instruction += "\n\n" + _("Imported from") + ": " + file.find("a", {"id": "original_link"}).text
step.save()
except AttributeError:
pass

View File

@@ -4,7 +4,7 @@ from io import BytesIO
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient
from cookbook.models import Ingredient, Recipe, Step
class Domestica(Integration):
@@ -37,11 +37,11 @@ class Domestica(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in file['ingredients'].split('\n'):
if len(ingredient.strip()) > 0:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)

View File

@@ -5,6 +5,8 @@ import traceback
import uuid
from io import BytesIO, StringIO
from zipfile import BadZipFile, ZipFile
import lxml
from django.core.cache import cache
import datetime
@@ -16,6 +18,7 @@ from django.http import HttpResponse
from django.utils.formats import date_format
from django.utils.translation import gettext as _
from django_scopes import scope
from lxml import etree
from cookbook.forms import ImportExportBase
from cookbook.helper.image_processing import get_filetype, handle_image
@@ -144,7 +147,7 @@ class Integration:
il.imported_recipes += 1
il.save()
import_zip.close()
elif '.zip' in f['name'] or '.paprikarecipes' in f['name']:
elif '.zip' in f['name'] or '.paprikarecipes' in f['name'] or '.mcb' in f['name']:
import_zip = ZipFile(f['file'])
file_list = []
for z in import_zip.filelist:
@@ -157,9 +160,16 @@ class Integration:
file_list = self.split_recipe_file(BytesIO(import_zip.read('recipes.html')))
il.total_recipes += len(file_list)
if isinstance(self, cookbook.integration.cookmate.Cookmate):
new_file_list = []
for file in file_list:
new_file_list += etree.parse(BytesIO(import_zip.read(file.filename))).getroot().getchildren()
il.total_recipes = len(new_file_list)
file_list = new_file_list
for z in file_list:
try:
if isinstance(z, Tag):
if not hasattr(z, 'filename'):
recipe = self.get_recipe_from_file(z)
else:
recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z.filename)))
@@ -172,7 +182,7 @@ class Integration:
traceback.print_exc()
self.handle_exception(e, log=il, message=f'-------------------- \nERROR \n{e}\n--------------------\n')
import_zip.close()
elif '.json' in f['name'] or '.txt' in f['name'] or '.mmf' in f['name']:
elif '.json' in f['name'] or '.txt' in f['name'] or '.mmf' in f['name'] or '.rk' in f['name'] or '.melarecipe' in f['name']:
data_list = self.split_recipe_file(f['file'])
il.total_recipes += len(data_list)
for d in data_list:
@@ -243,7 +253,7 @@ class Integration:
:param image_file: ByteIO stream containing the image
:param filetype: type of file to write bytes to, default to .jpeg if unknown
"""
recipe.image = File(handle_image(self.request, File(image_file, name='image'), filetype=filetype)[0], name=f'{uuid.uuid4()}_{recipe.pk}{filetype}')
recipe.image = File(handle_image(self.request, File(image_file, name='image'), filetype=filetype), name=f'{uuid.uuid4()}_{recipe.pk}{filetype}')
recipe.save()
def get_recipe_from_file(self, file):

View File

@@ -6,13 +6,13 @@ from zipfile import ZipFile
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient
from cookbook.models import Ingredient, Recipe, Step
class Mealie(Integration):
def import_file_name_filter(self, zip_info_object):
return re.match(r'^recipes/([A-Za-z\d-])+/([A-Za-z\d-])+.json$', zip_info_object.filename)
return re.match(r'^recipes/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.json$', zip_info_object.filename)
def get_recipe_from_file(self, file):
recipe_json = json.loads(file.getvalue().decode("utf-8"))
@@ -45,12 +45,14 @@ class Mealie(Integration):
u = ingredient_parser.get_unit(ingredient['unit'])
amount = ingredient['quantity']
note = ingredient['note']
original_text = None
else:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient['note'])
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient['note'])
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
original_text = ingredient['note']
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=original_text, space=self.request.space,
))
except Exception:
pass
@@ -60,7 +62,8 @@ class Mealie(Integration):
if '.zip' in f['name']:
import_zip = ZipFile(f['file'])
try:
self.import_recipe_image(recipe, BytesIO(import_zip.read(f'recipes/{recipe_json["slug"]}/images/min-original.webp')), filetype=get_filetype(f'recipes/{recipe_json["slug"]}/images/original'))
self.import_recipe_image(recipe, BytesIO(import_zip.read(f'recipes/{recipe_json["slug"]}/images/min-original.webp')),
filetype=get_filetype(f'recipes/{recipe_json["slug"]}/images/original'))
except Exception:
pass

View File

@@ -2,7 +2,7 @@ import re
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class MealMaster(Integration):
@@ -45,11 +45,11 @@ class MealMaster(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
if len(ingredient.strip()) > 0:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)

View File

@@ -0,0 +1,83 @@
import base64
import json
from io import BytesIO
from gettext import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, parse_time
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Keyword, Recipe, Step
class MelaRecipes(Integration):
def split_recipe_file(self, file):
return [json.loads(file.getvalue().decode("utf-8"))]
def get_files_from_recipes(self, recipes, el, cookie):
raise NotImplementedError('Method not implemented in storage integration')
def get_recipe_from_file(self, file):
recipe_json = file
recipe = Recipe.objects.create(
name=recipe_json['title'].strip(),
created_by=self.request.user, internal=True, space=self.request.space)
if 'yield' in recipe_json:
recipe.servings = parse_servings(recipe_json['yield'])
if 'cookTime' in recipe_json:
recipe.waiting_time = parse_time(recipe_json['cookTime'])
if 'prepTime' in recipe_json:
recipe.working_time = parse_time(recipe_json['prepTime'])
if 'favorite' in recipe_json and recipe_json['favorite']:
recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=_('Favorite'))[0])
if 'categories' in recipe_json:
try:
for x in recipe_json['categories']:
recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=x)[0])
except Exception:
pass
instruction = ''
if 'text' in recipe_json:
instruction += f'*{recipe_json["text"].strip()}* \n'
if 'instructions' in recipe_json:
instruction += recipe_json["instructions"].strip() + ' \n'
if 'notes' in recipe_json:
instruction += recipe_json["notes"].strip() + ' \n'
if 'link' in recipe_json:
recipe.source_url = recipe_json['link']
step = Step.objects.create(
instruction=instruction, space=self.request.space,
)
ingredient_parser = IngredientParser(self.request, True)
for ingredient in recipe_json['ingredients'].split('\n'):
if ingredient.strip() != '':
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)
if recipe_json.get("images", None):
try:
self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_json['images'][0])), filetype='.jpeg')
except Exception:
pass
return recipe
def get_file_from_recipe(self, recipe):
raise NotImplementedError('Method not implemented in storage integration')

View File

@@ -7,7 +7,7 @@ from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import iso_duration_to_minutes
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class NextcloudCookbook(Integration):
@@ -31,6 +31,9 @@ class NextcloudCookbook(Integration):
except Exception:
pass
if 'url' in recipe_json:
recipe.source_url = recipe_json['url'].strip()
if 'recipeCategory' in recipe_json:
try:
recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=recipe_json['recipeCategory'])[0])
@@ -40,7 +43,8 @@ class NextcloudCookbook(Integration):
if 'keywords' in recipe_json:
try:
for x in recipe_json['keywords'].split(','):
recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=x)[0])
if x.strip() != '':
recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=x)[0])
except Exception:
pass
@@ -57,11 +61,11 @@ class NextcloudCookbook(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in recipe_json['recipeIngredient']:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)

View File

@@ -2,7 +2,7 @@ import json
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient
from cookbook.models import Ingredient, Recipe, Step
class OpenEats(Integration):

View File

@@ -2,12 +2,13 @@ import base64
import gzip
import json
import re
from gettext import gettext as _
from io import BytesIO
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from gettext import gettext as _
from cookbook.models import Ingredient, Keyword, Recipe, Step
class Paprika(Integration):
@@ -26,10 +27,9 @@ class Paprika(Integration):
recipe.description = '' if len(recipe_json['description'].strip()) > 500 else recipe_json['description'].strip()
try:
if re.match(r'([0-9])+\s(.)*', recipe_json['servings']):
s = recipe_json['servings'].split(' ')
recipe.servings = s[0]
recipe.servings_text = s[1]
if 'servings' in recipe_json:
recipe.servings = parse_servings(recipe_json['servings'])
recipe.servings_text = parse_servings_text(recipe_json['servings'])
if len(recipe_json['cook_time'].strip()) > 0:
recipe.waiting_time = re.findall(r'\d+', recipe_json['cook_time'])[0]
@@ -70,11 +70,11 @@ class Paprika(Integration):
try:
for ingredient in recipe_json['ingredients'].split('\n'):
if len(ingredient.strip()) > 0:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
except AttributeError:
pass

View File

@@ -1,6 +1,6 @@
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient
from cookbook.models import Ingredient, Recipe, Step
class Pepperplate(Integration):
@@ -41,11 +41,11 @@ class Pepperplate(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
if len(ingredient.strip()) > 0:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)

View File

@@ -4,7 +4,7 @@ import requests
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class Plantoeat(Integration):
@@ -49,6 +49,7 @@ class Plantoeat(Integration):
)
if tags:
tags = tags.replace('^',',')
for k in tags.split(','):
keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space)
recipe.keywords.add(keyword)
@@ -56,11 +57,11 @@ class Plantoeat(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
if len(ingredient.strip()) > 0:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)
@@ -78,7 +79,11 @@ class Plantoeat(Integration):
current_recipe = ''
for fl in file.readlines():
line = fl.decode("windows-1250")
try:
line = fl.decode("utf-8")
except UnicodeDecodeError:
line = fl.decode("windows-1250")
if line.startswith('--------------'):
if current_recipe != '':
recipe_list.append(current_recipe)

View File

@@ -1,14 +1,17 @@
import re
import imghdr
import json
import requests
import re
from io import BytesIO
from zipfile import ZipFile
import imghdr
import requests
import validators
from django.utils.translation import gettext as _
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class RecetteTek(Integration):
@@ -48,7 +51,7 @@ class RecetteTek(Integration):
# Append the original import url to the step (if it exists)
try:
if file['url'] != '':
step.instruction += '\n\nImported from: ' + file['url']
step.instruction += '\n\n' + _('Imported from') + ': ' + file['url']
step.save()
except Exception as e:
print(recipe.name, ': failed to import source url ', str(e))
@@ -58,11 +61,11 @@ class RecetteTek(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in file['ingredients'].split('\n'):
if len(ingredient.strip()) > 0:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
amount, unit, food, note = ingredient_parser.parse(food)
f = ingredient_parser.get_food(ingredient)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
except Exception as e:
print(recipe.name, ': failed to parse recipe ingredients ', str(e))
@@ -121,11 +124,13 @@ class RecetteTek(Integration):
self.import_recipe_image(recipe, BytesIO(import_zip.read(image_file_name)), filetype=get_filetype(image_file_name))
else:
if file['originalPicture'] != '':
response = requests.get(file['originalPicture'])
if imghdr.what(BytesIO(response.content)) is not None:
self.import_recipe_image(recipe, BytesIO(response.content), filetype=get_filetype(file['originalPicture']))
else:
raise Exception("Original image failed to download.")
url = file['originalPicture']
if validators.url(url, public=True):
response = requests.get(url)
if imghdr.what(BytesIO(response.content)) is not None:
self.import_recipe_image(recipe, BytesIO(response.content), filetype=get_filetype(file['originalPicture']))
else:
raise Exception("Original image failed to download.")
except Exception as e:
print(recipe.name, ': failed to import image ', str(e))

View File

@@ -1,12 +1,14 @@
import re
from bs4 import BeautifulSoup
from io import BytesIO
from zipfile import ZipFile
from bs4 import BeautifulSoup
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, iso_duration_to_minutes
from cookbook.helper.recipe_url_import import iso_duration_to_minutes, parse_servings
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class RecipeKeeper(Integration):
@@ -45,11 +47,11 @@ class RecipeKeeper(Integration):
for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):
if ingredient.text == "":
continue
amount, unit, ingredient, note = ingredient_parser.parse(ingredient.text.strip())
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient.text.strip())
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
for s in file.find("div", {"itemprop": "recipeDirections"}).find_all("p"):
@@ -58,7 +60,7 @@ class RecipeKeeper(Integration):
step.instruction += s.text + ' \n'
if file.find("span", {"itemprop": "recipeSource"}).text != '':
step.instruction += "\n\nImported from: " + file.find("span", {"itemprop": "recipeSource"}).text
step.instruction += "\n\n" + _("Imported from") + ": " + file.find("span", {"itemprop": "recipeSource"}).text
step.save()
recipe.steps.add(step)

View File

@@ -2,10 +2,11 @@ import json
from io import BytesIO
import requests
import validators
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient
from cookbook.models import Ingredient, Recipe, Step
class RecipeSage(Integration):
@@ -31,7 +32,7 @@ class RecipeSage(Integration):
except Exception as e:
print('failed to parse yield or time ', str(e))
ingredient_parser = IngredientParser(self.request,True)
ingredient_parser = IngredientParser(self.request, True)
ingredients_added = False
for s in file['recipeInstructions']:
step = Step.objects.create(
@@ -41,18 +42,20 @@ class RecipeSage(Integration):
ingredients_added = True
for ingredient in file['recipeIngredient']:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)
if len(file['image']) > 0:
try:
response = requests.get(file['image'][0])
self.import_recipe_image(recipe, BytesIO(response.content))
url = file['image'][0]
if validators.url(url, public=True):
response = requests.get(url)
self.import_recipe_image(recipe, BytesIO(response.content))
except Exception as e:
print('failed to import image ', str(e))
@@ -77,14 +80,13 @@ class RecipeSage(Integration):
}
for s in recipe.steps.all():
if s.type != Step.TIME:
data['recipeInstructions'].append({
'@type': 'HowToStep',
'text': s.instruction
})
data['recipeInstructions'].append({
'@type': 'HowToStep',
'text': s.instruction
})
for i in s.ingredients.all():
data['recipeIngredient'].append(f'{float(i.amount)} {i.unit} {i.food}')
for i in s.ingredients.all():
data['recipeIngredient'].append(f'{float(i.amount)} {i.unit} {i.food}')
return data

View File

@@ -1,6 +1,6 @@
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class RezKonv(Integration):
@@ -12,43 +12,43 @@ class RezKonv(Integration):
ingredients = []
directions = []
for line in file.replace('\r', '').split('\n'):
for line in file.replace('\r', '').replace('\n\n', '\n').split('\n'):
if 'Titel:' in line:
title = line.replace('Titel:', '').strip()
if 'Kategorien:' in line:
tags = line.replace('Kategorien:', '').strip()
if ingredient_mode and ('quelle' in line.lower() or 'source' in line.lower()):
if ingredient_mode and (
'quelle' in line.lower() or 'source' in line.lower() or (line == '' and len(ingredients) > 0)):
ingredient_mode = False
direction_mode = True
if ingredient_mode:
if line != '' and '===' not in line and 'Zubereitung' not in line:
ingredients.append(line.strip())
if direction_mode:
if line.strip() != '' and line.strip() != '=====':
directions.append(line.strip())
if 'Zutaten:' in line:
if 'Zutaten:' in line or 'Ingredients' in line or 'Menge:' in line:
ingredient_mode = True
if 'Zubereitung:' in line:
ingredient_mode = False
direction_mode = True
recipe = Recipe.objects.create(name=title, created_by=self.request.user, internal=True, space=self.request.space)
recipe = Recipe.objects.create(name=title, created_by=self.request.user, internal=True,
space=self.request.space)
for k in tags.split(','):
keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space)
recipe.keywords.add(keyword)
step = Step.objects.create(
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
instruction=' \n'.join(directions) + '\n\n', space=self.request.space,
)
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
if len(ingredient.strip()) > 0:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)
@@ -60,9 +60,15 @@ class RezKonv(Integration):
def split_recipe_file(self, file):
recipe_list = []
current_recipe = ''
encoding_list = ['windows-1250',
'latin-1'] # TODO build algorithm to try trough encodings and fail if none work, use for all importers
encoding = 'windows-1250'
for fl in file.readlines():
line = fl.decode("windows-1250")
try:
line = fl.decode(encoding)
except UnicodeDecodeError:
encoding = 'latin-1'
line = fl.decode(encoding)
if line.startswith('=====') and 'rezkonv' in line.lower():
if current_recipe != '':
recipe_list.append(current_recipe)

View File

@@ -2,7 +2,7 @@ from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient
from cookbook.models import Ingredient, Recipe, Step
class Saffron(Integration):
@@ -47,11 +47,11 @@ class Saffron(Integration):
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, space=self.request.space,
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)
@@ -71,12 +71,11 @@ class Saffron(Integration):
recipeInstructions = []
recipeIngredient = []
for s in recipe.steps.all():
if s.type != Step.TIME:
recipeInstructions.append(s.instruction)
recipeInstructions.append(s.instruction)
for i in s.ingredients.all():
recipeIngredient.append(f'{float(i.amount)} {i.unit} {i.food}')
for i in s.ingredients.all():
recipeIngredient.append(f'{float(i.amount)} {i.unit} {i.food}')
data += "Ingredients: \n"
for ingredient in recipeIngredient:
data += ingredient+"\n"
@@ -91,10 +90,10 @@ class Saffron(Integration):
files = []
for r in recipes:
filename, data = self.get_file_from_recipe(r)
files.append([ filename, data ])
files.append([filename, data])
el.exported_recipes += 1
el.msg += self.get_recipe_processed_msg(r)
el.save()
return files
return files

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-04 12:31+0100\n"
"PO-Revision-Date: 2021-11-06 14:06+0000\n"
"Last-Translator: Nicklas Yli-Länttä <admin@timanttikuutio.eu>\n"
"PO-Revision-Date: 2022-03-18 16:31+0000\n"
"Last-Translator: Stefan Werner <werner@iki.fi>\n"
"Language-Team: Finnish <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/fi/>\n"
"Language: fi\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.8\n"
"X-Generator: Weblate 4.10.1\n"
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:125
#: .\cookbook\templates\forms\ingredients.html:34
@@ -31,10 +31,12 @@ msgid ""
"Color of the top navigation bar. Not all colors work with all themes, just "
"try them out!"
msgstr ""
"Ylänavigointipalkin väri. Ei kaikki värit toimi kaikkien teemojen kanssa; "
"kokeile!"
#: .\cookbook\forms.py:55
msgid "Default Unit to be used when inserting a new ingredient into a recipe."
msgstr ""
msgstr "Oletusmittayksikkö uuden aineksen lisäämisessä."
#: .\cookbook\forms.py:57
msgid ""
@@ -2435,7 +2437,7 @@ msgid ""
msgstr ""
#: .\cookbook\views\new.py:225
msgid "Email to user could not be send, please share link manually."
msgid "Email could not be sent to user. Please share the link manually."
msgstr ""
#: .\cookbook\views\views.py:127

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2493,7 +2493,7 @@ msgid ""
msgstr ""
#: .\cookbook\views\new.py:229
msgid "Email to user could not be send, please share link manually."
msgid "Email could not be sent to user. Please share the link manually."
msgstr ""
#: .\cookbook\views\views.py:127

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"PO-Revision-Date: 2021-10-23 09:06+0000\n"
"Last-Translator: rustam <uzbekr@gmail.com>\n"
"PO-Revision-Date: 2022-04-07 19:32+0000\n"
"Last-Translator: Artem Aksenov <artemmillerr@gmail.com>\n"
"Language-Team: Russian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/ru/>\n"
"Language: ru\n"
@@ -18,14 +18,14 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.8\n"
"X-Generator: Weblate 4.10.1\n"
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:125
#: .\cookbook\templates\forms\ingredients.html:34
#: .\cookbook\templates\space.html:43 .\cookbook\templates\stats.html:28
#: .\cookbook\templates\url_import.html:270
msgid "Ingredients"
msgstr "ингредиенты"
msgstr "Ингредиенты"
#: .\cookbook\forms.py:50
msgid ""
@@ -95,14 +95,14 @@ msgstr ""
#: .\cookbook\forms.py:103 .\cookbook\forms.py:334
#: .\cookbook\templates\url_import.html:154
msgid "Name"
msgstr "Имя"
msgstr "Название"
#: .\cookbook\forms.py:104 .\cookbook\forms.py:335
#: .\cookbook\templates\space.html:39 .\cookbook\templates\stats.html:24
#: .\cookbook\templates\url_import.html:188
#: .\cookbook\templates\url_import.html:573 .\cookbook\views\lists.py:112
msgid "Keywords"
msgstr "Ключевые поля"
msgstr "Ключевые слова"
#: .\cookbook\forms.py:105
msgid "Preparation time in minutes"
@@ -2501,7 +2501,7 @@ msgid ""
msgstr ""
#: .\cookbook\views\new.py:245
msgid "Email to user could not be send, please share link manually."
msgid "Email could not be sent to user. Please share the link manually."
msgstr ""
#: .\cookbook\views\views.py:128

View File

@@ -2530,7 +2530,7 @@ msgid ""
msgstr ""
#: .\cookbook\views\new.py:229
msgid "Email to user could not be send, please share link manually."
msgid "Email could not be sent to user. Please share the link manually."
msgstr ""
#: .\cookbook\views\views.py:127

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2254,7 +2254,7 @@ msgid ""
msgstr ""
#: .\cookbook\views\new.py:246
msgid "Email to user could not be send, please share link manually."
msgid "Email could not be sent to user. Please share the link manually."
msgstr ""
#: .\cookbook\views\views.py:125

View File

@@ -1,7 +1,5 @@
from django.contrib.postgres.aggregates import StringAgg
from django.contrib.postgres.search import (
SearchQuery, SearchRank, SearchVector,
)
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
from django.db import models
from django.db.models import Q
from django.utils import translation
@@ -18,6 +16,7 @@ DICTIONARY = {
'it': 'italian',
# 'lv': 'Latvian',
'es': 'spanish',
'sv': 'swedish',
}

View File

@@ -1,9 +1,10 @@
# Generated by Django 3.2.11 on 2022-02-03 15:03
import cookbook.models
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import cookbook.models
class Migration(migrations.Migration):

View File

@@ -0,0 +1,66 @@
# Generated by Django 3.2.11 on 2022-02-07 17:48
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import cookbook.models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('cookbook', '0169_exportlog'),
]
operations = [
migrations.AddField(
model_name='food',
name='child_inherit_fields',
field=models.ManyToManyField(blank=True, related_name='child_inherit', to='cookbook.FoodInheritField'),
),
migrations.AddField(
model_name='food',
name='substitute',
field=models.ManyToManyField(blank=True, related_name='_cookbook_food_substitute_+', to='cookbook.Food'),
),
migrations.AddField(
model_name='food',
name='substitute_children',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='food',
name='substitute_siblings',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='ingredient',
name='unit',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.unit'),
),
migrations.CreateModel(
name='CustomFilter',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128)),
('type', models.CharField(choices=[('RECIPE', 'Recipe'), ('FOOD', 'Food'), ('KEYWORD', 'Keyword')], default=('RECIPE', 'Recipe'), max_length=128)),
('search', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('shared', models.ManyToManyField(blank=True, related_name='f_shared_with', to=settings.AUTH_USER_MODEL)),
('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')),
],
bases=(models.Model, cookbook.models.PermissionModelMixin),
),
migrations.AddField(
model_name='recipebook',
name='filter',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.customfilter'),
),
migrations.AddConstraint(
model_name='customfilter',
constraint=models.UniqueConstraint(fields=('space', 'name'), name='cf_unique_name_per_space'),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2022-02-15 00:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0170_auto_20220207_1848'),
]
operations = [
migrations.AlterField(
model_name='searchpreference',
name='trigram_threshold',
field=models.DecimalField(decimal_places=2, default=0.2, max_digits=3),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2022-02-25 15:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0171_alter_searchpreference_trigram_threshold'),
]
operations = [
migrations.AddField(
model_name='ingredient',
name='original_text',
field=models.CharField(blank=True, default=None, max_length=512, null=True),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2022-03-04 13:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0172_ingredient_original_text'),
]
operations = [
migrations.AddField(
model_name='recipe',
name='source_url',
field=models.CharField(blank=True, default=None, max_length=1024, null=True),
),
]

View File

@@ -62,9 +62,10 @@ class TreeManager(MP_NodeManager):
# model.Manager get_or_create() is not compatible with MP_Tree
def get_or_create(self, *args, **kwargs):
kwargs['name'] = kwargs['name'].strip()
try:
return self.get(name__exact=kwargs['name'], space=kwargs['space']), False
except self.model.DoesNotExist:
if obj := self.filter(name__iexact=kwargs['name'], space=kwargs['space']).first():
return obj, False
else:
with scopes_disabled():
try:
defaults = kwargs.pop('defaults', None)
@@ -97,13 +98,6 @@ class TreeModel(MP_Node):
else:
return f"{self.name}"
# MP_Tree move uses raw SQL to execute move, override behavior to force a save triggering post_save signal
def move(self, *args, **kwargs):
super().move(*args, **kwargs)
# treebeard bypasses ORM, need to retrieve the object again to avoid writing previous state back to disk
obj = self.__class__.objects.get(id=self.id)
obj.save()
@property
def parent(self):
parent = self.get_parent()
@@ -247,7 +241,7 @@ class Space(ExportModelOperationsMixin('space'), models.Model):
max_users = models.IntegerField(default=0)
allow_sharing = models.BooleanField(default=True)
demo = models.BooleanField(default=False)
food_inherit = models.ManyToManyField(FoodInheritField, blank=True)
food_inherit = models.ManyToManyField(FoodInheritField, blank=True)
show_facet_count = models.BooleanField(default=False)
def __str__(self):
@@ -343,7 +337,7 @@ class UserPreference(models.Model, PermissionModelMixin):
default_delay = models.DecimalField(default=4, max_digits=8, decimal_places=4)
shopping_recent_days = models.PositiveIntegerField(default=7)
csv_delim = models.CharField(max_length=2, default=",")
csv_prefix = models.CharField(max_length=10, blank=True,)
csv_prefix = models.CharField(max_length=10, blank=True, )
created_at = models.DateTimeField(auto_now_add=True)
space = models.ForeignKey(Space, on_delete=models.CASCADE, null=True)
@@ -488,8 +482,10 @@ class Unit(ExportModelOperationsMixin('unit'), models.Model, PermissionModelMixi
class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
# TODO when savings a food as substitute children - assume children and descednants are also substitutes for siblings
# exclude fields not implemented yet
inheritable_fields = FoodInheritField.objects.exclude(field__in=['diet', 'substitute', 'substitute_children', 'substitute_siblings'])
inheritable_fields = FoodInheritField.objects.exclude(field__in=['diet', 'substitute', ])
# TODO add inherit children_inherit, parent_inherit, Do Not Inherit
# WARNING: Food inheritance relies on post_save signals, avoid using UPDATE to update Food objects unless you intend to bypass those signals
if SORT_TREE_BY_NAME:
@@ -500,7 +496,11 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
ignore_shopping = models.BooleanField(default=False) # inherited field
onhand_users = models.ManyToManyField(User, blank=True)
description = models.TextField(default='', blank=True)
inherit_fields = models.ManyToManyField(FoodInheritField, blank=True)
inherit_fields = models.ManyToManyField(FoodInheritField, blank=True)
substitute = models.ManyToManyField("self", blank=True)
substitute_siblings = models.BooleanField(default=False)
substitute_children = models.BooleanField(default=False)
child_inherit_fields = models.ManyToManyField(FoodInheritField, blank=True, related_name='child_inherit')
space = models.ForeignKey(Space, on_delete=models.CASCADE)
objects = ScopedManager(space='space', _manager_class=TreeManager)
@@ -514,34 +514,63 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
else:
return super().delete()
# MP_Tree move uses raw SQL to execute move, override behavior to force a save triggering post_save signal
def move(self, *args, **kwargs):
super().move(*args, **kwargs)
# treebeard bypasses ORM, need to explicity save to trigger post save signals retrieve the object again to avoid writing previous state back to disk
obj = self.__class__.objects.get(id=self.id)
if parent := obj.get_parent():
# child should inherit what the parent defines it should inherit
fields = list(parent.child_inherit_fields.all() or parent.inherit_fields.all())
if len(fields) > 0:
obj.inherit_fields.set(fields)
obj.save()
@staticmethod
def reset_inheritance(space=None):
def reset_inheritance(space=None, food=None):
# resets inherited fields to the space defaults and updates all inherited fields to root object values
inherit = space.food_inherit.all()
if food:
# if child inherit fields is preset children should be set to that, otherwise inherit this foods inherited fields
inherit = list((food.child_inherit_fields.all() or food.inherit_fields.all()).values('id', 'field'))
tree_filter = Q(path__startswith=food.path, space=space, depth=food.depth + 1)
else:
inherit = list(space.food_inherit.all().values('id', 'field'))
tree_filter = Q(space=space)
# remove all inherited fields from food
Through = Food.objects.filter(space=space).first().inherit_fields.through
Through = Food.objects.filter(tree_filter).first().inherit_fields.through
Through.objects.all().delete()
# food is going to inherit attributes
if space.food_inherit.all().count() > 0:
if len(inherit) > 0:
# ManyToMany cannot be updated through an UPDATE operation
for i in inherit:
Through.objects.bulk_create([
Through(food_id=x, foodinheritfield_id=i.id)
for x in Food.objects.filter(space=space).values_list('id', flat=True)
Through(food_id=x, foodinheritfield_id=i['id'])
for x in Food.objects.filter(tree_filter).values_list('id', flat=True)
])
inherit = inherit.values_list('field', flat=True)
if 'ignore_shopping' in inherit:
# get food at root that have children that need updated
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, space=space, ignore_shopping=True)).update(ignore_shopping=True)
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, space=space, ignore_shopping=False)).update(ignore_shopping=False)
inherit = [x['field'] for x in inherit]
for field in ['ignore_shopping', 'substitute_children', 'substitute_siblings']:
if field in inherit:
if food and getattr(food, field, None):
food.get_descendants().update(**{f"{field}": True})
elif food and not getattr(food, field, True):
food.get_descendants().update(**{f"{field}": False})
else:
# get food at root that have children that need updated
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, **{f"{field}": True}, space=space)).update(**{f"{field}": True})
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, **{f"{field}": False}, space=space)).update(**{f"{field}": False})
if 'supermarket_category' in inherit:
# when supermarket_category is null or blank assuming it is not set and not intended to be blank for all descedants
# find top node that has category set
category_roots = Food.exclude_descendants(queryset=Food.objects.filter(supermarket_category__isnull=False, numchild__gt=0, space=space))
for root in category_roots:
root.get_descendants().update(supermarket_category=root.supermarket_category)
if food and food.supermarket_category:
food.get_descendants().update(supermarket_category=food.supermarket_category)
elif food is None:
# find top node that has category set
category_roots = Food.exclude_descendants(queryset=Food.objects.filter(supermarket_category__isnull=False, numchild__gt=0, space=space))
for root in category_roots:
root.get_descendants().update(supermarket_category=root.supermarket_category)
class Meta:
constraints = [
@@ -554,14 +583,17 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, PermissionModelMixin):
# a pre-delete signal on Food checks if the Ingredient is part of a Step, if it is raises a ProtectedError instead of cascading the delete
# delete method on Food and Unit checks if they are part of a Recipe, if it is raises a ProtectedError instead of cascading the delete
food = models.ForeignKey(Food, on_delete=models.CASCADE, null=True, blank=True)
unit = models.ForeignKey(Unit, on_delete=models.PROTECT, null=True, blank=True)
unit = models.ForeignKey(Unit, on_delete=models.SET_NULL, null=True, blank=True)
amount = models.DecimalField(default=0, decimal_places=16, max_digits=32)
note = models.CharField(max_length=256, null=True, blank=True)
is_header = models.BooleanField(default=False)
no_amount = models.BooleanField(default=False)
order = models.IntegerField(default=0)
original_text = models.CharField(max_length=512, null=True, blank=True, default=None)
original_text = models.CharField(max_length=512, null=True, blank=True, default=None)
space = models.ForeignKey(Space, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
@@ -633,9 +665,7 @@ class Recipe(ExportModelOperationsMixin('recipe'), models.Model, PermissionModel
servings = models.IntegerField(default=1)
servings_text = models.CharField(default='', blank=True, max_length=32)
image = models.ImageField(upload_to='recipes/', blank=True, null=True)
storage = models.ForeignKey(
Storage, on_delete=models.PROTECT, blank=True, null=True
)
storage = models.ForeignKey(Storage, on_delete=models.PROTECT, blank=True, null=True)
file_uid = models.CharField(max_length=256, default="", blank=True)
file_path = models.CharField(max_length=512, default="", blank=True)
link = models.CharField(max_length=512, null=True, blank=True)
@@ -645,9 +675,9 @@ class Recipe(ExportModelOperationsMixin('recipe'), models.Model, PermissionModel
working_time = models.IntegerField(default=0)
waiting_time = models.IntegerField(default=0)
internal = models.BooleanField(default=False)
nutrition = models.ForeignKey(
NutritionInformation, blank=True, null=True, on_delete=models.CASCADE
)
nutrition = models.ForeignKey(NutritionInformation, blank=True, null=True, on_delete=models.CASCADE)
source_url = models.CharField(max_length=1024, default=None, blank=True, null=True)
created_by = models.ForeignKey(User, on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@@ -725,6 +755,7 @@ class RecipeBook(ExportModelOperationsMixin('book'), models.Model, PermissionMod
icon = models.CharField(max_length=16, blank=True, null=True)
shared = models.ManyToManyField(User, blank=True, related_name='shared_with')
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
filter = models.ForeignKey('cookbook.CustomFilter', null=True, blank=True, on_delete=models.SET_NULL)
space = models.ForeignKey(Space, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
@@ -1002,6 +1033,7 @@ class ImportLog(models.Model, PermissionModelMixin):
def __str__(self):
return f"{self.created_at}:{self.type}"
class ExportLog(models.Model, PermissionModelMixin):
type = models.CharField(max_length=32)
running = models.BooleanField(default=True)
@@ -1077,7 +1109,7 @@ class SearchPreference(models.Model, PermissionModelMixin):
istartswith = models.ManyToManyField(SearchFields, related_name="istartswith_fields", blank=True)
trigram = models.ManyToManyField(SearchFields, related_name="trigram_fields", blank=True, default=nameSearchField)
fulltext = models.ManyToManyField(SearchFields, related_name="fulltext_fields", blank=True)
trigram_threshold = models.DecimalField(default=0.1, decimal_places=2, max_digits=3)
trigram_threshold = models.DecimalField(default=0.2, decimal_places=2, max_digits=3)
class UserFile(ExportModelOperationsMixin('user_files'), models.Model, PermissionModelMixin):
@@ -1119,3 +1151,34 @@ class Automation(ExportModelOperationsMixin('automations'), models.Model, Permis
objects = ScopedManager(space='space')
space = models.ForeignKey(Space, on_delete=models.CASCADE)
class CustomFilter(models.Model, PermissionModelMixin):
RECIPE = 'RECIPE'
FOOD = 'FOOD'
KEYWORD = 'KEYWORD'
MODELS = (
(RECIPE, _('Recipe')),
(FOOD, _('Food')),
(KEYWORD, _('Keyword')),
)
name = models.CharField(max_length=128, null=False, blank=False)
type = models.CharField(max_length=128, choices=(MODELS), default=MODELS[0])
# could use JSONField, but requires installing extension on SQLite, don't need to search the objects, so seems unecessary
search = models.TextField(blank=False, null=False)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
shared = models.ManyToManyField(User, blank=True, related_name='f_shared_with')
objects = ScopedManager(space='space')
space = models.ForeignKey(Space, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Meta:
constraints = [
models.UniqueConstraint(fields=['space', 'name'], name='cf_unique_name_per_space')
]

View File

@@ -4,6 +4,8 @@ import os
from datetime import datetime
import requests
import validators
from cookbook.models import Recipe, RecipeImport, SyncLog
from cookbook.provider.provider import Provider
@@ -104,9 +106,11 @@ class Dropbox(Provider):
recipe.link = Dropbox.get_share_link(recipe)
recipe.save()
response = requests.get(recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.'))
url = recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.')
if validators.url(url, public=True):
response = requests.get(url)
return io.BytesIO(response.content)
return io.BytesIO(response.content)
@staticmethod
def rename_file(recipe, new_name):

View File

@@ -4,11 +4,14 @@ import tempfile
from datetime import datetime
import requests
import validators
import webdav3.client as wc
from cookbook.models import Recipe, RecipeImport, SyncLog
from cookbook.provider.provider import Provider
from requests.auth import HTTPBasicAuth
from recipes.settings import DEBUG
class Nextcloud(Provider):
@@ -28,15 +31,18 @@ class Nextcloud(Provider):
def import_all(monitor):
client = Nextcloud.get_client(monitor.storage)
if DEBUG:
print(f'TANDOOR_PROVIDER_DEBUG checking path {monitor.path} with client {client}')
files = client.list(monitor.path)
try:
files.pop(0) # remove first element because its the folder itself
except IndexError:
pass # folder is empty, no recipes will be imported
if DEBUG:
print(f'TANDOOR_PROVIDER_DEBUG file list {files}')
import_count = 0
for file in files:
if DEBUG:
print(f'TANDOOR_PROVIDER_DEBUG importing file {file}')
path = monitor.path + '/' + file
if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists():
name = os.path.splitext(file)[0]
@@ -87,20 +93,21 @@ class Nextcloud(Provider):
"Content-Type": "application/json"
}
r = requests.get(
url,
headers=headers,
auth=HTTPBasicAuth(
recipe.storage.username, recipe.storage.password
if validators.url(url, public=True):
r = requests.get(
url,
headers=headers,
auth=HTTPBasicAuth(
recipe.storage.username, recipe.storage.password
)
)
)
response_json = r.json()
for element in response_json['ocs']['data']:
if element['share_type'] == '3':
return element['url']
response_json = r.json()
for element in response_json['ocs']['data']:
if element['share_type'] == '3':
return element['url']
return Nextcloud.create_share_link(recipe)
return Nextcloud.create_share_link(recipe)
@staticmethod
def get_file(recipe):

View File

@@ -1,28 +1,28 @@
import random
from datetime import timedelta
from decimal import Decimal
from gettext import gettext as _
from django.contrib.auth.models import User
from django.db.models import Avg, QuerySet, Sum
from django.db.models import Avg, Q, QuerySet, Sum
from django.urls import reverse
from django.utils import timezone
from drf_writable_nested import UniqueFieldsMixin, WritableNestedModelSerializer
from rest_framework import serializers
from rest_framework.exceptions import NotFound, ValidationError
from rest_framework.fields import empty
from cookbook.helper.CustomStorageClass import CachedS3Boto3Storage
from cookbook.helper.HelperFunctions import str2bool
from cookbook.helper.permission_helper import above_space_limit
from cookbook.helper.shopping_helper import RecipeShoppingEditor
from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Food,
FoodInheritField, ImportLog, ExportLog, Ingredient, Keyword, MealPlan, MealType,
NutritionInformation, Recipe, RecipeBook, RecipeBookEntry,
RecipeImport, ShareLink, ShoppingList, ShoppingListEntry,
ShoppingListRecipe, Step, Storage, Supermarket, SupermarketCategory,
SupermarketCategoryRelation, Sync, SyncLog, Unit, UserFile,
UserPreference, ViewLog)
from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, CustomFilter,
ExportLog, Food, FoodInheritField, ImportLog, Ingredient, Keyword,
MealPlan, MealType, NutritionInformation, Recipe, RecipeBook,
RecipeBookEntry, RecipeImport, ShareLink, ShoppingList,
ShoppingListEntry, ShoppingListRecipe, Step, Storage, Supermarket,
SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, Unit,
UserFile, UserPreference, ViewLog)
from cookbook.templatetags.custom_tags import markdown
from recipes.settings import MEDIA_URL
from recipes.settings import MEDIA_URL, AWS_ENABLED
class ExtendedRecipeMixin(serializers.ModelSerializer):
@@ -43,7 +43,8 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
api_serializer = None
# extended values are computationally expensive and not needed in normal circumstances
try:
if str2bool(self.context['request'].query_params.get('extended', False)) and self.__class__ == api_serializer:
if str2bool(
self.context['request'].query_params.get('extended', False)) and self.__class__ == api_serializer:
return fields
except (AttributeError, KeyError) as e:
pass
@@ -56,7 +57,12 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
def get_image(self, obj):
if obj.recipe_image:
return MEDIA_URL + obj.recipe_image
if AWS_ENABLED:
storage = CachedS3Boto3Storage()
path = storage.url(obj.recipe_image)
else:
path = MEDIA_URL + obj.recipe_image
return path
class CustomDecimalField(serializers.Field):
@@ -91,7 +97,11 @@ class CustomOnHandField(serializers.Field):
if request := self.context.get('request', None):
shared_users = getattr(request, '_shared_users', None)
if shared_users is None:
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [self.context['request'].user.id]
try:
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [
self.context['request'].user.id]
except AttributeError: # Anonymous users (using share links) don't have shared users
shared_users = []
return obj.onhand_users.filter(id__in=shared_users).exists()
def to_internal_value(self, data):
@@ -163,7 +173,8 @@ class FoodInheritFieldSerializer(WritableNestedModelSerializer):
class UserPreferenceSerializer(WritableNestedModelSerializer):
food_inherit_default = FoodInheritFieldSerializer(source='space.food_inherit', many=True, allow_null=True, required=False, read_only=True)
food_inherit_default = FoodInheritFieldSerializer(source='space.food_inherit', many=True, allow_null=True,
required=False, read_only=True)
plan_share = UserNameSerializer(many=True, allow_null=True, required=False, read_only=True)
shopping_share = UserNameSerializer(many=True, allow_null=True, required=False)
food_children_exist = serializers.SerializerMethodField('get_food_children_exist')
@@ -182,9 +193,12 @@ class UserPreferenceSerializer(WritableNestedModelSerializer):
class Meta:
model = UserPreference
fields = (
'user', 'theme', 'nav_color', 'default_unit', 'default_page', 'use_fractions', 'use_kj', 'search_style', 'show_recent', 'plan_share',
'ingredient_decimals', 'comments', 'shopping_auto_sync', 'mealplan_autoadd_shopping', 'food_inherit_default', 'default_delay',
'mealplan_autoinclude_related', 'mealplan_autoexclude_onhand', 'shopping_share', 'shopping_recent_days', 'csv_delim', 'csv_prefix',
'user', 'theme', 'nav_color', 'default_unit', 'default_page', 'use_fractions', 'use_kj', 'search_style',
'show_recent', 'plan_share',
'ingredient_decimals', 'comments', 'shopping_auto_sync', 'mealplan_autoadd_shopping',
'food_inherit_default', 'default_delay',
'mealplan_autoinclude_related', 'mealplan_autoexclude_onhand', 'shopping_share', 'shopping_recent_days',
'csv_delim', 'csv_prefix',
'filter_to_supermarket', 'shopping_add_onhand', 'left_handed', 'food_children_exist'
)
@@ -299,9 +313,9 @@ class KeywordSerializer(UniqueFieldsMixin, ExtendedRecipeMixin):
def create(self, validated_data):
# since multi select tags dont have id's
# duplicate names might be routed to create
validated_data['name'] = validated_data['name'].strip()
validated_data['space'] = self.context['request'].space
obj, created = Keyword.objects.get_or_create(**validated_data)
name = validated_data.pop('name').strip()
space = validated_data.pop('space', self.context['request'].space)
obj, created = Keyword.objects.get_or_create(name=name, space=space, defaults=validated_data)
return obj
class Meta:
@@ -316,9 +330,9 @@ class UnitSerializer(UniqueFieldsMixin, ExtendedRecipeMixin):
recipe_filter = 'steps__ingredients__unit'
def create(self, validated_data):
validated_data['name'] = validated_data['name'].strip()
validated_data['space'] = self.context['request'].space
obj, created = Unit.objects.get_or_create(**validated_data)
name = validated_data.pop('name').strip()
space = validated_data.pop('space', self.context['request'].space)
obj, created = Unit.objects.get_or_create(name=name, space=space, defaults=validated_data)
return obj
def update(self, instance, validated_data):
@@ -334,9 +348,9 @@ class UnitSerializer(UniqueFieldsMixin, ExtendedRecipeMixin):
class SupermarketCategorySerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
def create(self, validated_data):
validated_data['name'] = validated_data['name'].strip()
validated_data['space'] = self.context['request'].space
obj, created = SupermarketCategory.objects.get_or_create(**validated_data)
name = validated_data.pop('name').strip()
space = validated_data.pop('space', self.context['request'].space)
obj, created = SupermarketCategory.objects.get_or_create(name=name, space=space)
return obj
def update(self, instance, validated_data):
@@ -363,16 +377,29 @@ class SupermarketSerializer(UniqueFieldsMixin, SpacedModelSerializer):
fields = ('id', 'name', 'description', 'category_to_supermarket')
class RecipeSimpleSerializer(serializers.ModelSerializer):
class RecipeSimpleSerializer(WritableNestedModelSerializer):
url = serializers.SerializerMethodField('get_url')
def get_url(self, obj):
return reverse('view_recipe', args=[obj.id])
def create(self, validated_data):
# don't allow writing to Recipe via this API
return Recipe.objects.get(**validated_data)
def update(self, instance, validated_data):
# don't allow writing to Recipe via this API
return Recipe.objects.get(**validated_data)
class Meta:
model = Recipe
fields = ('id', 'name', 'url')
read_only_fields = ['id', 'name', 'url']
class FoodSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Food
fields = ('id', 'name')
class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedRecipeMixin):
@@ -381,23 +408,47 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
# shopping = serializers.SerializerMethodField('get_shopping_status')
shopping = serializers.ReadOnlyField(source='shopping_status')
inherit_fields = FoodInheritFieldSerializer(many=True, allow_null=True, required=False)
child_inherit_fields = FoodInheritFieldSerializer(many=True, allow_null=True, required=False)
food_onhand = CustomOnHandField(required=False, allow_null=True)
substitute_onhand = serializers.SerializerMethodField('get_substitute_onhand')
substitute = FoodSimpleSerializer(many=True, allow_null=True, required=False)
recipe_filter = 'steps__ingredients__food'
images = ['recipe__image']
def get_substitute_onhand(self, obj):
shared_users = None
if request := self.context.get('request', None):
shared_users = getattr(request, '_shared_users', None)
if shared_users is None:
try:
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [
self.context['request'].user.id]
except AttributeError:
shared_users = []
filter = Q(id__in=obj.substitute.all())
if obj.substitute_siblings:
filter |= Q(path__startswith=obj.path[:Food.steplen * (obj.depth - 1)], depth=obj.depth)
if obj.substitute_children:
filter |= Q(path__startswith=obj.path, depth__gt=obj.depth)
return Food.objects.filter(filter).filter(onhand_users__id__in=shared_users).exists()
# def get_shopping_status(self, obj):
# return ShoppingListEntry.objects.filter(space=obj.space, food=obj, checked=False).count() > 0
def create(self, validated_data):
validated_data['name'] = validated_data['name'].strip()
validated_data['space'] = self.context['request'].space
name = validated_data.pop('name').strip()
space = validated_data.pop('space', self.context['request'].space)
# supermarket category needs to be handled manually as food.get or create does not create nested serializers unlike a super.create of serializer
if 'supermarket_category' in validated_data and validated_data['supermarket_category']:
sm_category = validated_data['supermarket_category']
sc_name = sm_category.pop('name', None)
validated_data['supermarket_category'], sc_created = SupermarketCategory.objects.get_or_create(
name=validated_data.pop('supermarket_category')['name'],
space=self.context['request'].space)
name=sc_name,
space=space, defaults=sm_category)
onhand = validated_data.pop('food_onhand', None)
if recipe := validated_data.get('recipe', None):
validated_data['recipe'] = Recipe.objects.get(**recipe)
# assuming if on hand for user also onhand for shopping_share users
if not onhand is None:
@@ -411,7 +462,7 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
else:
validated_data['onhand_users'] = list(set(onhand_users) - set(shared_users))
obj, created = Food.objects.get_or_create(**validated_data)
obj, created = Food.objects.get_or_create(name=name, space=space, defaults=validated_data)
return obj
def update(self, instance, validated_data):
@@ -419,40 +470,59 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
validated_data['name'] = name.strip()
# assuming if on hand for user also onhand for shopping_share users
onhand = validated_data.get('food_onhand', None)
reset_inherit = self.initial_data.get('reset_inherit', False)
if not onhand is None:
shared_users = [user := self.context['request'].user] + list(user.userpreference.shopping_share.all())
if onhand:
validated_data['onhand_users'] = list(self.instance.onhand_users.all()) + shared_users
else:
validated_data['onhand_users'] = list(set(self.instance.onhand_users.all()) - set(shared_users))
return super(FoodSerializer, self).update(instance, validated_data)
# update before resetting inheritance
saved_instance = super(FoodSerializer, self).update(instance, validated_data)
if reset_inherit and (r := self.context.get('request', None)):
Food.reset_inheritance(food=saved_instance, space=r.space)
return saved_instance
class Meta:
model = Food
fields = (
'id', 'name', 'description', 'shopping', 'recipe', 'food_onhand', 'supermarket_category',
'image', 'parent', 'numchild', 'numrecipe', 'inherit_fields', 'full_name', 'ignore_shopping'
'image', 'parent', 'numchild', 'numrecipe', 'inherit_fields', 'full_name', 'ignore_shopping',
'substitute', 'substitute_siblings', 'substitute_children', 'substitute_onhand', 'child_inherit_fields'
)
read_only_fields = ('id', 'numchild', 'parent', 'image', 'numrecipe')
class IngredientSerializer(WritableNestedModelSerializer):
food = FoodSerializer(allow_null=True)
class IngredientSimpleSerializer(WritableNestedModelSerializer):
food = FoodSimpleSerializer(allow_null=True)
unit = UnitSerializer(allow_null=True)
used_in_recipes = serializers.SerializerMethodField('get_used_in_recipes')
amount = CustomDecimalField()
def get_used_in_recipes(self, obj):
return list(Recipe.objects.filter(steps__ingredients=obj.id).values('id', 'name'))
def create(self, validated_data):
validated_data['space'] = self.context['request'].space
return super().create(validated_data)
def update(self, instance, validated_data):
validated_data.pop('original_text', None)
return super().update(instance, validated_data)
class Meta:
model = Ingredient
fields = (
'id', 'food', 'unit', 'amount', 'note', 'order',
'is_header', 'no_amount'
'is_header', 'no_amount', 'original_text', 'used_in_recipes',
)
class IngredientSerializer(IngredientSimpleSerializer):
food = FoodSerializer(allow_null=True)
class StepSerializer(WritableNestedModelSerializer, ExtendedRecipeMixin):
ingredients = IngredientSerializer(many=True)
ingredients_markdown = serializers.SerializerMethodField('get_ingredients_markdown')
@@ -575,11 +645,17 @@ class RecipeSerializer(RecipeBaseSerializer):
model = Recipe
fields = (
'id', 'name', 'description', 'image', 'keywords', 'steps', 'working_time',
'waiting_time', 'created_by', 'created_at', 'updated_at',
'waiting_time', 'created_by', 'created_at', 'updated_at','source_url',
'internal', 'nutrition', 'servings', 'file_path', 'servings_text', 'rating', 'last_cooked',
)
read_only_fields = ['image', 'created_by', 'created_at']
def validate(self, data):
above_limit, msg = above_space_limit(self.context['request'].space)
if above_limit:
raise serializers.ValidationError(msg)
return super().validate(data)
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
validated_data['space'] = self.context['request'].space
@@ -587,9 +663,12 @@ class RecipeSerializer(RecipeBaseSerializer):
class RecipeImageSerializer(WritableNestedModelSerializer):
image = serializers.ImageField(required=False, allow_null=True)
image_url = serializers.CharField(max_length=4096, required=False, allow_null=True)
class Meta:
model = Recipe
fields = ['image', ]
fields = ['image', 'image_url', ]
class RecipeImportSerializer(SpacedModelSerializer):
@@ -604,8 +683,22 @@ class CommentSerializer(serializers.ModelSerializer):
fields = '__all__'
class CustomFilterSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
shared = UserNameSerializer(many=True, required=False)
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
return super().create(validated_data)
class Meta:
model = CustomFilter
fields = ('id', 'name', 'search', 'shared', 'created_by')
read_only_fields = ('created_by',)
class RecipeBookSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
shared = UserNameSerializer(many=True)
filter = CustomFilterSerializer(allow_null=True, required=False)
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
@@ -613,7 +706,7 @@ class RecipeBookSerializer(SpacedModelSerializer, WritableNestedModelSerializer)
class Meta:
model = RecipeBook
fields = ('id', 'name', 'description', 'icon', 'shared', 'created_by')
fields = ('id', 'name', 'description', 'icon', 'shared', 'created_by', 'filter')
read_only_fields = ('created_by',)
@@ -630,7 +723,8 @@ class RecipeBookEntrySerializer(serializers.ModelSerializer):
def create(self, validated_data):
book = validated_data['book']
recipe = validated_data['recipe']
if not book.get_owner() == self.context['request'].user:
if not book.get_owner() == self.context['request'].user and not self.context[
'request'].user in book.get_shared():
raise NotFound(detail=None, code=None)
obj, created = RecipeBookEntry.objects.get_or_create(book=book, recipe=recipe)
return obj
@@ -659,7 +753,7 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
mealplan = super().create(validated_data)
if self.context['request'].data.get('addshopping', False):
if self.context['request'].data.get('addshopping', False) and self.context['request'].data.get('recipe', None):
SLR = RecipeShoppingEditor(user=validated_data['created_by'], space=validated_data['space'])
SLR.create(mealplan=mealplan, servings=validated_data['servings'])
return mealplan
@@ -674,7 +768,6 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
read_only_fields = ('created_by',)
# TODO deprecate
class ShoppingListRecipeSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField('get_name') # should this be done at the front end?
recipe_name = serializers.ReadOnlyField(source='recipe.name')
@@ -684,13 +777,14 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer):
def get_name(self, obj):
if not isinstance(value := obj.servings, Decimal):
value = Decimal(value)
value = value.quantize(Decimal(1)) if value == value.to_integral() else value.normalize() # strips trailing zero
value = value.quantize(
Decimal(1)) if value == value.to_integral() else value.normalize() # strips trailing zero
return (
obj.name
or getattr(obj.mealplan, 'title', None)
or (d := getattr(obj.mealplan, 'date', None)) and ': '.join([obj.mealplan.recipe.name, str(d)])
or obj.recipe.name
) + f' ({value:.2g})'
obj.name
or getattr(obj.mealplan, 'title', None)
or (d := getattr(obj.mealplan, 'date', None)) and ': '.join([obj.mealplan.recipe.name, str(d)])
or obj.recipe.name
) + f' ({value:.2g})'
def update(self, instance, validated_data):
# TODO remove once old shopping list
@@ -761,7 +855,8 @@ class ShoppingListEntrySerializer(WritableNestedModelSerializer):
class Meta:
model = ShoppingListEntry
fields = (
'id', 'list_recipe', 'food', 'unit', 'ingredient', 'ingredient_note', 'amount', 'order', 'checked', 'recipe_mealplan',
'id', 'list_recipe', 'food', 'unit', 'ingredient', 'ingredient_note', 'amount', 'order', 'checked',
'recipe_mealplan',
'created_by', 'created_at', 'completed_at', 'delay_until'
)
read_only_fields = ('id', 'created_by', 'created_at',)
@@ -859,11 +954,13 @@ class ExportLogSerializer(serializers.ModelSerializer):
class Meta:
model = ExportLog
fields = ('id', 'type', 'msg', 'running', 'total_recipes', 'exported_recipes', 'cache_duration', 'possibly_not_expired', 'created_by', 'created_at')
fields = (
'id', 'type', 'msg', 'running', 'total_recipes', 'exported_recipes', 'cache_duration',
'possibly_not_expired',
'created_by', 'created_at')
read_only_fields = ('created_by',)
class AutomationSerializer(serializers.ModelSerializer):
def create(self, validated_data):
@@ -881,12 +978,19 @@ class AutomationSerializer(serializers.ModelSerializer):
# CORS, REST and Scopes aren't currently working
# Scopes are evaluating before REST has authenticated the user assigning a None space
# I've made the change below to fix the bookmarklet, other serializers likely need a similar/better fix
class BookmarkletImportSerializer(serializers.ModelSerializer):
class BookmarkletImportListSerializer(serializers.ModelSerializer):
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
validated_data['space'] = self.context['request'].user.userpreference.space
return super().create(validated_data)
class Meta:
model = BookmarkletImport
fields = ('id', 'url', 'created_by', 'created_at')
read_only_fields = ('created_by', 'space')
class BookmarkletImportSerializer(BookmarkletImportListSerializer):
class Meta:
model = BookmarkletImport
fields = ('id', 'url', 'html', 'created_by', 'created_at')
@@ -972,10 +1076,12 @@ class RecipeExportSerializer(WritableNestedModelSerializer):
class RecipeShoppingUpdateSerializer(serializers.ModelSerializer):
list_recipe = serializers.IntegerField(write_only=True, allow_null=True, required=False, help_text=_("Existing shopping list to update"))
list_recipe = serializers.IntegerField(write_only=True, allow_null=True, required=False,
help_text=_("Existing shopping list to update"))
ingredients = serializers.IntegerField(write_only=True, allow_null=True, required=False, help_text=_(
"List of ingredient IDs from the recipe to add, if not provided all ingredients will be added."))
servings = serializers.IntegerField(default=1, write_only=True, allow_null=True, required=False, help_text=_("Providing a list_recipe ID and servings of 0 will delete that shopping list."))
servings = serializers.IntegerField(default=1, write_only=True, allow_null=True, required=False, help_text=_(
"Providing a list_recipe ID and servings of 0 will delete that shopping list."))
class Meta:
model = Recipe
@@ -983,9 +1089,12 @@ class RecipeShoppingUpdateSerializer(serializers.ModelSerializer):
class FoodShoppingUpdateSerializer(serializers.ModelSerializer):
amount = serializers.IntegerField(write_only=True, allow_null=True, required=False, help_text=_("Amount of food to add to the shopping list"))
unit = serializers.IntegerField(write_only=True, allow_null=True, required=False, help_text=_("ID of unit to use for the shopping list"))
delete = serializers.ChoiceField(choices=['true'], write_only=True, allow_null=True, allow_blank=True, help_text=_("When set to true will delete all food from active shopping lists."))
amount = serializers.IntegerField(write_only=True, allow_null=True, required=False,
help_text=_("Amount of food to add to the shopping list"))
unit = serializers.IntegerField(write_only=True, allow_null=True, required=False,
help_text=_("ID of unit to use for the shopping list"))
delete = serializers.ChoiceField(choices=['true'], write_only=True, allow_null=True, allow_blank=True,
help_text=_("When set to true will delete all food from active shopping lists."))
class Meta:
model = Recipe

View File

@@ -18,9 +18,8 @@ if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_ps
'django.db.backends.postgresql']:
SQLITE = False
# wraps a signal with the ability to set 'skip_signal' to avoid creating recursive signals
def skip_signal(signal_func):
@wraps(signal_func)
def _decorator(sender, instance, **kwargs):
@@ -38,6 +37,7 @@ def update_recipe_search_vector(sender, instance=None, created=False, **kwargs):
if SQLITE:
return
language = DICTIONARY.get(translation.get_language(), 'simple')
# these indexed fields are space wide, reading user preferences would lead to inconsistent behavior
instance.name_search_vector = SearchVector('name__unaccent', weight='A', config=language)
instance.desc_search_vector = SearchVector('description__unaccent', weight='C', config=language)
try:
@@ -76,8 +76,9 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
# apply changes from parent to instance for each inherited field
if instance.parent and inherit.count() > 0:
parent = instance.get_parent()
if 'ignore_shopping' in inherit:
instance.ignore_shopping = parent.ignore_shopping
for field in ['ignore_shopping', 'substitute_children', 'substitute_siblings']:
if field in inherit:
setattr(instance, field, getattr(parent, field, None))
# if supermarket_category is not set, do not cascade - if this becomes non-intuitive can change
if 'supermarket_category' in inherit and parent.supermarket_category:
instance.supermarket_category = parent.supermarket_category
@@ -87,49 +88,48 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
finally:
del instance.skip_signal
# TODO figure out how to generalize this
# apply changes to direct children - depend on save signals for those objects to cascade inheritance down
_save = []
for child in instance.get_children().filter(inherit_fields__field='ignore_shopping'):
child.ignore_shopping = instance.ignore_shopping
_save.append(child)
# don't cascade empty supermarket category
if instance.supermarket_category:
# apply changes to direct children - depend on save signals for those objects to cascade inheritance down
for child in instance.get_children().filter(inherit_fields__field='supermarket_category'):
child.supermarket_category = instance.supermarket_category
_save.append(child)
for child in set(_save):
for child in instance.get_children().filter(inherit_fields__in=Food.inheritable_fields):
# set inherited field values
for field in (inherit_fields := ['ignore_shopping', 'substitute_children', 'substitute_siblings']):
if field in instance.inherit_fields.values_list('field', flat=True):
setattr(child, field, getattr(instance, field, None))
# don't cascade empty supermarket category
if instance.supermarket_category and 'supermarket_category' in inherit_fields:
setattr(child, 'supermarket_category', getattr(instance, 'supermarket_category', None))
child.save()
@receiver(post_save, sender=MealPlan)
def auto_add_shopping(sender, instance=None, created=False, weak=False, **kwargs):
print("MEAL_AUTO_ADD Signal trying to auto add to shopping")
if not instance:
return
user = instance.get_owner()
with scope(space=instance.space):
slr_exists = instance.shoppinglistrecipe_set.exists()
if not created and slr_exists:
for x in instance.shoppinglistrecipe_set.all():
# assuming that permissions checks for the MealPlan have happened upstream
if instance.servings != x.servings:
SLR = RecipeShoppingEditor(id=x.id, user=user, space=instance.space)
SLR.edit_servings(servings=instance.servings)
# list_recipe = list_from_recipe(list_recipe=x, servings=instance.servings, space=instance.space)
elif not user.userpreference.mealplan_autoadd_shopping or not instance.recipe:
print("MEAL_AUTO_ADD Instance is none")
return
if created:
# if creating a mealplan - perform shopping list activities
# kwargs = {
# 'mealplan': instance,
# 'space': instance.space,
# 'created_by': user,
# 'servings': instance.servings
# }
SLR = RecipeShoppingEditor(user=user, space=instance.space)
SLR.create(mealplan=instance, servings=instance.servings)
try:
space = instance.get_space()
user = instance.get_owner()
with scope(space=space):
slr_exists = instance.shoppinglistrecipe_set.exists()
if not created and slr_exists:
for x in instance.shoppinglistrecipe_set.all():
# assuming that permissions checks for the MealPlan have happened upstream
if instance.servings != x.servings:
SLR = RecipeShoppingEditor(id=x.id, user=user, space=instance.space)
SLR.edit_servings(servings=instance.servings)
elif not user.userpreference.mealplan_autoadd_shopping or not instance.recipe:
print("MEAL_AUTO_ADD No recipe or no setting")
return
if created:
SLR = RecipeShoppingEditor(user=user, space=space)
SLR.create(mealplan=instance, servings=instance.servings)
print("MEAL_AUTO_ADD Created SLR")
except AttributeError:
pass
# list_recipe = list_from_recipe(**kwargs)

View File

@@ -1,3 +1,15 @@
.brand-icon {
height: 40px;
}
@media (max-width: 991.98px) {
.menu-dropdown-text {
font-size: 14px;
font-weight: 200;
}
}
.spinner-tandoor {
animation: rotation 3s infinite linear;
content: url("../assets/spinner.svg");

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More