Compare commits

...

106 Commits

Author SHA1 Message Date
vabene1111
afe46b3f67 Merge branch 'develop' 2021-11-04 15:30:39 +01:00
vabene1111
4b5edb4230 use safe version of coa package 2021-11-04 15:20:11 +01:00
vabene1111
11ea61094f remove package lock 2021-11-04 15:18:36 +01:00
vabene1111
e11d24b8c4 updated translations again 2021-11-04 14:57:00 +01:00
Kaibu
04822103c3 Merge branch 'develop_translate_backend' into develop
# Conflicts:
#	cookbook/locale/de/LC_MESSAGES/django.po
2021-11-04 14:55:09 +01:00
Kaibu
8041e092f7 Translated using Weblate (German)
Currently translated at 100.0% (496 of 496 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2021-11-04 13:53:39 +00:00
vabene1111
4c87440691 updated translations 2021-11-04 12:31:32 +01:00
vabene1111
e1056f9bbe Translated using Weblate (German)
Currently translated at 97.5% (484 of 496 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2021-11-04 11:29:56 +00:00
vabene1111
1fad1d2b8f improved deletion of recipes 2021-11-04 12:27:21 +01:00
Kaibu
980dc48eb8 Merge branch 'develop_translate_backend' into develop
# Conflicts:
#	vue/src/locales/de.json
2021-11-04 11:24:18 +01:00
FrenchAnon
835a34708d Translated using Weblate (French)
Currently translated at 94.5% (192 of 203 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2021-11-04 09:06:30 +00:00
Maximilian J
8247c8d2ca Translated using Weblate (German)
Currently translated at 100.0% (203 of 203 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2021-11-04 09:06:29 +00:00
FrenchAnon
3b612f5c8a Translated using Weblate (French)
Currently translated at 88.7% (440 of 496 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fr/
2021-11-04 09:06:29 +00:00
Kaibu
dd5509f5b4 translating new mealtypes 2021-11-03 23:55:39 +01:00
Kaibu
2215e06506 translation fixes 2021-11-03 21:34:18 +01:00
Kaibu
a40c8c3f83 added password reset from key templates 2021-11-03 20:44:36 +01:00
vabene1111
c2c51d5e1a Merge pull request #1012 from krial057/patch-2
prepTime and workTime of CookbookApp not imported correctly
2021-11-02 13:09:45 +01:00
krial057
c40f6986f1 prepTime and workTime of CookbookApp not imported correctly 2021-11-01 18:01:05 +01:00
vabene1111
4f1f1239c8 Merge branch 'develop' 2021-11-01 16:54:09 +01:00
vabene1111
486e2fca3e release trigger update 2021-11-01 16:53:59 +01:00
vabene1111
5aaf0fb237 Merge branch 'master' of https://github.com/vabene1111/recipes 2021-11-01 15:46:18 +01:00
vabene1111
a12b2ffb21 updated actions repo for organization 2021-11-01 14:58:04 +01:00
vabene1111
2bda4c85b7 Merge pull request #1004 from TandoorRecipes/dependabot/pip/django-3.2.9
Bump django from 3.2.8 to 3.2.9
2021-11-01 14:57:09 +01:00
vabene1111
70774bdb32 Merge pull request #1005 from TandoorRecipes/dependabot/npm_and_yarn/vue/vue/cli-plugin-eslint-4.5.15
Bump @vue/cli-plugin-eslint from 4.5.13 to 4.5.15 in /vue
2021-11-01 14:57:04 +01:00
vabene1111
7e8a3c2b43 Merge pull request #1006 from TandoorRecipes/dependabot/npm_and_yarn/vue/core-js-3.19.0
Bump core-js from 3.18.1 to 3.19.0 in /vue
2021-11-01 14:56:58 +01:00
vabene1111
8450cddc1e Merge pull request #1007 from TandoorRecipes/dependabot/npm_and_yarn/vue/vue/cli-plugin-typescript-4.5.15
Bump @vue/cli-plugin-typescript from 4.5.13 to 4.5.15 in /vue
2021-11-01 14:56:54 +01:00
vabene1111
a036f2d323 Merge pull request #1008 from TandoorRecipes/dependabot/npm_and_yarn/vue/babel/eslint-parser-7.16.0
Bump @babel/eslint-parser from 7.14.4 to 7.16.0 in /vue
2021-11-01 14:56:49 +01:00
vabene1111
4af5e9d18a Merge pull request #1009 from TandoorRecipes/dependabot/npm_and_yarn/vue/typescript-eslint/eslint-plugin-4.33.0
Bump @typescript-eslint/eslint-plugin from 4.26.1 to 4.33.0 in /vue
2021-11-01 14:56:43 +01:00
dependabot[bot]
6bb2b04986 Bump @typescript-eslint/eslint-plugin from 4.26.1 to 4.33.0 in /vue
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.26.1 to 4.33.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.33.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 13:52:11 +00:00
dependabot[bot]
c0bc0bd6c3 Bump @babel/eslint-parser from 7.14.4 to 7.16.0 in /vue
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.14.4 to 7.16.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.0/eslint/babel-eslint-parser)

---
updated-dependencies:
- dependency-name: "@babel/eslint-parser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 13:51:26 +00:00
dependabot[bot]
262238c96c Bump @vue/cli-plugin-typescript from 4.5.13 to 4.5.15 in /vue
Bumps [@vue/cli-plugin-typescript](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-typescript) from 4.5.13 to 4.5.15.
- [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/v4.5.15/packages/@vue/cli-plugin-typescript)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 13:51:07 +00:00
dependabot[bot]
3d41065f3b Bump core-js from 3.18.1 to 3.19.0 in /vue
Bumps [core-js](https://github.com/zloirock/core-js) from 3.18.1 to 3.19.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.18.1...v3.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 13:50:52 +00:00
dependabot[bot]
ff764cbbec Bump @vue/cli-plugin-eslint from 4.5.13 to 4.5.15 in /vue
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.13 to 4.5.15.
- [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/v4.5.15/packages/@vue/cli-plugin-eslint)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 13:50:37 +00:00
dependabot[bot]
7d3c7dce75 Bump django from 3.2.8 to 3.2.9
Bumps [django](https://github.com/django/django) from 3.2.8 to 3.2.9.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.8...3.2.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 13:50:19 +00:00
vabene1111
f66bf13ec5 Create FUNDING.yml 2021-11-01 12:51:14 +01:00
vabene1111
3e8bc0a42b another try at fixing the discord release bot 2021-11-01 12:25:53 +01:00
vabene1111
0e55fe162c renamed components to match recommended naming 2021-11-01 11:39:10 +01:00
vabene1111
355f2d30a6 -a 2021-11-01 11:37:55 +01:00
vabene1111
4efed9a1d2 improved html importer instruction line break behavior 2021-11-01 11:27:19 +01:00
vabene1111
e4924f9d27 improved recipe card time pill 2021-11-01 11:24:28 +01:00
vabene1111
77f0bf3628 Merge pull request #1003 from krial057/patch-1
Also show working/waiting time if only one of both is set
2021-11-01 11:21:20 +01:00
vabene1111
9a10f866e1 Merge remote-tracking branch 'origin/develop' into develop 2021-11-01 11:10:45 +01:00
vabene1111
66794d619f improved cookbook app importer 2021-11-01 11:10:35 +01:00
krial057
1a814aa9d1 Also show working/waiting time if only one of both is set 2021-11-01 10:40:03 +01:00
Oliver Cervera
6b4200acc3 Translated using Weblate (Italian)
Currently translated at 99.5% (201 of 202 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/
2021-11-01 08:47:19 +00:00
Jesse
7749ad1441 Translated using Weblate (Dutch)
Currently translated at 100.0% (202 of 202 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nl/
2021-11-01 08:47:19 +00:00
Kaibu
3d6d998774 Translated using Weblate (German)
Currently translated at 100.0% (202 of 202 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2021-11-01 08:47:19 +00:00
Kaibu
bcbd5c1103 Translated using Weblate (German)
Currently translated at 95.9% (476 of 496 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2021-11-01 08:47:19 +00:00
vabene1111
2d9b21b0d7 Merge pull request #974 from xeals/feature/kilojoules
Add user preference to display/edit using kilojoules
2021-11-01 09:47:14 +01:00
vabene1111
c9bd3ccae8 Merge branch 'develop' into feature/kilojoules 2021-11-01 09:46:04 +01:00
vabene1111
08aa5cc36e Merge pull request #998 from vabene1111/dependabot/pip/django-cors-headers-3.10.0
Bump django-cors-headers from 3.9.0 to 3.10.0
2021-11-01 08:54:53 +01:00
vabene1111
c3cbc2799b Merge pull request #999 from vabene1111/dependabot/pip/icalendar-4.0.9
Bump icalendar from 4.0.7 to 4.0.9
2021-11-01 08:54:48 +01:00
vabene1111
e0af020210 Merge pull request #1000 from vabene1111/dependabot/pip/boto3-1.19.7
Bump boto3 from 1.18.52 to 1.19.7
2021-11-01 08:54:42 +01:00
vabene1111
97c9b304f3 Merge pull request #1001 from vabene1111/dependabot/pip/uritemplate-4.1.1
Bump uritemplate from 3.0.1 to 4.1.1
2021-11-01 08:54:37 +01:00
vabene1111
2aa1df1c92 Merge pull request #1002 from vabene1111/dependabot/pip/pillow-8.4.0
Bump pillow from 8.3.2 to 8.4.0
2021-11-01 08:54:32 +01:00
dependabot[bot]
490e86a346 Bump boto3 from 1.18.52 to 1.19.7
Bumps [boto3](https://github.com/boto/boto3) from 1.18.52 to 1.19.7.
- [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.18.52...1.19.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 07:44:39 +00:00
dependabot[bot]
a495b853ea Bump uritemplate from 3.0.1 to 4.1.1
Bumps [uritemplate](https://github.com/python-hyper/uritemplate) from 3.0.1 to 4.1.1.
- [Release notes](https://github.com/python-hyper/uritemplate/releases)
- [Changelog](https://github.com/python-hyper/uritemplate/blob/main/HISTORY.rst)
- [Commits](https://github.com/python-hyper/uritemplate/compare/3.0.1...4.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 07:44:38 +00:00
vabene1111
0bd6ddae71 Merge remote-tracking branch 'origin/develop' into develop 2021-11-01 08:43:50 +01:00
dependabot[bot]
ef44ab1562 Bump icalendar from 4.0.7 to 4.0.9
Bumps [icalendar](https://github.com/collective/icalendar) from 4.0.7 to 4.0.9.
- [Release notes](https://github.com/collective/icalendar/releases)
- [Changelog](https://github.com/collective/icalendar/blob/master/CHANGES.rst)
- [Commits](https://github.com/collective/icalendar/compare/4.0.7...4.0.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 07:42:51 +00:00
dependabot[bot]
acd6a7fa76 Bump django-cors-headers from 3.9.0 to 3.10.0
Bumps [django-cors-headers](https://github.com/adamchainz/django-cors-headers) from 3.9.0 to 3.10.0.
- [Release notes](https://github.com/adamchainz/django-cors-headers/releases)
- [Changelog](https://github.com/adamchainz/django-cors-headers/blob/main/HISTORY.rst)
- [Commits](https://github.com/adamchainz/django-cors-headers/compare/3.9.0...3.10.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 07:42:35 +00:00
dependabot[bot]
e92c4d7b80 Bump pillow from 8.3.2 to 8.4.0
Bumps [pillow](https://github.com/python-pillow/Pillow) from 8.3.2 to 8.4.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/8.3.2...8.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 07:42:33 +00:00
vabene1111
1ca50c5932 Merge pull request #990 from vabene1111/dependabot/pip/django-storages-1.12.3
Bump django-storages from 1.11.1 to 1.12.3
2021-11-01 08:42:16 +01:00
vabene1111
61bb8abe0e Merge pull request #996 from vabene1111/dependabot/pip/pyyaml-6.0
Bump pyyaml from 5.4.1 to 6.0
2021-11-01 08:42:02 +01:00
vabene1111
7c4ecc7048 Merge pull request #986 from vabene1111/dependabot/pip/python-dotenv-0.19.1
Bump python-dotenv from 0.19.0 to 0.19.1
2021-11-01 08:29:57 +01:00
dependabot[bot]
8e09645f6c Bump pyyaml from 5.4.1 to 6.0
Bumps [pyyaml](https://github.com/yaml/pyyaml) from 5.4.1 to 6.0.
- [Release notes](https://github.com/yaml/pyyaml/releases)
- [Changelog](https://github.com/yaml/pyyaml/blob/master/CHANGES)
- [Commits](https://github.com/yaml/pyyaml/compare/5.4.1...6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 07:29:53 +00:00
vabene1111
ebf99c0889 Merge pull request #987 from vabene1111/dependabot/pip/jinja2-3.0.2
Bump jinja2 from 3.0.1 to 3.0.2
2021-11-01 08:29:48 +01:00
vabene1111
eecf646bdd Merge pull request #988 from vabene1111/dependabot/pip/django-tables2-2.4.1
Bump django-tables2 from 2.4.0 to 2.4.1
2021-11-01 08:29:37 +01:00
vabene1111
cacb9dd447 Merge pull request #989 from vabene1111/dependabot/pip/django-3.2.8
Bump django from 3.2.7 to 3.2.8
2021-11-01 08:29:27 +01:00
vabene1111
28612e910a update recipe scrapers 2021-11-01 08:29:11 +01:00
vabene1111
9f5f689c45 Merge pull request #991 from vabene1111/dependabot/npm_and_yarn/vue/typescript-4.4.4
Bump typescript from 4.4.3 to 4.4.4 in /vue
2021-11-01 08:28:51 +01:00
dependabot[bot]
2e046b1bcc Bump typescript from 4.4.3 to 4.4.4 in /vue
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.4.3 to 4.4.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.4.3...v4.4.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 07:26:43 +00:00
vabene1111
07785fae6b Merge pull request #992 from vabene1111/dependabot/npm_and_yarn/vue/eslint-plugin-vue-8.0.3
Bump eslint-plugin-vue from 7.10.0 to 8.0.3 in /vue
2021-11-01 08:26:14 +01:00
vabene1111
dc9cc95860 Merge pull request #993 from vabene1111/dependabot/npm_and_yarn/vue/workbox-webpack-plugin-6.3.0
Bump workbox-webpack-plugin from 6.1.5 to 6.3.0 in /vue
2021-11-01 08:26:03 +01:00
vabene1111
26bcfdda96 Merge pull request #994 from vabene1111/dependabot/npm_and_yarn/vue/vue/compiler-sfc-3.2.20
Bump @vue/compiler-sfc from 3.1.1 to 3.2.20 in /vue
2021-11-01 08:25:53 +01:00
vabene1111
f32a0a092c Merge pull request #995 from vabene1111/dependabot/npm_and_yarn/vue/vue-i18n-8.26.5
Bump vue-i18n from 8.24.4 to 8.26.5 in /vue
2021-11-01 08:25:42 +01:00
dependabot[bot]
74935b22b7 Bump vue-i18n from 8.24.4 to 8.26.5 in /vue
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.24.4 to 8.26.5.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.24.4...v8.26.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:16:08 +00:00
dependabot[bot]
e84a38a98e Bump @vue/compiler-sfc from 3.1.1 to 3.2.20 in /vue
Bumps [@vue/compiler-sfc](https://github.com/vuejs/vue-next/tree/HEAD/packages/compiler-sfc) from 3.1.1 to 3.2.20.
- [Release notes](https://github.com/vuejs/vue-next/releases)
- [Changelog](https://github.com/vuejs/vue-next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-next/commits/v3.2.20/packages/compiler-sfc)

---
updated-dependencies:
- dependency-name: "@vue/compiler-sfc"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:15:46 +00:00
dependabot[bot]
890def60d3 Bump workbox-webpack-plugin from 6.1.5 to 6.3.0 in /vue
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.1.5 to 6.3.0.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.1.5...v6.3.0)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:15:29 +00:00
dependabot[bot]
0ef69ada91 Bump eslint-plugin-vue from 7.10.0 to 8.0.3 in /vue
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.10.0 to 8.0.3.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.10.0...v8.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:14:53 +00:00
dependabot[bot]
4ea77882fc Bump django-storages from 1.11.1 to 1.12.3
Bumps [django-storages](https://github.com/jschneier/django-storages) from 1.11.1 to 1.12.3.
- [Release notes](https://github.com/jschneier/django-storages/releases)
- [Changelog](https://github.com/jschneier/django-storages/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jschneier/django-storages/compare/1.11.1...1.12.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:03:42 +00:00
dependabot[bot]
590e56f003 Bump django from 3.2.7 to 3.2.8
Bumps [django](https://github.com/django/django) from 3.2.7 to 3.2.8.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.7...3.2.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:03:37 +00:00
dependabot[bot]
47135e929d Bump django-tables2 from 2.4.0 to 2.4.1
Bumps [django-tables2](https://github.com/jieter/django-tables2) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/jieter/django-tables2/releases)
- [Changelog](https://github.com/jieter/django-tables2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jieter/django-tables2/compare/v2.4.0...v2.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:03:32 +00:00
dependabot[bot]
8d102727ff Bump jinja2 from 3.0.1 to 3.0.2
Bumps [jinja2](https://github.com/pallets/jinja) from 3.0.1 to 3.0.2.
- [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.1...3.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:03:28 +00:00
dependabot[bot]
4a85081d18 Bump python-dotenv from 0.19.0 to 0.19.1
Bumps [python-dotenv](https://github.com/theskumar/python-dotenv) from 0.19.0 to 0.19.1.
- [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.0...v0.19.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 00:03:23 +00:00
Kaibu
e7ce582959 readme update 2021-10-31 18:11:48 +01:00
Kaibu
31720927b1 deprecated old meal plan 2021-10-31 18:08:37 +01:00
vabene1111
b6845e06a5 Merge pull request #983 from lostlont/develop
Added LDAP usage in documentation
2021-10-31 15:23:36 +01:00
lostlont
831b7c391d Merge branch 'vabene1111:develop' into develop 2021-10-31 14:16:16 +01:00
Perjéssy, Lóránt
4eaf0df9a3 Added LDAP usage description in authentication page of documentation. 2021-10-31 14:10:57 +01:00
vabene1111
f720c5c094 fixed development server webpack path 2021-10-31 13:21:25 +01:00
vabene1111
83253be6ba Merge branch 'develop' 2021-10-29 14:56:28 +02:00
vabene1111
5badb305ae possible fix for tagged discord notification 2021-10-29 14:56:18 +02:00
vabene1111
4927f8bf4d fixed nutrition form 2021-10-29 14:25:20 +02:00
vabene1111
03cd85537d fixed exporter issue 2021-10-29 13:19:50 +02:00
vabene1111
6949e17a33 possibly fixed sub path hosting issues 2021-10-29 11:29:55 +02:00
vabene1111
6c8843ca74 reverted back to static public path 2021-10-26 16:24:37 +02:00
vabene1111
6a8003e904 trying relative path 2021-10-26 16:03:17 +02:00
vabene1111
bb6c53bc82 testing with public path auto 2021-10-26 15:45:38 +02:00
vabene1111
52904a9d72 Merge branch 'develop' 2021-10-26 15:43:02 +02:00
xeals
34d9f5a1d8 Correct capitalization for KJ in preference form 2021-10-25 17:46:05 +11:00
xeals
6dfd3ae1d7 Localize nutritional energy headings 2021-10-25 17:39:04 +11:00
xeals
15eec9d373 Set calories heading based on user preference 2021-10-25 17:38:41 +11:00
xeals
c9ff0543e3 Convert nutrition input from KJ to calories with preference 2021-10-25 17:37:31 +11:00
xeals
3d830a4449 Display nutritional energy in KJ with preference 2021-10-25 17:28:52 +11:00
xeals
b1b770c9e5 Add KJ user preference 2021-10-25 17:25:35 +11:00
vabene1111
52ab369fa7 Merge branch 'develop' 2021-10-14 13:29:34 +02:00
125 changed files with 8148 additions and 35047 deletions

View File

@@ -41,10 +41,17 @@ SHOPPING_MIN_AUTOSYNC_INTERVAL=5
# Default for user setting sticky navbar
# STICKY_NAV_PREF_DEFAULT=1
# If staticfiles are stored at a different location uncomment and change accordingly
# If base URL is something other than just / (you are serving a subfolder in your proxy for instance http://recipe_app/recipes/)
# SCRIPT_NAME=/recipes
# If staticfiles are stored at a different location uncomment and change accordingly, MUST END IN /
# this is not required if you are just using a subfolder
# This can either be a relative path from the applications base path or the url of an external host
# STATIC_URL=/static/
# If mediafiles are stored at a different location uncomment and change accordingly
# If mediafiles are stored at a different location uncomment and change accordingly, MUST END IN /
# this is not required if you are just using a subfolder
# This can either be a relative path from the applications base path or the url of an external host
# MEDIA_URL=/media/
# Serve mediafiles directly using gunicorn. Basically everyone recommends not doing this. Please use any of the examples
@@ -79,8 +86,6 @@ GUNICORN_MEDIA=0
# when unset: 0 (false)
REVERSE_PROXY_AUTH=0
# If base URL is something other than just / (you are serving a subfolder in your proxy for instance http://recipe_app/recipes/)
# SCRIPT_NAME=/recipes
# Default settings for spaces, apply per space and can be changed in the admin view
# SPACE_DEFAULT_MAX_RECIPES=0 # 0=unlimited recipes
# SPACE_DEFAULT_MAX_USERS=0 # 0=unlimited users per space

12
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [vabene1111]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -4,7 +4,7 @@ on: [push]
jobs:
build:
if: github.repository_owner == 'vabene1111'
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
strategy:
max-parallel: 4

View File

@@ -8,7 +8,7 @@ on:
jobs:
CodeQL-Build:
if: github.repository_owner == 'vabene1111'
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
steps:
- name: Checkout repository

View File

@@ -5,7 +5,7 @@ on:
- 'beta'
jobs:
build:
if: github.repository_owner == 'vabene1111'
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master

View File

@@ -7,7 +7,7 @@ on:
- '!master'
jobs:
build:
if: github.repository_owner == 'vabene1111'
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master

View File

@@ -6,7 +6,7 @@ on:
jobs:
build:
if: github.repository_owner == 'vabene1111'
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master

View File

@@ -1,13 +1,12 @@
name: publish tagged release docker
on:
push:
tags:
- '*'
release:
types: [published]
jobs:
build:
if: github.repository_owner == 'vabene1111'
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
name: Build image job
steps:
@@ -50,4 +49,4 @@ jobs:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
uses: Ilshidur/action-discord@0.3.2
with:
args: '🚀 A new Version of tandoor has been released 🥳 \n https://github.com/vabene1111/recipes/releases/tag/{{ steps.get_version.outputs.VERSION }}'
args: '🚀 Version {{ EVENT_PAYLOAD.release.tag_name }} of tandoor has been released 🥳 \nCheck it out *https://github.com/vabene1111/recipes/releases/tag/{{ EVENT_PAYLOAD.release.tag_name }}*'

View File

@@ -7,7 +7,7 @@ on:
jobs:
deploy:
if: github.repository_owner == 'vabene1111'
if: github.repository_owner == 'TandoorRecipes'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

View File

@@ -1,6 +1,6 @@
<h1 align="center">
<br>
<a href="https://app.tandoor.dev"><img src="https://github.com/vabene1111/recipes/raw/develop/docs/logo_color.svg" height="256px" width="256px"></a>
<a href="https://tandoor.dev"><img src="https://github.com/vabene1111/recipes/raw/develop/docs/logo_color.svg" height="256px" width="256px"></a>
<br>
Tandoor Recipes
<br>
@@ -15,46 +15,74 @@
<a href="https://discord.gg/RhzBrfWgtp" target="_blank" rel="noopener noreferrer"><img src="https://badgen.net/badge/icon/discord?icon=discord&label" ></a>
<a href="https://hub.docker.com/r/vabene1111/recipes" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/docker/pulls/vabene1111/recipes" ></a>
<a href="https://github.com/vabene1111/recipes/releases/latest" rel="noopener noreferrer"><img src="https://img.shields.io/github/v/release/vabene1111/recipes" ></a>
<a href="https://app.tandoor.dev/accounts/login/?demo" rel="noopener noreferrer"><img src="https://img.shields.io/badge/demo-available-success" ></a>
</p>
<p align="center">
<a href="https://tandoor.dev" target="_blank" rel="noopener noreferrer">Website</a> •
<a href="https://docs.tandoor.dev/install/docker/" target="_blank" rel="noopener noreferrer">Installation</a> •
<a href="https://docs.tandoor.dev/" target="_blank" rel="noopener noreferrer">Documentation</a> •
<a href="https://docs.tandoor.dev/" target="_blank" rel="noopener noreferrer">Docs</a> •
<a href="https://app.tandoor.dev/accounts/login/?demo" target="_blank" rel="noopener noreferrer">Demo</a> •
<a href="https://discord.gg/RhzBrfWgtp" target="_blank" rel="noopener noreferrer">Discord server</a>
<a href="https://discord.gg/RhzBrfWgtp" target="_blank" rel="noopener noreferrer">Discord</a>
</p>
![Preview](docs/preview.png)
# Your Feedback
## Core Features
- 🥗 **Manage your recipes** - Manage your ever growing recipe collection
- 📆 **Plan** - multiple meals for each day
- 🛒 **Shopping lists** - via the meal plan or straight from recipes
- 📚 **Cookbooks** - collect recipes into books
- 👪 **Share and collaborate** on recipes with friends and family
Share some information on how you use Tandoor to help me improve the application [Google Survey](https://forms.gle/qNfLK2tWTeWHe9Qd7)
## Made by and for power users
## Features
- 📦 **Sync** files with Dropbox and Nextcloud (more can easily be added)
- 🔍 Powerful **search** with Djangos [TrigramSimilarity](https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/search/#trigram-similarity)
- 🔍 Powerful & customizable **search** with fulltext support and [TrigramSimilarity](https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/search/#trigram-similarity)
- 🏷️ Create and search for **tags**, assign them in batch to all files matching certain filters
- 📄 **Create recipes** locally within a nice, standardized web interface
- **Import recipes** from thousands of websites supporting [ld+json or microdata](https://schema.org/Recipe)
- 📱 Optimized for use on **mobile** devices like phones and tablets
- 🛒 Generate **shopping** lists from recipes
- 📆 Create a **Plan** on what to eat when
- 👪 **Share** recipes with friends and comment on them to suggest or remember changes you made
- ➗ automatically convert decimal units to **fractions** for those who like this
- 🐳 Easy setup with **Docker** and included examples for Kubernetes, Unraid and Synology
- ↔️ Quickly merge and rename ingredients, tags and units
- 📥 **Import recipes** from thousands of websites supporting [ld+json or microdata](https://schema.org/Recipe)
- ➗ Support for **fractions** or decimals
- 🐳 Easy setup with **Docker** and included examples for **Kubernetes**, **Unraid** and **Synology**
- 🎨 Customize your interface with **themes**
- ✉️ Export and import recipes from other users
- 📦 **Sync** files with Dropbox and Nextcloud
## All the must haves
- 📱Optimized for use on **mobile** devices
- 🌍 localized in many languages thanks to the awesome community
- Many more like recipe scaling, image compression, cookbooks, printing views, ...
- 📥️ **Import your collection** from many other [recipe managers](https://docs.tandoor.dev/features/import_export/)
- Many more like recipe scaling, image compression, printing views and supermarkets
This application is meant for people with a collection of recipes they want to share with family and friends or simply
store them in a nicely organized way. A basic permission system exists but this application is not meant to be run as
a public page.
## Docs
Documentation can be found [here](https://docs.tandoor.dev/).
While this application has been around for a while and is actively used by many (including myself), it is still considered
**beta** software that has a lot of rough edges and unpolished parts.
## Contributing
You can help out with the ongoing development by looking for potential bugs in our code base, or by contributing new features. We are always welcoming new pull requests containing bug fixes, refactors and new features. We have a list of tasks and bugs on our issue tracker on Github. Please comment on issues if you want to contribute with, to avoid duplicating effort.
## Your Feedback
Share some information on how you use Tandoor to help me improve the application [Google Survey](https://forms.gle/qNfLK2tWTeWHe9Qd7)
## Get in touch
<table>
<tr>
<td><a href="https://discord.gg/RhzBrfWgtp">Discord</a></td>
<td>We have a public Discord server that anyone can join. This is where all our developers and contributors hang out and where we make announcements</td>
</tr>
<tr>
<td><a href="https://twitter.com/TandoorRecipes">Twitter</a></td>
<td>You can follow our Twitter account to get updates on new features or releases</td>
</tr>
</table>
## License
Beginning with version 0.10.0 the code in this repository is licensed under the [GNU AGPL v3](https://www.gnu.org/licenses/agpl-3.0.de.html) license with a

View File

@@ -39,12 +39,16 @@ class UserPreferenceForm(forms.ModelForm):
class Meta:
model = UserPreference
fields = (
'default_unit', 'use_fractions', 'theme', 'nav_color',
'default_unit', 'use_fractions', 'use_kj', 'theme', 'nav_color',
'sticky_navbar', 'default_page', 'show_recent', 'search_style',
'plan_share', 'ingredient_decimals', 'shopping_auto_sync',
'comments'
)
labels = {
'use_kj': 'Use KJ'
}
help_texts = {
'nav_color': _('Color of the top navigation bar. Not all colors work with all themes, just try them out!'),
# noqa: E501
@@ -52,6 +56,7 @@ class UserPreferenceForm(forms.ModelForm):
'use_fractions': _(
'Enables support for fractions in ingredient amounts (e.g. convert decimals to fractions automatically)'),
# noqa: E501
'use_kj': _('Display nutritional energy amounts in joules instead of calories'), # noqa: E501
'plan_share': _(
'Users with whom newly created meal plan/shopping list entries should be shared by default.'),
# noqa: E501

View File

@@ -246,7 +246,10 @@ def parse_instructions(instructions):
instruction_text += str(i)
instructions = instruction_text
return normalize_string(instructions)
normalized_string = normalize_string(instructions)
normalized_string = normalized_string.replace('\n', ' \n')
normalized_string = normalized_string.replace(' \n \n', '\n\n')
return normalized_string
def parse_image(image):

View File

@@ -4,9 +4,12 @@ import json
import re
from io import BytesIO
import requests
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 _
@@ -15,53 +18,51 @@ from gettext import gettext as _
class CookBookApp(Integration):
def import_file_name_filter(self, zip_info_object):
return zip_info_object.filename.endswith('.yml')
return zip_info_object.filename.endswith('.html')
def get_recipe_from_file(self, file):
recipe_yml = yaml.safe_load(file.getvalue().decode("utf-8"))
recipe_html = file.getvalue().decode("utf-8")
recipe_json, recipe_tree, html_data, images = get_recipe_from_source(recipe_html, 'CookBookApp', self.request)
recipe = Recipe.objects.create(
name=recipe_yml['name'].strip(),
name=recipe_json['name'].strip(),
created_by=self.request.user, internal=True,
space=self.request.space)
try:
recipe.servings = re.findall('([0-9])+', recipe_yml['recipeYield'])[0]
recipe.servings = re.findall('([0-9])+', recipe_json['recipeYield'])[0]
except Exception as e:
pass
try:
recipe.working_time = recipe_yml['prep_time'].replace(' minutes', '')
recipe.waiting_time = recipe_yml['cook_time'].replace(' minutes', '')
recipe.working_time = iso_duration_to_minutes(recipe_json['prepTime'])
recipe.waiting_time = iso_duration_to_minutes(recipe_json['cookTime'])
except Exception:
pass
if recipe_yml['on_favorites']:
recipe.keywords.add(Keyword.objects.get_or_create(name=_('Favorites'), space=self.request.space))
step = Step.objects.create(instruction=recipe_json['recipeInstructions'], space=self.request.space, )
step = Step.objects.create(instruction=recipe_yml['directions'], space=self.request.space, )
if 'notes' in recipe_yml and recipe_yml['notes'].strip() != '':
step.instruction = step.instruction + '\n\n' + recipe_yml['notes']
if 'nutritional_info' in recipe_yml:
step.instruction = step.instruction + '\n\n' + recipe_yml['nutritional_info']
if 'source' in recipe_yml and recipe_yml['source'].strip() != '':
step.instruction = step.instruction + '\n\n' + recipe_yml['source']
if 'nutrition' in recipe_json:
step.instruction = step.instruction + '\n\n' + recipe_json['nutrition']
step.save()
recipe.steps.add(step)
ingredient_parser = IngredientParser(self.request, True)
for ingredient in recipe_yml['ingredients'].split('\n'):
if ingredient.strip() != '':
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(ingredient)
u = ingredient_parser.get_unit(unit)
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=amount, note=note, space=self.request.space,
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))
except Exception as e:
print('failed to import image ', str(e))
recipe.save()
return recipe

View File

@@ -269,7 +269,8 @@ class Integration:
"""
raise NotImplementedError('Method not implemented in integration')
def handle_exception(self, exception, log=None, message=''):
@staticmethod
def handle_exception(exception, log=None, message=''):
if log:
if message:
log.msg += message

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

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2.7 on 2021-10-25 05:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0157_alter_searchpreference_trigram'),
]
operations = [
migrations.AddField(
model_name='userpreference',
name='use_kj',
field=models.BooleanField(default=False),
),
]

View File

@@ -19,7 +19,8 @@ from treebeard.mp_tree import MP_Node, MP_NodeManager
from django_scopes import ScopedManager, scopes_disabled
from django_prometheus.models import ExportModelOperationsMixin
from recipes.settings import (COMMENT_PREF_DEFAULT, FRACTION_PREF_DEFAULT,
STICKY_NAV_PREF_DEFAULT, SORT_TREE_BY_NAME)
KJ_PREF_DEFAULT, STICKY_NAV_PREF_DEFAULT,
SORT_TREE_BY_NAME)
def get_user_name(self):
@@ -217,6 +218,7 @@ class UserPreference(models.Model, PermissionModelMixin):
)
default_unit = models.CharField(max_length=32, default='g')
use_fractions = models.BooleanField(default=FRACTION_PREF_DEFAULT)
use_kj = models.BooleanField(default=KJ_PREF_DEFAULT)
default_page = models.CharField(
choices=PAGES, max_length=64, default=SEARCH
)
@@ -456,6 +458,9 @@ class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixi
from cookbook.helper.template_helper import render_instructions
return render_instructions(self)
def __str__(self):
return f'{self.pk} {self.name}'
class Meta:
ordering = ['order', 'pk']
indexes = (GinIndex(fields=["search_vector"]),)

View File

@@ -38,8 +38,13 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
return fields
except AttributeError:
pass
del fields['image']
del fields['numrecipe']
except KeyError:
pass
try:
del fields['image']
del fields['numrecipe']
except KeyError:
pass
return fields
def get_image(self, obj):

View File

@@ -0,0 +1,42 @@
{% extends "base.html" %}
{% load crispy_forms_filters %}
{% load i18n %}
{% load account %}
{% block head_title %}{% trans "Change Password" %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-12" style="text-align: center">
<h3>{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}</h3>
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %}
{% endif %}
</div>
</div>
<div class="row">
<div class="col-sm-12 col-lg-6 col-md-6 offset-lg-3 offset-md-3">
<hr>
{% if token_fail %}
{% url 'account_reset_password' as passwd_reset_url %}
<p>{% blocktrans %}The password reset link was invalid, possibly because it has already been used.
Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktrans %}</p>
{% else %}
{% if form %}
<form method="POST" action="{{ action_url }}">
{% csrf_token %}
{{ form | crispy }}
<input type="submit" class="btn btn-warning float-right" name="action"
value="{% trans 'change password' %}"/>
</form>
{% else %}
<p>{% trans 'Your password is now changed.' %}</p>
{% endif %}
{% endif %}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,22 @@
{% extends "base.html" %}
{% load i18n %}
{% load account %}
{% block title %}{% trans "Change Password" %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-12 col-lg-6 col-md-6 offset-lg-3 offset-md-3">
<hr>
<h3>{% trans "Change Password" %}</h3>
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %}
{% endif %}
<p>{% trans 'Your password is now changed.' %}</p>
</div>
</div>
{% endblock %}

View File

@@ -344,6 +344,7 @@
<script type="application/javascript">
localStorage.setItem('SCRIPT_NAME', "{% base_path request 'script' %}")
localStorage.setItem('BASE_PATH', "{% base_path request 'base' %}")
localStorage.setItem('STATIC_URL', "{% base_path request 'static_base' %}")
window.addEventListener("load", () => {
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("{% url 'service_worker' %}", {scope: "{% base_path request 'base' %}" + '/'}).then(function (reg) {

View File

@@ -32,6 +32,9 @@
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}'
window.RECIPE_ID = {{ recipe.pk }}
window.DEFAULT_UNIT = '{{request.user.userpreference.default_unit}}'
window.USER_PREF = {
'use_kj': {% if request.user.userpreference.use_kj %} true {% else %} false {% endif %},
}
</script>

View File

@@ -22,13 +22,11 @@
</div>
{{ form|crispy }}
{% if related_objects %}
{% blocktrans %} <i>{{ object }}</i> could not be deleted because it is still referenced by the following instances: {% endblocktrans %}
<br/>
<br/>
{% for o in related_objects %}
{% if protected_objects %}
<h5>{% trans 'Protected' %} <small class="text-muted">The object you are trying to delete is <b>protected</b> by the following references to it.</small></h5>
{% for o in protected_objects %}
{% class_name o.model as name %}
<h5>{{ name }}</h5>
<u>{{ name }}</u>
<ul>
{% for e in o %}
<li>
@@ -36,14 +34,40 @@
</li>
{% endfor %}
</ul>
{% endfor %}
<br/>
{% endif %}
<button class="btn btn-success" type="submit" href="{{ success_url }}"><i
{% if cascading_objects %}
<h5>{% trans 'Cascade' %} <small class="text-muted">The object you are trying to delete is used by the following objects which will <b>also be deleted</b>.</small></h5>
{% for o in cascading_objects %}
{% class_name o.model as name %}
<u>{{ name }}</u>
<ul>
{% for e in o %}
<li>
<span class="badge badge-info">#{{ e.id }}</span> {{ e }}
</li>
{% endfor %}
</ul>
{% endfor %}
{% endif %}
{% if set_null_objects %}
<h5>{% trans 'Remove' %} <small class="text-muted">The object you are trying to delete is used by the following objects from which the reference will be removed.</small></h5>
{% for o in set_null_objects %}
{% class_name o.model as name %}
<u>{{ name }}</u>
<ul>
{% for e in o %}
<li>
<span class="badge badge-info">#{{ e.id }}</span> {{ e }}
</li>
{% endfor %}
</ul>
{% endfor %}
{% endif %}
<button class="btn btn-success" type="submit" href="{{ success_url }}" {% if protected_objects %}disabled{% endif %}><i
class="fas fa-trash-alt"></i> {% trans 'Confirm' %}</button>
<a href="javascript:history.back()" class="btn btn-danger"><i class="fas fa-undo-alt"></i> {% trans 'Cancel' %}
</a>

View File

@@ -28,6 +28,8 @@
<script type="application/javascript">
window.IMAGE_PLACEHOLDER = "{% static 'assets/recipe_no_image.svg' %}"
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}'
{% if current_file_size_mb %}
window.CURRENT_FILE_SIZE_MB = {{ current_file_size_mb|unlocalize }}
window.MAX_FILE_SIZE_MB = {{ max_file_size_mb|unlocalize }}

View File

@@ -1,742 +1,36 @@
{% extends "base.html" %}
{% load i18n %}
{% load static %}
{% load render_bundle from webpack_loader %}
{% load static %}
{% load i18n %}
{% load l10n %}
{% block title %}{% trans 'Meal-Plan' %}{% endblock %}
{% block extra_head %}
{% block content_fluid %}
{% include 'include/vue_base.html' %}
<div id="app">
<meal-plan-view></meal-plan-view>
</div>
<script src="{% static 'js/moment-with-locales.min.js' %}"></script>
<script src="{% static 'js/Sortable.min.js' %}"></script>
<script src="{% static 'js/vuedraggable.umd.min.js' %}"></script>
<script src="{% static 'js/vue-cookies.js' %}"></script>
<script src="{% static 'js/js.cookie.min.js' %}"></script>
{% endblock %}
{% block content %}
<div id="app">
<div class="row mt-2 mb-1">
<div class="col-md-4 offset-md-4">
<div class="input-group">
<div class="input-group-prepend">
<button class="btn btn-outline-secondary shadow-none"
@click="changeStartDate(number_of_days * -1)">
<i class="fas fa-arrow-left"></i>
</button>
</div>
<input name="date" id="id_date" class="form-control" type="date" v-model="start_date"
@change="updatePlan()">
<div class="input-group-append">
<button class="btn btn-outline-secondary shadow-none" @click="changeStartDate(number_of_days)">
<i class="fas fa-arrow-right"></i>
</button>
</div>
</div>
</div>
<div class="col-md-4">
<a href="{% url 'view_plan_new' %}" class="float-right">
<button class="btn btn-outline-secondary shadow-none">
<i class="fas fa-star"></i> {% trans 'Try the new meal planner' %}
</button>
</a>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-sm table-striped table-responsive-sm" style=" table-layout:fixed;">
<thead class="thead-dark" style="background-image: url({% static 'assets/header.svg' %});">
<tr>
<th class="thead-blank" v-for="d in dates" style="width: 14.2%; text-align: center;">
[[formatDateDayname(d)]]<br/>[[formatDateDay(d)]].
<button class="btn btn-sm btn-outline-secondary shadow-none" @click="addDayToShopping(d)"><i
class="fas fa-cart-plus fa-sm"></i></button>
</th>
</tr>
</thead>
<tbody v-for="t in meal_types">
<tr v-if="meal_plan[t.name] !== undefined">
<td :colspan="number_of_days" style="text-align: center">
[[ meal_plan[t.name].name]]
<template
v-if="t.created_by !== {{ request.user.pk }} && user_names[t.created_by] !== undefined">
([[ user_names[t.created_by] ]])
</template>
</td>
</tr>
<tr v-if="meal_plan[t.name] !== undefined">
<td v-for="d in meal_plan[t.name].days">
<draggable class="list-group" :list="d.items" group="plan" style="min-height: 40px"
@change="dragChanged(d.date, t, $event)"
:empty-insert-threshold="10" handle=".handle">
<div class="" v-for="(element, index) in d.items" :key="element.id">
<!-- small layout with handle -->
<div class="d-block d-md-none">
<div class="col-">
<i class="fas fa-arrows-alt handle input-group-text"
style="width: 100%"></i>
</div>
<div class="list-group-item" style="word-wrap: break-word;">
<a href="#" @click="plan_detail = element" data-toggle="modal"
data-target="#id_plan_detail_modal">[[ planElementName(element)]]</a>
</div>
</div>
<!-- big layout -->
<div class="list-group-item handle d-md-block d-none"
style="word-wrap: break-word; padding: 2;margin-bottom: 4">
<div class="col-md-12" style="padding: 0">
<a href="#" @click="plan_detail = element" data-toggle="modal"
data-target="#id_plan_detail_modal">[[ planElementName(element)]]</a>
</div>
</div>
</div>
</draggable>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card">
<div class="card-header">
<i class="fas fa-calendar-plus"></i> {% trans 'New Entry' %} <a href="#" data-toggle="modal"
data-target="#id_plan_help_modal"><i
class="far fa-question-circle"></i></a>
</div>
<div class="row">
<div class="col-md-6">
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="input-group mb-3">
<input type="text" class="form-control" v-model="recipe_query" @keyup="getRecipes"
placeholder="{% trans 'Search Recipe' %}">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button"
@click="getRandomRecipes">
<i class="fas fa-dice"></i>
</button>
</div>
</div>
</div>
</div>
<draggable class="list-group" :list="recipes"
:group="{ name: 'plan', pull: 'clone', put: false }" :clone="cloneRecipe">
<div class="list-group-item d-flex align-items-center justify-content-between"
v-for="(element, index) in recipes" :key="element.id">
<span>
<i class="fas fa-arrows-alt"></i> [[element.name]]
</span>
<span class="badge badge-light badge-pill">[[element.servings]]</span>
</div>
</draggable>
</div>
</div>
<div class="col-md-6">
<div>
<div class="card-body">
<input type="text" class="form-control" v-model="new_note_title"
placeholder="{% trans 'Title' %}" style="margin-bottom: 8px">
<textarea class="form-control" v-model="new_note_text"
placeholder="{% trans 'Note (optional)' %}"></textarea>
<small><span
class="text-muted">{% trans 'You can use markdown to format this field. See the <a href="/docs/markdown/" target="_blank" rel="noopener noreferrer">docs here</a>' %}</span></small>
<br/>
<br/>
<input type="number" class="form-control" v-model="new_note_servings"
placeholder="{% trans 'Serving Count' %}" style="margin-bottom: 8px">
<br/>
<draggable :list="pseudo_note_list"
:group="{ name: 'plan', pull: 'clone', put: false }" :clone="cloneNote">
<div class="list-group-item" v-for="(element, index) in pseudo_note_list"
:key="element.id">
<i class="fas fa-arrows-alt"></i> {% trans 'Create only note' %}
</div>
</draggable>
</div>
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<i class="fas fa-shopping-cart"></i> {% trans 'Shopping List' %}
</div>
<div class="card-body">
<template v-if="shopping_list.length < 1">{% trans 'Shopping list currently empty' %}</template>
<template v-else>
<a v-bind:href="getShoppingUrl()" class="btn btn-success"
target="_blank">{% trans 'Open Shopping List' %}</a>
<br/>
<br/>
{% trans 'Recipes' %}
<ul class="list-group" style="margin-top: 8px">
<li class="list-group-item" v-for="item in shopping_list"> [[ item.recipe_name ]]</li>
</ul>
</template>
</div>
</div>
</div>
<div class="col-md-6" style="margin-top: 8px">
<div class="card">
<div class="card-header">
<i class="fas fa-shopping-cart"></i> {% trans 'Plan' %}
</div>
<div class="card-body">
<div class="row">
<div class="col">
<label>
{% trans 'Number of Days' %}
<input class="form-control" type="number" v-model="number_of_days"
@change="updatePlan(); $cookies.set('number_of_days',number_of_days, -1)">
</label>
</div>
</div>
<div class="row">
<div class="col">
<label>
{% trans 'Weekday offset' %}
<input class="form-control" type="number" v-model="start_offset"
@change="updatePlan(); $cookies.set('start_offset',start_offset, -1)">
<small class="text-muted">{% trans 'Number of days starting from the first day of the week to offset the default view.' %}</small>
</label>
</div>
</div>
<a href="#" data-toggle="modal"
data-target="#id_plan_types_modal">{% trans 'Edit plan types' %}</a> <br/>
<a href="#" data-toggle="modal"
data-target="#id_plan_help_modal">{% trans 'Show help' %}</a><br/>
<a v-bind:href="getIcalUrl()">{% trans 'Week iCal export' %}</a>
</div>
</div>
</div>
</div>
<br/>
<br/>
<div class="modal fade" id="id_plan_detail_modal" tabindex="-1" role="dialog"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<template v-if="plan_detail.title !==''">[[ plan_detail.title ]]</template>
<template v-else>[[ plan_detail.recipe_name ]]</template>
<small
class="text-muted"><br/>[[ plan_detail.meal_type_name ]] [[
formatLocalDate(plan_detail.date) ]]</small>
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<template v-if="plan_detail.recipe_name !== undefined ">
<small class="text-muted">{% trans 'Recipe' %}</small><br/>
<a v-bind:href="planDetailRecipeUrl()" target="_blank">[[ plan_detail.recipe_name ]]</a>
<br/>
<br/>
<small class="text-muted">{% trans 'Serving Count' %}</small><br/>
<span>[[ plan_detail.servings ]]</span>
</template>
<template v-if="plan_detail.note !== ''">
<small class="text-muted">{% trans 'Note' %}</small><br/>
<span v-html="plan_detail.note_markdown"></span>
<br/>
</template>
<br/>
<br/>
<template v-if="plan_detail.created_by !== undefined ">
<small class="text-muted">{% trans 'Created by' %}</small><br/>
[[ user_names[plan_detail.created_by] ]]
<br/>
</template>
<template v-if="plan_detail.shared.length > 0">
<small class="text-muted">{% trans 'Shared with' %}</small><br/>
<span>[[ planDetailUserList() ]]</span>
<br/>
</template>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger"
@click="deleteEntry(plan_detail)">{% trans 'Delete' %}</button>
<button type="button" class="btn btn-success"
v-if="!shopping_list.includes(plan_detail) && plan_detail.recipe_name !== undefined"
@click="shopping_list.push(plan_detail)">{% trans 'Add to Shopping' %}</button>
<a class="btn btn-primary" v-bind:href="planDetailEditUrl()">{% trans 'Edit' %}</a>
<button type="button" class="btn btn-secondary"
data-dismiss="modal">{% trans 'Close' %}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="id_plan_types_modal" tabindex="-1" role="dialog"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{% trans 'Edit plan types' %}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<draggable :list="meal_types_edit" handle=".handle"
:group="{ name: 'types'}">
<div v-for="(element, index) in meal_types_edit"
:key="element.id">
<template v-if="!element.delete">
<div class="input-group mb-3">
<div class="input-group-prepend handle">
<button tabindex="-1" class="btn btn-outline-secondary"><i
class="fas fa-arrows-alt-v"></i></button>
</div>
<input class="form-control" v-model="element.name">
<div class="input-group-append">
<button tabindex="-1" class="btn btn-outline-danger" type="button"
@click="markTypeDelete(element)"><i class="fas fa-trash-alt"></i>
</button>
</div>
</div>
</template>
</div>
</draggable>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary"
@click="meal_types_edit.push({name:'{% trans 'New meal type' %}', delete:false})">{% trans 'New' %}</button>
<button type="button" class="btn btn-success"
@click="updatePlanTypes()">{% trans 'Save' %}</button>
<button type="button" class="btn btn-secondary"
data-dismiss="modal">{% trans 'Close' %}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="id_plan_help_modal" tabindex="-1" role="dialog"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{% trans 'Meal Plan Help' %}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
{% blocktrans %}
<p>The meal plan module allows planning of meals both with recipes and notes.</p>
<p>Simply select a recipe from the list of recently viewed recipes or search the one you
want and drag it to the desired plan position. You can also add a note and a title and
then drag the recipe to create a plan entry with a custom title and note. Creating only
Notes is possible by dragging the create note box into the plan.</p>
<p>Click on a recipe in order to open the detailed view. There you can also add it to the
shopping list. You can also add all recipes of a day to the shopping list by
clicking the shopping cart at the top of the table.</p>
<p>Since a common use case is to plan meals together you can define
users you want to share your plan with in the settings.
</p>
<p>You can also edit the types of meals you want to plan. If you share your plan with
someone with
different meals, their meal types will appear in your list as well. To prevent
duplicates (e.g. Other and Misc.)
name your meal types the same as the users you share your meals with and they will be
merged.</p>
{% endblocktrans %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-dismiss="modal">{% trans 'Close' %}</button>
</div>
</div>
</div>
</div>
</div>
<script src="{% url 'javascript-catalog' %}"></script>
{% block script %}
{% if debug %}
<script src="{% url 'js_reverse' %}"></script>
{% else %}
<script src="{% static 'django_js_reverse/reverse.js' %}"></script>
{% endif %}
<script type="application/javascript">
moment.locale('{{request.LANGUAGE_CODE}}');
window.IMAGE_PLACEHOLDER = "{% static 'assets/recipe_no_image.svg' %}"
let csrftoken = Cookies.get('csrftoken');
Vue.http.headers.common['X-CSRFToken'] = csrftoken;
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}'
let app = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
start_date: undefined,
start_offset: 0,
dates: [],
number_of_days: $cookies.isKey('number_of_days') ? $cookies.get('number_of_days') : 7,
plan_entries: [],
meal_types: [],
meal_types_edit: [],
meal_plan: {},
plan_detail: {shared: []},
recipes: [],
recipe_query: '',
pseudo_note_list: [
{id: 0, title: '', text: ''}
],
new_note_title: '',
new_note_text: '',
new_note_servings: '',
default_shared_users: [],
user_id_update: [],
user_names: {},
shopping: false,
shopping_list: [],
},
mounted: function () {
this.default_shared_users = [{% for u in request.user.userpreference.plan_share.all %}
{{ u.pk }},
{% endfor %}]
this.$set(this.user_names, {{ request.user.pk }}, '{{ request.user.get_user_name }}')
this.user_id_update = Array.from(this.default_shared_users)
this.start_offset = $cookies.isKey('start_offset') ? $cookies.get('start_offset') : 0;
this.start_date = moment().weekday(0).add(this.start_offset, 'days').format('YYYY-MM-DD')
this.updatePlan();
this.getRecipes();
//this.makeToast('success', 'this actually works', 'success')
},
methods: {
makeToast: function (title, message, variant = null) {
this.$bvToast.toast(message, {
title: title,
variant: variant,
toaster: 'b-toaster-top-center',
solid: true
})
},
updatePlan: function () {
this.dates = [];
for (var i = 0; i <= (this.number_of_days - 1); i++) {
this.dates.push(moment(this.start_date).add(i, 'days'));
}
let planEntryPromise = this.getPlanEntries();
let planTypePromise = this.getPlanTypes();
Promise.allSettled([planEntryPromise, planTypePromise]).then(() => {
this.buildGrid()
})
},
getPlanEntries: function () {
return this.$http.get("{% url 'api:mealplan-list' %}?from_date=" + this.dates[0].format('YYYY-MM-DD') + "&to_date=" + this.dates[this.dates.length - 1].format('YYYY-MM-DD')).then((response) => {
this.plan_entries = response.data;
}).catch((err) => {
console.log("getPlanEntries error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
})
},
getPlanTypes: function () {
return this.$http.get("{% url 'api:mealtype-list' %}").then((response) => {
this.meal_types = response.data;
this.meal_types_edit = jQuery.extend(true, [], response.data);
for (let mte of this.meal_types_edit) {
this.$set(mte, 'delete', false)
}
if (this.meal_types.length === 0) {
this.makeToast(gettext('Information'), gettext('To use the meal plan please first create at least one meal plan type.'), 'warning')
}
}).catch((err) => {
console.log("getPlanTypes error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
})
},
buildGrid: function () {
this.meal_plan = {}
for (let e of this.plan_entries) {
let new_type = {id: e.meal_type, name: e.meal_type_name, created_by: e.created_by}
if (this.meal_types.filter(el => el.name === new_type.name).length === 0) {
this.meal_types.push(new_type)
}
}
for (let t of this.meal_types) {
this.$set(this.meal_plan, t.name, {
name: t.name,
meal_type: t.id,
days: {}
})
for (let d of this.dates) {
this.$set(this.meal_plan[t.name].days, d.format('YYYY-MM-DD'), {
name: this.formatDateDayname(d),
date: d.format('YYYY-MM-DD'),
items: []
})
}
}
for (let e of this.plan_entries) {
this.meal_plan[e.meal_type_name].days[e.date].items.push(e)
for (let u of e.shared) {
if (!this.user_id_update.includes(parseInt(u))) {
this.user_id_update.push(parseInt(u))
}
}
}
this.updateUserNames()
},
getRandomRecipes: function () {
this.$set(this, 'recipe_query', '');
this.getRecipes();
},
getRecipes: function () {
let url = "{% url 'api:recipe-list' %}?page_size=5"
if (this.recipe_query !== '') {
url += '&query=' + this.recipe_query;
} else {
url += '&random=true'
}
this.$http.get(url).then((response) => {
this.recipes = this.removeDuplicates(response.data.results, recipe => recipe.id);
}).catch((err) => {
console.log("getRecipes error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
})
},
getMdNote: function () {
let url = "{% url 'api:recipe-list' %}?page_size=5"
if (this.recipe_query !== '') {
url += '&query=' + this.recipe_query;
}
this.$http.get(url).then((response) => {
this.recipes = response.data.results;
}).catch((err) => {
console.log("getRecipes error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
})
},
updateUserNames: function () {
return this.$http.get("{% url 'api:username-list' %}?filter_list=[" + this.user_id_update + ']').then((response) => {
for (let u of response.data) {
this.$set(this.user_names, u.id, u.username);
}
}).catch((err) => {
console.log("updateUserNames error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
})
},
dragChanged: function (date, meal_type, evt) {
if (evt.added !== undefined) {
let plan_entry = evt.added.element
plan_entry.date = date
plan_entry.meal_type = meal_type
plan_entry.meal_type_name = meal_type.name
if (plan_entry.is_new) { // its not a meal plan object
plan_entry.created_by = {{ request.user.id }};
plan_entry.shared = this.default_shared_users
this.$http.post(`{% url 'api:mealplan-list' %}`, plan_entry).then((response) => {
let entry = response.data
this.meal_plan[entry.meal_type_name].days[entry.date].items = this.meal_plan[entry.meal_type_name].days[entry.date].items.filter(item => !item.is_new)
this.meal_plan[entry.meal_type_name].days[entry.date].items.push(entry)
}).catch((err) => {
console.log("dragChanged create error", err);
})
} else {
this.$http.put(`{% url 'api:mealplan-list' %}${plan_entry.id}/`, plan_entry).then((response) => {
}).catch((err) => {
console.log("dragChanged update error", err);
this.makeToast(gettext('Error'), gettext('There was an error updating a resource!') + err.bodyText, 'danger')
})
}
}
},
deleteEntry: function (entry) {
$('#id_plan_detail_modal').modal('hide')
this.$http.delete(`{% url 'api:mealplan-list' %}${entry.id}/`, entry).then((response) => {
this.meal_plan[entry.meal_type_name].days[entry.date].items = this.meal_plan[entry.meal_type_name].days[entry.date].items.filter(item => item !== entry)
}).catch((err) => {
console.log("deleteEntry error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
})
},
removeDuplicates: function (data, key) {
return [
...new Map(data.map(item => [key(item), item])).values()
]
},
updatePlanTypes: function () {
let promise_list = []
let i = 0
for (let x of this.meal_types_edit) {
x.order = i
i++
if (x.id === undefined && !x.delete) {
x.created_by = {{ request.user.id }}
promise_list.push(this.$http.post("{% url 'api:mealtype-list' %}", x).then((response) => {
}).catch((err) => {
console.log("updatePlanTypes create error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
}))
} else if (x.delete) {
if (x.id !== undefined) {
promise_list.push(this.$http.delete(`{% url 'api:mealtype-list' %}${x.id}/`, x).then((response) => {
}).catch((err) => {
console.log("updatePlanTypes delete error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
}))
}
} else {
promise_list.push(this.$http.put(`{% url 'api:mealtype-list' %}${x.id}/`, x).then((response) => {
}).catch((err) => {
console.log("updatePlanTypes update error: ", err);
this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger')
}))
}
}
Promise.allSettled(promise_list).then(() => {
this.updatePlan()
$('#id_plan_types_modal').modal('hide')
})
},
markTypeDelete: function (element) {
if (confirm(gettext('When deleting a meal type all entries using that type will be deleted as well. Deletion will apply when configuration is saved. Do you want to proceed?'))) {
element.delete = true
}
},
cloneRecipe: function (recipe) {
let r = {
id: Math.round(Math.random() * 1000) + 10000,
recipe: recipe,
recipe_name: recipe.name,
servings: (this.new_note_servings > 1) ? this.new_note_servings : recipe.servings,
title: this.new_note_title,
note: this.new_note_text,
is_new: true
}
console.log(recipe)
this.new_note_title = ''
this.new_note_text = ''
this.new_note_servings = ''
return r
},
cloneNote: function () {
let new_entry = {
id: Math.round(Math.random() * 1000) + 10000,
title: this.new_note_title,
note: this.new_note_text,
servings: 1,
is_new: true,
}
if (new_entry.title === '') {
new_entry.title = gettext('Title')
}
this.new_note_title = ''
this.new_note_text = ''
this.new_note_servings = ''
return new_entry
},
planElementName: function (element) {
if (element.title) {
return element.title
} else if (element.recipe_name) {
return element.recipe_name
} else {
return element.name
}
},
planDetailRecipeUrl: function () {
return "{% url 'view_recipe' 12345 %}".replace(/12345/, this.plan_detail.recipe.id);
},
planDetailEditUrl: function () {
return "{% url 'edit_meal_plan' 12345 %}".replace(/12345/, this.plan_detail.id);
},
planDetailUserList: function () {
let users = []
for (let u of this.plan_detail.shared) {
users.push(this.user_names[u])
}
return users.join(', ')
},
formatLocalDate: function (date) {
return moment(date).format('LL')
},
formatDateDay: function (date) {
return moment(date).format('D')
},
formatDateDayname: function (date) {
return moment(date).format('dddd')
},
changeStartDate: function (change) {
this.start_date = moment(this.start_date).add(change, 'days').format('YYYY-MM-DD')
this.updatePlan();
},
getShoppingUrl: function () {
let url = "{% url 'view_shopping' %}"
let first = true
for (let se of this.shopping_list) {
if (first) {
url += `?r=[${se.recipe.id},${se.servings}]`
first = false
} else {
url += `&r=[${se.recipe.id},${se.servings}]`
}
}
return url
},
getIcalUrl: function () {
if (this.dates.length === 0) {
return ""
}
return "{% url 'api_get_plan_ical' 12345 6789 %}".replace(/12345/, this.dates[0].format('YYYY-MM-DD')).replace(/6789/, this.dates[this.dates.length - 1].format('YYYY-MM-DD'));
},
addDayToShopping: function (date) {
for (let t of this.meal_types) {
for (let i of this.meal_plan[t.name].days[date.format('YYYY-MM-DD')].items) {
if (!this.shopping_list.includes(i)) {
this.shopping_list.push(i)
}
}
}
}
}
});
window.ICAL_URL = '{% url 'api_get_plan_ical' 12345 6789 %}'
window.SHOPPING_URL = '{% url 'view_shopping' %}'
</script>
{% render_bundle 'meal_plan_view' %}
{% endblock %}

View File

@@ -69,6 +69,7 @@
window.USER_PREF = {
'use_fractions': {% if request.user.userpreference.use_fractions %} true {% else %} false {% endif %},
'ingredient_decimals': {% if request.user.userpreference.use_fractions %} {{ request.user.userpreference.ingredient_decimals }} {% else %} 2 {% endif %},
'use_kj': {% if request.user.userpreference.use_kj %} true {% else %} false {% endif %},
}
</script>

View File

@@ -142,7 +142,7 @@ def bookmarklet(request):
localStorage.setItem('redirectURL', '" + server + reverse('data_import_url') + "'); \
localStorage.setItem('token', '" + api_token.__str__() + "'); \
document.body.appendChild(document.createElement(\'script\')).src=\'" \
+ server + prefix + static('js/bookmarklet.js') + "? \
+ server + prefix + static('js/bookmarklet.js') + "? \
r=\'+Math.floor(Math.random()*999999999);}})();"
return re.sub(r"[\n\t\s]*", "", bookmark)
@@ -153,3 +153,5 @@ def base_path(request, path_type):
return request._current_scheme_host + request.META.get('HTTP_X_SCRIPT_NAME', '')
elif path_type == 'script':
return request.META.get('HTTP_X_SCRIPT_NAME', '')
elif path_type == 'static_base':
return static('vue/manifest.json').replace('vue/manifest.json', '')

View File

@@ -58,7 +58,6 @@ urlpatterns = [
path('search/v2/', views.search_v2, name='view_search_v2'),
path('books/', views.books, name='view_books'),
path('plan/', views.meal_plan, name='view_plan'),
path('plan_new/', views.meal_plan_new, name='view_plan_new'),
path('plan/entry/<int:pk>', views.meal_plan_entry, name='view_plan_entry'),
path('shopping/', views.shopping_list, name='view_shopping'),
path('shopping/<int:pk>', views.shopping_list, name='view_shopping'),

View File

@@ -1,4 +1,5 @@
from django.contrib import messages
from django.db import models
from django.db.models import ProtectedError
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
@@ -24,30 +25,36 @@ class RecipeDelete(GroupRequiredMixin, DeleteView):
success_url = reverse_lazy('index')
def delete(self, request, *args, **kwargs):
obj = self.get_object()
related_objects = []
for x in obj._meta.get_fields():
try:
related = x.related_model.objects.filter(**{x.field.name: obj})
if related.exists():
related_objects.append(related)
except AttributeError:
pass
if related_objects:
self.object = obj
return render(request, template_name=self.template_name, context=self.get_context_data(related_objects=related_objects))
self.object = self.get_object()
# TODO make this more generic so that all delete functions benefit from this
if self.get_context_data()['protected_objects']:
return render(request, template_name=self.template_name, context=self.get_context_data())
success_url = self.get_success_url()
obj.delete()
self.object.delete()
return HttpResponseRedirect(success_url)
def get_context_data(self, **kwargs):
context = super(RecipeDelete, self).get_context_data(**kwargs)
context['title'] = _("Recipe")
if 'related_objects' in kwargs:
context['related_objects'] = kwargs.pop('related_objects')
# TODO make this more generic so that all delete functions benefit from this
self.object = self.get_object()
context['protected_objects'] = []
context['cascading_objects'] = []
context['set_null_objects'] = []
for x in self.object._meta.get_fields():
try:
related = x.related_model.objects.filter(**{x.field.name: self.object})
if related.exists() and x.on_delete == models.PROTECT:
context['protected_objects'].append(related)
if related.exists() and x.on_delete == models.CASCADE:
context['cascading_objects'].append(related)
if related.exists() and x.on_delete == models.SET_NULL:
context['set_null_objects'].append(related)
except AttributeError:
pass
return context

View File

@@ -220,11 +220,6 @@ def meal_plan(request):
return render(request, 'meal_plan.html', {})
@group_required('user')
def meal_plan_new(request):
return render(request, 'meal_plan_new.html', {})
@group_required('user')
def supermarket(request):
return render(request, 'supermarket.html', {})
@@ -307,6 +302,7 @@ def user_settings(request):
up.ingredient_decimals = form.cleaned_data['ingredient_decimals'] # noqa: E501
up.comments = form.cleaned_data['comments']
up.use_fractions = form.cleaned_data['use_fractions']
up.use_kj = form.cleaned_data['use_kj']
up.sticky_navbar = form.cleaned_data['sticky_navbar']
up.shopping_auto_sync = form.cleaned_data['shopping_auto_sync']
@@ -343,10 +339,13 @@ def user_settings(request):
if fields_searched == 0:
search_form.add_error(None, _('You must select at least one field to search!'))
search_error = True
elif search_form.cleaned_data['search'] in ['websearch', 'raw'] and len(search_form.cleaned_data['fulltext']) == 0:
search_form.add_error('search', _('To use this search method you must select at least one full text search field!'))
elif search_form.cleaned_data['search'] in ['websearch', 'raw'] and len(
search_form.cleaned_data['fulltext']) == 0:
search_form.add_error('search',
_('To use this search method you must select at least one full text search field!'))
search_error = True
elif search_form.cleaned_data['search'] in ['websearch', 'raw'] and len(search_form.cleaned_data['trigram']) > 0:
elif search_form.cleaned_data['search'] in ['websearch', 'raw'] and len(
search_form.cleaned_data['trigram']) > 0:
search_form.add_error(None, _('Fuzzy search is not compatible with this search method!'))
search_error = True
else:
@@ -385,7 +384,8 @@ def user_settings(request):
else:
preference_form = UserPreferenceForm()
fields_searched = len(sp.icontains.all()) + len(sp.istartswith.all()) + len(sp.trigram.all()) + len(sp.fulltext.all())
fields_searched = len(sp.icontains.all()) + len(sp.istartswith.all()) + len(sp.trigram.all()) + len(
sp.fulltext.all())
if sp and not search_error and fields_searched > 0:
search_form = SearchPreferenceForm(instance=sp)
elif not search_error:
@@ -395,7 +395,8 @@ def user_settings(request):
api_token = Token.objects.create(user=request.user)
# these fields require postgress - just disable them if postgress isn't available
if not settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']:
if not settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2',
'django.db.backends.postgresql']:
search_form.fields['search'].disabled = True
search_form.fields['lookup'].disabled = True
search_form.fields['trigram'].disabled = True

View File

@@ -60,6 +60,25 @@ Use the superuser account to grant permissions to the newly created users.
To link an account to an already existing normal user go to the settings page of the user and link it.
Here you can also unlink your account if you no longer want to use a social login method.
## LDAP
LDAP authentication can be enabled in the `.env` file by setting `LDAP_AUTH=1`.
If set, users listed in the LDAP instance will be able to sign in without signing up.
These variables must be set to configure the connection to the LDAP instance:
```
AUTH_LDAP_SERVER_URI=ldap://ldap.example.org:389
AUTH_LDAP_BIND_DN=uid=admin,ou=users,dc=example,dc=org
AUTH_LDAP_BIND_PASSWORD=adminpassword
AUTH_LDAP_USER_SEARCH_BASE_DN=ou=users,dc=example,dc=org
```
Additional optional variables:
```
AUTH_LDAP_USER_SEARCH_FILTER_STR=(uid=%(user)s)
AUTH_LDAP_USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn', 'email': 'mail'}
AUTH_LDAP_ALWAYS_UPDATE_USER=1
AUTH_LDAP_CACHE_TIMEOUT=3600
```
## Reverse Proxy Authentication
!!! Info "Community Contributed Tutorial"

View File

@@ -36,7 +36,7 @@ Overview of the capabilities of the different integrations.
| RezKonv | ✔️ | ❌ | ❌ |
| OpenEats | ✔️ | ❌ | ⌚ |
| Plantoeat | ✔️ | ❌ | ✔ |
| CookBookApp | ✔️ | ⌚ | |
| CookBookApp | ✔️ | ⌚ | ✔️ |
✔ = implemented, ❌ = not implemented and not possible/planned, ⌚ = not yet implemented
@@ -217,4 +217,4 @@ Plan to eat allow to export a text file containing all your recipes. Simply uplo
## CookBookApp
CookBookApp can export .zip files containing .yml files. Upload the entire ZIP to Tandoor to import all conluded recipes.
CookBookApp can export .zip files containing .html files. Upload the entire ZIP to Tandoor to import all included recipes.

View File

@@ -1,72 +1,79 @@
<h1 align="center">
<br>
<a href="https://app.tandoor.dev"><img src="https://github.com/vabene1111/recipes/raw/develop/docs/logo_color.svg" height="256px" width="256px"></a>
<a href="https://tandoor.dev"><img src="https://github.com/vabene1111/recipes/raw/develop/docs/logo_color.svg" height="256px" width="256px"></a>
<br>
Tandoor Recipes
<br>
</h1>
<h4 align="center">This is my personal beta of vabene's excellent recipe app. It includes many of the new features I've developed and should be considered experimental.</h4>
## Experimental Features
- Manual import recipes from URL & Source (HTML/JSON)
- Bookmarklet to import recipes from any website
- Full Text Search
- Hierarchical Keywords
## Coming Next
- Heirarchical Ingredients
- Faceted Search
- Search filter by rating
- What Can I Make Now?
- Better ingredient/unit matching on import
- Custom word replacement on import (e.g. 'grams' automatically imported as 'g')
- improved ingredient parser (items in parens moved to notes)
- quick view ingredients
- quick view associated recipe
- favorite recipes
<h4 align="center">The recipe manager that allows you to manage your ever growing collection of digital recipes.</h4>
<p align="center">
<img src="https://github.com/vabene1111/recipes/workflows/Continous%20Integration/badge.svg?branch=develop" >
<img src="https://img.shields.io/github/stars/vabene1111/recipes" >
<img src="https://img.shields.io/github/forks/vabene1111/recipes" >
<img src="https://img.shields.io/docker/pulls/vabene1111/recipes" >
<a href="https://github.com/vabene1111/recipes/actions" target="_blank" rel="noopener noreferrer"><img src="https://github.com/vabene1111/recipes/workflows/Continous%20Integration/badge.svg?branch=master" ></a>
<a href="https://github.com/vabene1111/recipes/stargazers" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/github/stars/vabene1111/recipes" ></a>
<a href="https://github.com/vabene1111/recipes/network/members" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/github/forks/vabene1111/recipes" ></a>
<a href="https://discord.gg/RhzBrfWgtp" target="_blank" rel="noopener noreferrer"><img src="https://badgen.net/badge/icon/discord?icon=discord&label" ></a>
<a href="https://hub.docker.com/r/vabene1111/recipes" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/docker/pulls/vabene1111/recipes" ></a>
<a href="https://github.com/vabene1111/recipes/releases/latest" rel="noopener noreferrer"><img src="https://img.shields.io/github/v/release/vabene1111/recipes" ></a>
<a href="https://app.tandoor.dev/accounts/login/?demo" rel="noopener noreferrer"><img src="https://img.shields.io/badge/demo-available-success" ></a>
</p>
<p align="center">
<a href="https://docs.tandoor.dev/install/docker.html" rel="noopener noreferrer">Installation</a> •
<a href="https://docs.tandoor.dev/" target="_blank" rel="noopener noreferrer">Documentation</a> •
<a href="https://app.tandoor.dev/" target="_blank" rel="noopener noreferrer">Demo</a>
<a href="https://tandoor.dev" target="_blank" rel="noopener noreferrer">Website</a> •
<a href="https://docs.tandoor.dev/install/docker/" target="_blank" rel="noopener noreferrer">Installation</a> •
<a href="https://docs.tandoor.dev/" target="_blank" rel="noopener noreferrer">Docs</a>
<a href="https://app.tandoor.dev/accounts/login/?demo" target="_blank" rel="noopener noreferrer">Demo</a> •
<a href="https://discord.gg/RhzBrfWgtp" target="_blank" rel="noopener noreferrer">Discord</a>
</p>
![Preview](preview.png)
!!! info "WIP"
The documentation is work in progress. New information will be added over time.
Feel free to open pull requests to enhance the documentation.
## Core Features
- 🥗 **Manage your recipes** with a fast and intuitive editor
- 📆 **Plan** multiple meals for each day
- 🛒 **Shopping lists** via the meal plan or straight from recipes
- 📚 **Cookbooks** collect recipes into books
- 👪 **Share and collaborate** on recipes with friends and family
## Features
## Made by and for power users
- 📦 **Sync** files with Dropbox and Nextcloud (more can easily be added)
- 🔍 Powerful **search** with Djangos [TrigramSimilarity](https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/search/#trigram-similarity)
- 🔍 Powerful & customizable **search** with fulltext support and [TrigramSimilarity](https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/search/#trigram-similarity)
- 🏷️ Create and search for **tags**, assign them in batch to all files matching certain filters
- 📄 **Create recipes** locally within a nice, standardized web interface
- **Import recipes** from thousands of websites supporting [ld+json or microdata](https://schema.org/Recipe)
- 📱 Optimized for use on **mobile** devices like phones and tablets
- 🛒 Generate **shopping** lists from recipes
- 📆 Create a **Plan** on what to eat when
- 👪 **Share** recipes with friends and comment on them to suggest or remember changes you made
- ➗ automatically convert decimal units to **fractions** for those who like this
- 🐳 Easy setup with **Docker** and included examples for Kubernetes, Unraid and Synology
- ↔️ Quickly merge and rename ingredients, tags and units
- 📥 **Import recipes** from thousands of websites supporting [ld+json or microdata](https://schema.org/Recipe)
- ➗ Support for **fractions** or decimals
- 🐳 Easy setup with **Docker** and included examples for **Kubernetes**, **Unraid** and **Synology**
- 🎨 Customize your interface with **themes**
- ✉️ Export and import recipes from other users
- 📦 **Sync** files with Dropbox and Nextcloud
## All the must haves
- 📱Optimized for use on **mobile** devices
- 🌍 localized in many languages thanks to the awesome community
- Many more like recipe scaling, image compression, cookbooks, printing views, ...
- 📥️ **Import your collection** from many other [recipe managers](https://docs.tandoor.dev/features/import_export/)
- Many more like recipe scaling, image compression, printing views and supermarkets
This application is meant for people with a collection of recipes they want to share with family and friends or simply
store them in a nicely organized way. A basic permission system exists but this application is not meant to be run as
a public page.
## Your Feedback
Share some information on how you use Tandoor to help me improve the application [Google Survey](https://forms.gle/qNfLK2tWTeWHe9Qd7)
## Get in touch
<table>
<tr>
<td><a href="https://discord.gg/RhzBrfWgtp">Discord</a></td>
<td>We have a public Discord server that anyone can join. This is where all our developers and contributors hang out and where we make announcements</td>
</tr>
<tr>
<td><a href="https://twitter.com/TandoorRecipes">Twitter</a></td>
<td>You can follow our Twitter account to get updates on new features or releases</td>
</tr>
</table>
## Roadmap
This application has been under rapid development over the last year.

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,52 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr "Englisch"
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr "Deutsch"
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
#, fuzzy
#| msgid "English"
msgid "Polish"
msgstr "Englisch"
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,42 +17,50 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -19,42 +19,50 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
"2);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,42 +17,50 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,42 +18,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"POT-Creation-Date: 2021-11-04 14:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,42 +17,50 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: .\recipes\settings.py:324
#: .\recipes\settings.py:353
msgid "Armenian "
msgstr ""
#: .\recipes\settings.py:325
#: .\recipes\settings.py:354
msgid "Catalan"
msgstr ""
#: .\recipes\settings.py:326
#: .\recipes\settings.py:355
msgid "Czech"
msgstr ""
#: .\recipes\settings.py:327
#: .\recipes\settings.py:356
msgid "Dutch"
msgstr ""
#: .\recipes\settings.py:328
#: .\recipes\settings.py:357
msgid "English"
msgstr ""
#: .\recipes\settings.py:329
#: .\recipes\settings.py:358
msgid "French"
msgstr ""
#: .\recipes\settings.py:330
#: .\recipes\settings.py:359
msgid "German"
msgstr ""
#: .\recipes\settings.py:331
#: .\recipes\settings.py:360
msgid "Italian"
msgstr ""
#: .\recipes\settings.py:332
#: .\recipes\settings.py:361
msgid "Latvian"
msgstr ""
#: .\recipes\settings.py:333
#: .\recipes\settings.py:362
msgid "Polish"
msgstr ""
#: .\recipes\settings.py:363
msgid "Russian"
msgstr ""
#: .\recipes\settings.py:364
msgid "Spanish"
msgstr ""

View File

@@ -44,6 +44,7 @@ REVERSE_PROXY_AUTH = bool(int(os.getenv('REVERSE_PROXY_AUTH', False)))
# default value for user preference 'comment'
COMMENT_PREF_DEFAULT = bool(int(os.getenv('COMMENT_PREF_DEFAULT', True)))
FRACTION_PREF_DEFAULT = bool(int(os.getenv('FRACTION_PREF_DEFAULT', False)))
KJ_PREF_DEFAULT = bool(int(os.getenv('KJ_PREF_DEFAULT', False)))
STICKY_NAV_PREF_DEFAULT = bool(int(os.getenv('STICKY_NAV_PREF_DEFAULT', True)))
# minimum interval that users can set for automatic sync of shopping lists

View File

@@ -1,11 +1,11 @@
Django==3.2.7
Django==3.2.9
cryptography==35.0.0
django-annoying==0.10.6
django-autocomplete-light==3.8.2
django-cleanup==5.2.0
django-crispy-forms==1.13.0
django-filter==21.1
django-tables2==2.4.0
django-tables2==2.4.1
djangorestframework==3.12.4
drf-writable-nested==0.6.3
bleach==4.1.0
@@ -13,31 +13,31 @@ bleach-allowlist==1.0.3
gunicorn==20.1.0
lxml==4.6.3
Markdown==3.3.4
Pillow==8.3.2
Pillow==8.4.0
psycopg2-binary==2.9.1
python-dotenv==0.19.0
python-dotenv==0.19.1
requests==2.26.0
simplejson==3.17.5
six==1.16.0
webdavclient3==3.14.6
whitenoise==5.3.0
icalendar==4.0.7
pyyaml==5.4.1
uritemplate==3.0.1
icalendar==4.0.9
pyyaml==6.0
uritemplate==4.1.1
beautifulsoup4==4.10.0
microdata==0.7.1
Jinja2==3.0.1
Jinja2==3.0.2
django-webpack-loader==1.4.1
django-js-reverse==0.9.1
django-allauth==0.45.0
recipe-scrapers==13.4.0
recipe-scrapers==13.5.0
django-scopes==1.2.0
pytest==6.2.5
pytest-django==4.4.0
django-treebeard==4.5.1
django-cors-headers==3.9.0
django-storages==1.11.1
boto3==1.18.52
django-cors-headers==3.10.0
django-storages==1.12.3
boto3==1.19.7
django-prometheus==2.1.0
django-hCaptcha==0.1.0
python-ldap==3.3.1

27362
vue/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,14 +8,14 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@babel/eslint-parser": "^7.13.14",
"@babel/eslint-parser": "^7.16.0",
"@kangc/v-md-editor": "^1.7.7",
"@kevinfaguiar/vue-twemoji-picker": "^5.7.4",
"@popperjs/core": "^2.10.1",
"@riophae/vue-treeselect": "^0.4.0",
"axios": "^0.21.4",
"bootstrap-vue": "^2.21.2",
"core-js": "^3.18.1",
"core-js": "^3.19.0",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"prismjs": "^1.25.0",
@@ -24,7 +24,7 @@
"vue-click-outside": "^1.1.0",
"vue-clickaway": "^2.2.2",
"vue-cookies": "^1.7.4",
"vue-i18n": "^8.24.4",
"vue-i18n": "^8.26.5",
"vue-infinite-loading": "^2.4.5",
"vue-multiselect": "^2.1.6",
"vue-property-decorator": "^9.1.2",
@@ -33,23 +33,23 @@
"vue2-touch-events": "^3.2.2",
"vuedraggable": "^2.24.3",
"vuex": "^3.6.0",
"workbox-webpack-plugin": "^6.1.5"
"workbox-webpack-plugin": "^6.3.0"
},
"devDependencies": {
"@kazupon/vue-i18n-loader": "^0.5.0",
"@typescript-eslint/eslint-plugin": "^4.26.1",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.32.0",
"@vue/cli-plugin-babel": "~4.5.13",
"@vue/cli-plugin-eslint": "~4.5.13",
"@vue/cli-plugin-eslint": "~4.5.15",
"@vue/cli-plugin-pwa": "~4.5.13",
"@vue/cli-plugin-typescript": "^4.5.13",
"@vue/cli-plugin-typescript": "^4.5.15",
"@vue/cli-service": "~4.5.13",
"@vue/compiler-sfc": "^3.1.1",
"@vue/compiler-sfc": "^3.2.20",
"@vue/eslint-config-typescript": "^7.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^7.28.0",
"eslint-plugin-vue": "^7.10.0",
"typescript": "~4.4.3",
"eslint-plugin-vue": "^8.0.3",
"typescript": "~4.4.4",
"vue-cli-plugin-i18n": "^2.1.1",
"webpack-bundle-tracker": "1.4.0",
"workbox-expiration": "^6.3.0",
@@ -81,6 +81,7 @@
"not dead"
],
"resolutions": {
"@vue/cli-plugin-pwa/workbox-webpack-plugin": "^5.1.3"
"@vue/cli-plugin-pwa/workbox-webpack-plugin": "^5.1.3",
"coa": "2.0.2"
}
}

View File

@@ -4,6 +4,14 @@ import i18n from '@/i18n'
Vue.config.productionTip = false
// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
let publicPath = localStorage.STATIC_URL + 'vue/'
if (process.env.NODE_ENV === 'development') {
publicPath = 'http://localhost:8080/'
}
export default __webpack_public_path__ = publicPath // eslint-disable-line
new Vue({
i18n,
render: h => h(App),

View File

@@ -61,10 +61,10 @@ import Vue from 'vue'
import {BootstrapVue} from 'bootstrap-vue'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import {ApiApiFactory} from "../../utils/openapi/api";
import CookbookSlider from "../../components/CookbookSlider";
import LoadingSpinner from "../../components/LoadingSpinner";
import {StandardToasts} from "../../utils/utils";
import {ApiApiFactory} from "@/utils/openapi/api";
import CookbookSlider from "@/components/CookbookSlider";
import LoadingSpinner from "@/components/LoadingSpinner";
import {StandardToasts} from "@/utils/utils";
Vue.use(BootstrapVue)
@@ -119,7 +119,7 @@ export default {
createNew: function () {
let apiClient = new ApiApiFactory()
apiClient.createRecipeBook({name: 'New Book', description: '', icon: '', shared: []}).then(result => {
apiClient.createRecipeBook({name: this.$t('New_Cookbook'), description: '', icon: '', shared: []}).then(result => {
let new_book = result.data
this.refreshData()
StandardToasts.makeStandardToast(StandardToasts.SUCCESS_CREATE)

View File

@@ -4,6 +4,14 @@ import i18n from '@/i18n'
Vue.config.productionTip = false
// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
let publicPath = localStorage.STATIC_URL + 'vue/'
if (process.env.NODE_ENV === 'development') {
publicPath = 'http://localhost:8080/'
}
export default __webpack_public_path__ = publicPath // eslint-disable-line
new Vue({
i18n,
render: h => h(App),

View File

@@ -4,6 +4,14 @@ import i18n from '@/i18n'
Vue.config.productionTip = false
// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
let publicPath = localStorage.STATIC_URL + 'vue/'
if (process.env.NODE_ENV === 'development') {
publicPath = 'http://localhost:8080/'
}
export default __webpack_public_path__ = publicPath // eslint-disable-line
new Vue({
i18n,
render: h => h(App),

View File

@@ -203,7 +203,7 @@
</a>
</div>
<div class="col-md-3 col-6">
<button class="btn btn-block btn-primary shadow-none disabled" v-b-tooltip.focus.top :title="$t('Coming-Soon')">{{ $t('Auto-Planner') }}</button>
<button class="btn btn-block btn-primary shadow-none disabled" v-b-tooltip.focus.top :title="$t('Coming_Soon')">{{ $t('Auto_Planner') }}</button>
</div>
<div class="col-12 d-flex justify-content-center mt-2 d-block d-md-none">
<b-button-toolbar key-nav aria-label="Toolbar with button groups">
@@ -231,22 +231,24 @@
<script>
import Vue from "vue";
import {BootstrapVue} from 'bootstrap-vue'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import ContextMenu from "@/components/ContextMenu/ContextMenu";
import ContextMenuItem from "@/components/ContextMenu/ContextMenuItem";
import {CalendarView, CalendarMathMixin} from "vue-simple-calendar/src/components/bundle";
import Vue from "vue";
import {ApiApiFactory} from "@/utils/openapi/api";
import MealPlanCard from "../../components/MealPlanCard";
import moment from 'moment'
import {ApiMixin, StandardToasts} from "@/utils/utils";
import MealPlanEditModal from "../../components/MealPlanEditModal";
import VueCookies from "vue-cookies";
import MealPlanCard from "@/components/MealPlanCard";
import MealPlanEditModal from "@/components/MealPlanEditModal";
import MealPlanCalenderHeader from "@/components/MealPlanCalenderHeader";
import EmojiInput from "../../components/Modals/EmojiInput";
import draggable from 'vuedraggable'
import EmojiInput from "@/components/Modals/EmojiInput";
import moment from "moment"
import draggable from "vuedraggable"
import VueCookies from "vue-cookies";
import {ApiMixin, StandardToasts} from "@/utils/utils";
import {CalendarView, CalendarMathMixin} from "vue-simple-calendar/src/components/bundle";
import {ApiApiFactory} from "@/utils/openapi/api";
const {makeToast} = require("@/utils/utils");
@@ -375,6 +377,7 @@ export default {
}
})
this.$root.$on('change', this.updateEmoji);
this.$i18n.locale = window.CUSTOM_LOCALE
},
watch: {
settings: {
@@ -418,7 +421,7 @@ export default {
newMealType() {
let apiClient = new ApiApiFactory()
apiClient.createMealType({name: "Mealtype"}).then(e => {
apiClient.createMealType({name: this.$t('Meal_Type')}).then(e => {
this.periodChangedCallback(this.current_period)
}).catch(error => {
StandardToasts.makeStandardToast(StandardToasts.FAIL_UPDATE)

View File

@@ -4,6 +4,13 @@ import i18n from '@/i18n'
Vue.config.productionTip = false
// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
let publicPath = localStorage.STATIC_URL + 'vue/'
if (process.env.NODE_ENV === 'development') {
publicPath = 'http://localhost:8080/'
}
export default __webpack_public_path__ = publicPath // eslint-disable-line
new Vue({
i18n,
render: h => h(App),

View File

@@ -156,7 +156,7 @@ export default {
this.getItems({page:1},'left')
}
})
this.$i18n.locale = window.CUSTOM_LOCALE
},
methods: {
// this.genericAPI inherited from ApiMixin

View File

@@ -4,6 +4,14 @@ import i18n from '@/i18n'
Vue.config.productionTip = false
// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
let publicPath = localStorage.STATIC_URL + 'vue/'
if (process.env.NODE_ENV === 'development') {
publicPath = 'http://localhost:8080/'
}
export default __webpack_public_path__ = publicPath // eslint-disable-line
new Vue({
i18n,
render: h => h(App),

View File

@@ -4,6 +4,14 @@ import i18n from "@/i18n";
Vue.config.productionTip = false
// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
let publicPath = localStorage.STATIC_URL + 'vue/'
if (process.env.NODE_ENV === 'development') {
publicPath = 'http://localhost:8080/'
}
export default __webpack_public_path__ = publicPath // eslint-disable-line
new Vue({
i18n,
render: h => h(App),

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