Compare commits

...

645 Commits

Author SHA1 Message Date
renovate[bot]
faf716cb7e fix(deps): update dependency gunicorn to v22 (#3479)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-16 23:07:01 -05:00
Michael Genson
46f1ad7941 fix: Bad Recipe Rating Calc Preventing App Startup (#3475) 2024-04-16 20:47:15 +00:00
p0lycarpio
6e1112c73e fix: make groups private by default (#3474) 2024-04-16 15:12:00 -05:00
Hayden
6bd5a82b92 rewrite logger to support custom config files (#3104) 2024-04-16 15:52:49 +00:00
renovate[bot]
cba076b6a4 chore(deps): update dependency ruff to v0.3.7 (#3458)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-16 10:41:00 -05:00
Michael Genson
2ff1135b00 fix: duplicate ld+json data (#3444)
Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
2024-04-16 10:54:14 +00:00
renovate[bot]
467b9c6d65 fix(deps): update dependency apprise to v1.7.6 (#3464)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
2024-04-16 10:46:17 +00:00
renovate[bot]
176e471276 fix(deps): update dependency orjson to v3.10.1 (#3467)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-16 20:35:27 +10:00
renovate[bot]
193888fb30 chore(deps): update dependency mkdocs-material to v9.5.18 (#3468)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-16 00:13:49 -05:00
Hayden
13edefbf41 New Crowdin updates (#3465) 2024-04-14 19:21:05 +02:00
Hayden
fd33468fda New Crowdin updates (#3462) 2024-04-13 17:24:37 +02:00
Michael Genson
2a541f081a feat: User-specific Recipe Ratings (#3345) 2024-04-11 21:28:43 -05:00
renovate[bot]
8ab09cf03b fix(deps): update dependency tzdata to v2024 (#3456)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-12 01:49:18 +00:00
Hayden
9e6ae2e514 chore: remove black (#3437) 2024-04-11 20:36:55 -05:00
renovate[bot]
94678fe6e0 chore(deps): update dependency ruff to v0.3.6 (#3451)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-11 15:39:17 -05:00
renovate[bot]
ed533c8fad fix(deps): update dependency pydantic to v2.7.0 (#3452)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-11 15:24:24 -05:00
Hayden
93f7d15917 New Crowdin updates (#3447) 2024-04-10 14:39:49 +02:00
Hayden
53aa4dab51 New Crowdin updates (#3443) 2024-04-09 15:07:18 +02:00
tba-code
92659c64eb fix: properly escape postgres password (#3424)
Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
2024-04-08 14:47:57 +00:00
Hayden
6f871c6bdb New Crowdin updates (#3441) 2024-04-08 10:57:49 +00:00
renovate[bot]
f4f511aad6 Update dependency rapidfuzz to v3.8.1 (#3439)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-08 20:08:52 +10:00
Hayden
03d384f3a5 New Crowdin updates (#3435) 2024-04-07 09:45:46 -08:00
renovate[bot]
0c2917a112 Update dependency rapidfuzz to v3.8.0 (#3431)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-06 12:02:11 -05:00
boc-the-git
606a8f03a3 Merge pull request #3429 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-04-06 21:40:31 +11:00
Hayden
2d31c0abf2 New translations en-us.json (French, Canada) 2024-04-06 05:29:58 -05:00
Hayden
15c752d428 New translations en-us.json (Latvian) 2024-04-06 05:29:58 -05:00
Hayden
b254cf3833 New translations en-us.json (Croatian) 2024-04-06 05:29:57 -05:00
Hayden
0bd023d8a8 New translations en-us.json (Portuguese, Brazilian) 2024-04-06 05:29:56 -05:00
Hayden
aad50f2267 New translations en-us.json (Icelandic) 2024-04-06 05:29:55 -05:00
Hayden
fcbc57b392 New translations en-us.json (Galician) 2024-04-06 05:29:54 -05:00
Hayden
a62299e6ef New translations en-us.json (Vietnamese) 2024-04-06 05:29:53 -05:00
Hayden
82563fa948 New translations en-us.json (Chinese Traditional) 2024-04-06 05:29:52 -05:00
Hayden
7583c56b35 New translations en-us.json (Chinese Simplified) 2024-04-06 05:29:51 -05:00
Hayden
b9cc2dc257 New translations en-us.json (Ukrainian) 2024-04-06 05:29:50 -05:00
Hayden
0dcf81e764 New translations en-us.json (Turkish) 2024-04-06 05:29:49 -05:00
Hayden
3d3763d4b9 New translations en-us.json (Serbian (Cyrillic)) 2024-04-06 05:29:49 -05:00
Hayden
517727a4b6 New translations en-us.json (Slovenian) 2024-04-06 05:29:48 -05:00
Hayden
1c26dff1e9 New translations en-us.json (Slovak) 2024-04-06 05:29:47 -05:00
Hayden
ed1834d945 New translations en-us.json (Russian) 2024-04-06 05:29:46 -05:00
Hayden
bf8bc88ffb New translations en-us.json (Portuguese) 2024-04-06 05:29:45 -05:00
Hayden
6c48eba5f7 New translations en-us.json (Norwegian) 2024-04-06 05:29:44 -05:00
Hayden
dc7df0d4aa New translations en-us.json (Dutch) 2024-04-06 05:29:43 -05:00
Hayden
45d5194f19 New translations en-us.json (Lithuanian) 2024-04-06 05:29:42 -05:00
Hayden
8ad1a15bf1 New translations en-us.json (Korean) 2024-04-06 05:29:41 -05:00
Hayden
57aeb401b8 New translations en-us.json (Japanese) 2024-04-06 05:29:41 -05:00
Hayden
e15a2f35e2 New translations en-us.json (Italian) 2024-04-06 05:29:40 -05:00
Hayden
b28e135ceb New translations en-us.json (Hungarian) 2024-04-06 05:29:39 -05:00
Hayden
148aca5e85 New translations en-us.json (Hebrew) 2024-04-06 05:29:38 -05:00
Hayden
1ac7f90c28 New translations en-us.json (Finnish) 2024-04-06 05:29:37 -05:00
Hayden
413a8a82fc New translations en-us.json (Greek) 2024-04-06 05:29:36 -05:00
Hayden
72c414bf94 New translations en-us.json (German) 2024-04-06 05:29:35 -05:00
Hayden
b67263e63f New translations en-us.json (Danish) 2024-04-06 05:29:34 -05:00
Hayden
1673eedff7 New translations en-us.json (Czech) 2024-04-06 05:29:33 -05:00
Hayden
d3ee5f34f8 New translations en-us.json (Catalan) 2024-04-06 05:29:32 -05:00
Hayden
683f1ac69e New translations en-us.json (Bulgarian) 2024-04-06 05:29:31 -05:00
Hayden
d6d0f7de71 New translations en-us.json (Arabic) 2024-04-06 05:29:30 -05:00
Hayden
dd0eaac45f New translations en-us.json (Afrikaans) 2024-04-06 05:29:29 -05:00
Hayden
f8e672c7ac New translations en-us.json (French) 2024-04-06 05:29:28 -05:00
Hayden
2aa9d84d6c New translations en-us.json (Romanian) 2024-04-06 05:29:27 -05:00
Hayden
2c13c4760e New translations en-us.json (Polish) 2024-04-06 05:29:26 -05:00
Hayden
62bf733548 New translations en-us.json (English, United Kingdom) 2024-04-06 05:29:25 -05:00
Hayden
2c72ea17a2 New translations en-us.json (Swedish) 2024-04-06 05:29:24 -05:00
Hayden
06406c86f5 New translations en-us.json (Spanish) 2024-04-06 05:29:23 -05:00
boc-the-git
b7f7712011 fix: Update description for manage data page (#3427)
* Update description for manage data page

* Add some punctuation consistency.

* Capitalise item types

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>

---------

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
2024-04-05 22:04:32 +02:00
Hayden
4b13686261 New Crowdin updates (#3425)
* New translations en-us.json (Hungarian)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)
2024-04-05 10:05:13 +00:00
tba-code
9fade36014 feat: Support HEIF, HEIC and AVIF recipe image uploads (#3409)
* feat: Support HEIF, HEIC and AVIF recipe image uploads

* fix: lint import block

* fix: avif now included

* fix: lint import block
2024-04-04 18:31:10 -05:00
Carter
eb1d569e95 Infinite redirect fix again (#3419)
* override the check method to not care about the id token if we have a valid mealie token

* prevent auto log in with auth check is already good

* fix check

* simplify check logic
2024-04-04 21:23:33 +00:00
tba-code
1099e30a1d feat: Add OIDC_USER_CLAIM (#3422)
* feat: Add OIDC_USER_CLAIM

* fix: add validation
2024-04-04 21:16:54 +00:00
tba-code
fa9a2d64f7 fix: unstyled docs 404 page (#3421) 2024-04-04 18:56:27 +02:00
boc-the-git
de142c47df Merge pull request #3420 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-04-04 22:00:23 +11:00
Hayden
c990420a87 New translations en-us.json (Slovenian) 2024-04-04 04:58:11 -05:00
Hayden
d772e3bb4f New translations en-us.json (French, Canada) 2024-04-04 04:58:10 -05:00
Hayden
bb8080475c New translations en-us.json (Latvian) 2024-04-04 04:58:09 -05:00
Hayden
c1e05f57db New translations en-us.json (Croatian) 2024-04-04 04:58:08 -05:00
Hayden
9ad68542e0 New translations en-us.json (Portuguese, Brazilian) 2024-04-04 04:58:07 -05:00
Hayden
83997dbb47 New translations en-us.json (Icelandic) 2024-04-04 04:58:06 -05:00
Hayden
b5f3c5bef7 New translations en-us.json (Galician) 2024-04-04 04:58:04 -05:00
Hayden
ddd97cce10 New translations en-us.json (Vietnamese) 2024-04-04 04:58:03 -05:00
Hayden
0ecd57a50b New translations en-us.json (Chinese Traditional) 2024-04-04 04:58:02 -05:00
Hayden
e4efcee0df New translations en-us.json (Chinese Simplified) 2024-04-04 04:58:00 -05:00
Hayden
a6920f057e New translations en-us.json (Ukrainian) 2024-04-04 04:58:00 -05:00
Hayden
dbb212ceda New translations en-us.json (Turkish) 2024-04-04 04:57:59 -05:00
Hayden
5d5805459a New translations en-us.json (Serbian (Cyrillic)) 2024-04-04 04:57:58 -05:00
Hayden
3e68920e69 New translations en-us.json (Slovenian) 2024-04-04 04:57:57 -05:00
Hayden
91c978a309 New translations en-us.json (Slovak) 2024-04-04 04:57:56 -05:00
Hayden
e7c101c96b New translations en-us.json (Russian) 2024-04-04 04:57:55 -05:00
Hayden
004f3552c0 New translations en-us.json (Portuguese) 2024-04-04 04:57:54 -05:00
Hayden
cd56149371 New translations en-us.json (Norwegian) 2024-04-04 04:57:53 -05:00
Hayden
8edea0a7e0 New translations en-us.json (Dutch) 2024-04-04 04:57:52 -05:00
Hayden
df15e97026 New translations en-us.json (Lithuanian) 2024-04-04 04:57:51 -05:00
Hayden
760462e12f New translations en-us.json (Korean) 2024-04-04 04:57:50 -05:00
Hayden
60793bb560 New translations en-us.json (Japanese) 2024-04-04 04:57:49 -05:00
Hayden
7c84d3dea5 New translations en-us.json (Italian) 2024-04-04 04:57:47 -05:00
Hayden
eee1c5733d New translations en-us.json (Hungarian) 2024-04-04 04:57:46 -05:00
Hayden
cf0a7ae9c9 New translations en-us.json (Hebrew) 2024-04-04 04:57:45 -05:00
Hayden
be80d3e74c New translations en-us.json (Finnish) 2024-04-04 04:57:44 -05:00
Hayden
db1fabf5c8 New translations en-us.json (Greek) 2024-04-04 04:57:43 -05:00
Hayden
e7e73772e0 New translations en-us.json (German) 2024-04-04 04:57:42 -05:00
Hayden
e5cab0e4d0 New translations en-us.json (Danish) 2024-04-04 04:57:41 -05:00
Hayden
6a14d5b7db New translations en-us.json (Czech) 2024-04-04 04:57:40 -05:00
Hayden
57106c4cce New translations en-us.json (Catalan) 2024-04-04 04:57:38 -05:00
Hayden
61c6a991f3 New translations en-us.json (Bulgarian) 2024-04-04 04:57:37 -05:00
Hayden
6824b3c269 New translations en-us.json (Arabic) 2024-04-04 04:57:36 -05:00
Hayden
6b13166880 New translations en-us.json (Afrikaans) 2024-04-04 04:57:35 -05:00
Hayden
b2747d77e1 New translations en-us.json (French) 2024-04-04 04:57:34 -05:00
Hayden
fc4d1b88d0 New translations en-us.json (Romanian) 2024-04-04 04:57:32 -05:00
Hayden
8798bd6e55 New translations en-us.json (Polish) 2024-04-04 04:57:31 -05:00
Hayden
cef61ae29f New translations en-us.json (English, United Kingdom) 2024-04-04 04:57:30 -05:00
Hayden
e304d48e84 New translations en-us.json (Swedish) 2024-04-04 04:57:29 -05:00
Hayden
4f1a7c55b9 New translations en-us.json (Spanish) 2024-04-04 04:57:28 -05:00
boc-the-git
bae7acbc3b Merge pull request #3395 from tba-code/postgres-url-feature
feat: PostgresProvider - Add POSTGRES_URL_OVERRIDE
2024-04-04 13:18:45 +11:00
boc-the-git
c0cf6a9aca Merge branch 'mealie-next' into postgres-url-feature 2024-04-04 13:12:39 +11:00
Kuchenpirat
f4570faf1a cleanup: Add Organizers translation (#3415)
* Add Organizers translation

* 🧹
2024-04-03 15:07:20 -05:00
Tarek Al-Qarqaz
9548a7eb70 fix: removed period in POSTGRES_URL_OVERRIDE for consistency 2024-04-03 14:01:30 +00:00
Tarek Al-Qarqaz
d5e3a1dacb change: updated POSTGRES_URL_OVERRIDE description 2024-04-03 14:00:25 +00:00
tba-code
1ce760ec7e Merge branch 'mealie-recipes:mealie-next' into postgres-url-feature 2024-04-03 08:57:19 -05:00
github-actions[bot]
9e23ed1a07 docs(auto): Update image tag, for release v1.4.0 (#3411)
* Update image tag, for release v1.4.0

* Commit without changing anything.. to trigger workflows on PR 3411

---------

Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
2024-04-03 06:02:19 -05:00
Tarek Al-Qarqaz
b3885cc3f8 change: docs now use TZ variable over read only bind mount /etc/timezone 2024-04-02 16:38:19 +00:00
tba-code
5da990abd4 Merge branch 'mealie-recipes:mealie-next' into postgres-url-feature 2024-04-02 10:18:48 -05:00
Carter
f709d11952 fix: (OAuth) redirect to direct login on failure (#3406) 2024-04-02 15:13:30 +00:00
Hayden
2a3463b746 security: gh security recs (#3368)
* change ALLOW_SIGNUP to default to false

* add 1.4.0 tag for OIDC docs

* new notes on security inline with security/policy review

* safer transport for external requests

* fix linter errors

* docs: Tidy up wording/formatting

* fix request errors

* whoops

* fix implementation with std lib

* format

* Remove check on netloc_parts. It only includes URL after any @

---------

Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
Co-authored-by: Brendan <b.oconnell14@gmail.com>
2024-04-02 07:04:42 -08:00
Tarek Al-Qarqaz
cb7302d2d9 fix: added validation to POSTGRES_URL_OVERRIDE 2024-04-02 12:24:51 +00:00
Tarek Al-Qarqaz
a30084a199 change: POSTGRES_URL_OVERRIDE note wording in docs 2024-04-02 11:23:06 +00:00
tba-code
c0654a5d95 Merge branch 'mealie-recipes:mealie-next' into postgres-url-feature 2024-04-02 06:21:35 -05:00
boc-the-git
737a370874 Merge pull request #3408 from mealie-recipes/renovate/fastapi-0.x-lockfile
fix(deps): update dependency fastapi to v0.110.1
2024-04-02 22:01:13 +11:00
boc-the-git
2a2b6f312b Merge branch 'mealie-next' into renovate/fastapi-0.x-lockfile 2024-04-02 21:54:02 +11:00
boc-the-git
96d220acbd Merge pull request #3407 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
chore(deps): update dependency mkdocs-material to v9.5.17
2024-04-02 21:52:45 +11:00
renovate[bot]
b9a9b8695d fix(deps): update dependency fastapi to v0.110.1 2024-04-02 08:13:19 +00:00
renovate[bot]
e80c8a50e6 chore(deps): update dependency mkdocs-material to v9.5.17 2024-04-02 08:13:05 +00:00
renovate[bot]
41795799e6 chore(deps): update dependency ruff to v0.3.5 (#3405)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-01 20:52:36 +00:00
renovate[bot]
9980e49eef fix(deps): update dependency pillow to v10.3.0 (#3402)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-01 15:42:02 -05:00
tba-code
945810c47a Merge branch 'mealie-recipes:mealie-next' into postgres-url-feature 2024-04-01 06:32:17 -05:00
Kuchenpirat
a283828461 refactor: Sidebar UI (#3390)
* Refactor sidebar links in DefaultLayout.vue

* 🧹
2024-04-01 10:16:52 +02:00
Hayden
7c365b7c03 New translations en-us.json (German) (#3400) 2024-03-31 18:43:59 -08:00
renovate[bot]
16da55f58b chore(deps): update dependency mkdocs-material to v9.5.16 (#3397)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-31 18:02:16 -08:00
Tarek Al-Qarqaz
35f6b0e80e fix: POSTGRES_URL is now POSTGRES_URL_OVERRIDE 2024-03-31 04:49:41 +00:00
Tarek Al-Qarqaz
ab37c2e8c0 change: reverted BASE_URL value, removed notes, removed mention of POSTGRES_URL_OVERRIDE 2024-03-31 04:48:21 +00:00
Tarek Al-Qarqaz
d1f82df936 change: reverted BASE_URL value, removed note, removed incorrect lines 2024-03-31 04:47:15 +00:00
Tarek Al-Qarqaz
6c7cb7e795 change: rename POSTGRES_URL to POSTGRES_URL_OVERRIDE / no longer changes value 2024-03-31 04:42:38 +00:00
tba-code
ecf80b8e9c Merge branch 'mealie-recipes:mealie-next' into postgres-url-feature 2024-03-30 18:50:20 -05:00
boc-the-git
e280734e33 Merge pull request #3394 from mealie-recipes/renovate/apprise-1.x-lockfile
fix(deps): update dependency apprise to v1.7.5
2024-03-31 09:33:06 +11:00
Tarek Al-Qarqaz
24d8854723 fix: typo in db_providers.py 2024-03-30 20:55:00 +00:00
Tarek Al-Qarqaz
2f9b711973 revert: revert typo in docker tag. 2024-03-30 20:18:13 +00:00
Tarek Al-Qarqaz
2b09495e87 fix: update sqlite doc for consistency 2024-03-30 19:39:15 +00:00
Tarek Al-Qarqaz
ae5a1a9af2 feat: PostgresProvider - Add POSTGRES_URL override. 2024-03-30 19:38:23 +00:00
renovate[bot]
a312c4dbf3 fix(deps): update dependency apprise to v1.7.5 2024-03-30 16:50:07 +00:00
renovate[bot]
79fb1fb299 fix(deps): update dependency tzdata to v2024 (#3386)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-28 18:00:15 -05:00
boc-the-git
b7c1cdfd46 Merge pull request #3383 from mealie-recipes/renovate/orjson-3.x-lockfile
fix(deps): update dependency orjson to v3.10.0
2024-03-28 21:53:13 +11:00
renovate[bot]
09873d4814 fix(deps): update dependency orjson to v3.10.0 2024-03-28 01:13:59 +00:00
Hayden
7f596c653b New Crowdin updates (#3381)
* New translations en-us.json (Greek)

* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)

* New translations en-us.json (Greek)

* New translations en-us.json (Greek)

* New translations en-us.json (Japanese)

* New translations en-us.json (Japanese)

* New translations en-us.json (Japanese)

* New translations en-us.json (Japanese)
2024-03-27 17:36:23 +01:00
boc-the-git
bb06b0414b Housekeeping (#3380) 2024-03-27 10:40:13 +01:00
Hayden
6b720bafd6 New Crowdin updates (#3379)
* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)
2024-03-26 17:59:38 +01:00
Kuchenpirat
6449591143 feat: cookbook editor on cookbook page (#3378)
* remove unnecessairy string

* add edit functionality to cookbook page

* restrict to own group
2024-03-26 08:02:20 -05:00
Kuchenpirat
8fb43246b2 fix: add auto-select-first attribute to RecipeOrganizerSelector.vue (#3376) 2024-03-25 16:52:41 +00:00
Hayden
95d3fd4958 New Crowdin updates (#3377)
* New translations en-us.json (German)

* New translations en-us.json (Portuguese)
2024-03-25 16:38:04 +00:00
Michael Genson
dfbc890f2c fix: Recipe Search URL State (#3332)
* fix several state issues with explore page
- update state when there are no query params
- only call search if the query params actually changed
- wait until ready to call API

* store last search query in user prefs

* restore chip tag click to anonymous user
2024-03-25 16:04:42 +00:00
renovate[bot]
21886ab4b8 Update dependency rapidfuzz to v3.7.0 (#3370)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-25 14:56:10 +00:00
Kuchenpirat
4b0df3ace8 Reset the search input after selection on the RecipeOrganizerSelector (#3373)
* Reset the search input after selection on the RecipeOrganizerSelector

* remove unused import
2024-03-25 14:47:10 +00:00
renovate[bot]
7505b5cf65 Update dependency pre-commit to v3.7.0 (#3369)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-25 14:39:35 +00:00
renovate[bot]
45e71da402 Update dependency SQLAlchemy to v2.0.29 (#3362)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-25 09:30:02 -05:00
Hayden
3ded63dfdf New translations en-us.json (Bulgarian) (#3366) 2024-03-24 17:35:12 +01:00
boc-the-git
735c3e3146 Merge pull request #3358 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
Update dependency mkdocs-material to v9.5.15
2024-03-24 21:27:35 +11:00
boc-the-git
83861cfcb8 Merge branch 'mealie-next' into renovate/mkdocs-material-9.x-lockfile 2024-03-24 21:21:16 +11:00
boc-the-git
c22ff8ccad Merge pull request #3361 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-03-24 21:21:01 +11:00
Hayden
9a17a484f3 New translations en-us.json (Turkish) 2024-03-23 11:13:55 -05:00
renovate[bot]
bc6734399f Update dependency mkdocs-material to v9.5.15 2024-03-23 06:44:01 +00:00
boc-the-git
8e6f2a3d61 Merge pull request #3355 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-03-23 07:12:01 +11:00
Hayden
20fa3a25f2 New translations en-us.json (French, Canada) 2024-03-22 11:15:57 -05:00
Hayden
1a9f5470ca New translations en-us.json (Latvian) 2024-03-22 11:15:56 -05:00
Hayden
2254d114be New translations en-us.json (Croatian) 2024-03-22 11:15:55 -05:00
Hayden
ef22d29ef1 New translations en-us.json (Portuguese, Brazilian) 2024-03-22 11:15:54 -05:00
Hayden
ef165cd276 New translations en-us.json (Icelandic) 2024-03-22 11:15:53 -05:00
Hayden
e6477920ce New translations en-us.json (Galician) 2024-03-22 11:15:52 -05:00
Hayden
c49584d027 New translations en-us.json (Vietnamese) 2024-03-22 11:15:50 -05:00
Hayden
e56eabf1e2 New translations en-us.json (Chinese Traditional) 2024-03-22 11:15:49 -05:00
Hayden
a35f2ae56a New translations en-us.json (Chinese Simplified) 2024-03-22 11:15:49 -05:00
Hayden
2a4a195dcb New translations en-us.json (Ukrainian) 2024-03-22 11:15:48 -05:00
Hayden
6318e8d1c6 New translations en-us.json (Turkish) 2024-03-22 11:15:46 -05:00
Hayden
b7a4899302 New translations en-us.json (Serbian (Cyrillic)) 2024-03-22 11:15:46 -05:00
Hayden
7fe6ef4da5 New translations en-us.json (Slovenian) 2024-03-22 11:15:45 -05:00
Hayden
0391763d18 New translations en-us.json (Slovak) 2024-03-22 11:15:44 -05:00
Hayden
3250384862 New translations en-us.json (Russian) 2024-03-22 11:15:43 -05:00
Hayden
1bf496751c New translations en-us.json (Portuguese) 2024-03-22 11:15:42 -05:00
Hayden
580700458c New translations en-us.json (Norwegian) 2024-03-22 11:15:41 -05:00
Hayden
6c6276cb79 New translations en-us.json (Dutch) 2024-03-22 11:15:40 -05:00
Hayden
787f9293fb New translations en-us.json (Lithuanian) 2024-03-22 11:15:38 -05:00
Hayden
aa0547ae69 New translations en-us.json (Korean) 2024-03-22 11:15:37 -05:00
Hayden
1c6b0f1122 New translations en-us.json (Japanese) 2024-03-22 11:15:36 -05:00
Hayden
014721b6f7 New translations en-us.json (Italian) 2024-03-22 11:15:35 -05:00
Hayden
692d8a5681 New translations en-us.json (Hungarian) 2024-03-22 11:15:34 -05:00
Hayden
120d4cfc5a New translations en-us.json (Hebrew) 2024-03-22 11:15:33 -05:00
Hayden
e3b3f70621 New translations en-us.json (Finnish) 2024-03-22 11:15:32 -05:00
Hayden
c5e55a2207 New translations en-us.json (Greek) 2024-03-22 11:15:31 -05:00
Hayden
f6d508af92 New translations en-us.json (German) 2024-03-22 11:15:30 -05:00
Hayden
516a732b12 New translations en-us.json (Danish) 2024-03-22 11:15:28 -05:00
Hayden
dfd4943304 New translations en-us.json (Czech) 2024-03-22 11:15:27 -05:00
Hayden
511e08e7e9 New translations en-us.json (Catalan) 2024-03-22 11:15:26 -05:00
Hayden
ed50dfc145 New translations en-us.json (Bulgarian) 2024-03-22 11:15:25 -05:00
Hayden
ee542255a5 New translations en-us.json (Arabic) 2024-03-22 11:15:24 -05:00
Hayden
32fa9d4439 New translations en-us.json (Afrikaans) 2024-03-22 11:15:23 -05:00
Hayden
f2be3383ac New translations en-us.json (French) 2024-03-22 11:15:22 -05:00
Hayden
fd6874e8dd New translations en-us.json (Romanian) 2024-03-22 11:15:21 -05:00
Hayden
09e514fa84 New translations en-us.json (Polish) 2024-03-22 11:15:20 -05:00
Hayden
f4678f99ed New translations en-us.json (English, United Kingdom) 2024-03-22 11:15:19 -05:00
Hayden
4e9670acf6 New translations en-us.json (Swedish) 2024-03-22 11:15:18 -05:00
Hayden
fb097ca095 New translations en-us.json (Spanish) 2024-03-22 11:15:16 -05:00
boc-the-git
8f40d13f20 Merge pull request #3352 from michael-genson/feat/migrate-from-my-recipe-box
feat: Migrate from My Recipe Box
2024-03-22 20:40:01 +11:00
boc-the-git
2aaef9ae54 Merge branch 'mealie-next' into feat/migrate-from-my-recipe-box 2024-03-22 20:33:37 +11:00
boc-the-git
a6d31638e2 Merge pull request #3354 from cmintey/signing-algorithm-env-var
Add OIDC environment variable for specififying the signing algorithm
2024-03-22 20:21:59 +11:00
Carter Mintey
f73aefce4e lint 2024-03-22 01:46:45 +00:00
Carter Mintey
ff5131018b add new environment variable for specififying the signing algorithm 2024-03-22 01:32:33 +00:00
renovate[bot]
1c6c5042ae chore(deps): update dependency ruff to v0.3.4 (#3353)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-21 18:23:58 -05:00
Michael Genson
d770009e0d added reactive accepted file types 2024-03-21 16:21:37 +00:00
Michael Genson
4a0b211f27 added test 2024-03-21 16:17:01 +00:00
Michael Genson
7dcf2ca33d added migration to frontend and cleaned up migration page 2024-03-21 16:11:33 +00:00
Michael Genson
95c15504d0 fixed BaseOverflowButton divider 2024-03-21 16:11:18 +00:00
Michael Genson
4e38625bde added backend for myrecipebox migration 2024-03-21 16:11:06 +00:00
Hayden
4a411f0483 New Crowdin updates (#3351)
* New translations en-us.json (Danish)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Norwegian)
2024-03-21 15:59:50 +00:00
boc-the-git
95b6d901bf Merge pull request #3323 from cmintey/authelia-docs-update
OIDC Docs Updates
2024-03-21 08:08:36 +11:00
boc-the-git
c9d74e25ac Merge branch 'mealie-next' into authelia-docs-update 2024-03-21 08:01:58 +11:00
Hayden
54aef24caf New translations en-us.json (Danish) (#3347)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2024-03-20 15:44:33 +00:00
renovate[bot]
6050b1e25a fix(deps): update dependency uvicorn to ^0.29.0 (#3346)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 10:36:47 -05:00
boc-the-git
b54cef2702 Merge pull request #3328 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-03-20 20:53:22 +11:00
boc-the-git
abb2c8110c Merge branch 'mealie-next' into l10n_mealie-next 2024-03-20 20:47:13 +11:00
boc-the-git
f1e8d633fc Merge pull request #3321 from michael-genson/fix/repeated-calls-to-groups-self
fix: Repeated calls to group self
2024-03-20 20:44:55 +11:00
boc-the-git
c4f60942b5 Merge branch 'mealie-next' into l10n_mealie-next 2024-03-20 20:41:03 +11:00
boc-the-git
abbaf12e9e Merge branch 'mealie-next' into fix/repeated-calls-to-groups-self 2024-03-20 20:38:31 +11:00
renovate[bot]
04e6601d5b fix(deps): update dependency uvicorn to v0.28.1 (#3342)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-19 13:37:08 +00:00
renovate[bot]
1ebc7d27d4 chore(deps): update dependency pytest-asyncio to v0.23.6 (#3341)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-19 08:27:04 -05:00
Carter
59d53a02b3 Dicsussion Template: OAuth example template (#3340)
* Create oauth_example.yaml

* Update and rename oauth_example.yaml to oauth-provider-example.yaml
2024-03-19 01:21:53 +00:00
Carter Mintey
370da5aee3 update links 2024-03-19 01:06:45 +00:00
Ikko Eltociear Ashimine
af2992eee9 docs: Update maintainers.md (#3339)
reviered -> reviewed
2024-03-18 17:42:02 +00:00
Carter Mintey
e17b8b813c Remove examples from docs and link to GH discussions 2024-03-18 15:04:01 +00:00
renovate[bot]
9b4e0dd0d9 chore(deps): update dependency mkdocs-material to v9.5.14 (#3333)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-18 02:19:35 +00:00
Carter Mintey
d7bc1c75da add redirect uri required for idps with rp-initiated logout 2024-03-17 15:21:15 +00:00
Hayden
b963b99a4c New translations en-us.json (Japanese) 2024-03-17 05:46:58 -05:00
Carter Mintey
9270e22f19 clarify docs 2024-03-16 01:41:38 +00:00
Carter Mintey
7df34890d4 update authelia example config 2024-03-16 01:37:55 +00:00
renovate[bot]
36b0661e1d chore(deps): update dependency black to v24.3.0 (#3322)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-15 20:28:22 +00:00
Michael Genson
6da50b576f remove unused import 2024-03-15 20:21:43 +00:00
Michael Genson
517491e507 Merge branch 'mealie-next' into fix/repeated-calls-to-groups-self 2024-03-15 15:17:31 -05:00
renovate[bot]
82aca1f77f chore(deps): update dependency ruff to v0.3.3 (#3261)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-15 20:16:53 +00:00
Michael Genson
8c4f657aa7 Merge branch 'mealie-next' into fix/repeated-calls-to-groups-self 2024-03-15 15:02:46 -05:00
renovate[bot]
4352762e93 chore(deps): update dependency coverage to v7.4.4 (#3316)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-15 15:00:37 -05:00
Michael Genson
ad0ea09be9 better model inheritance 2024-03-15 19:57:57 +00:00
Michael Genson
52c6fe34b2 remove potentially sensitive fields from group self 2024-03-15 19:50:39 +00:00
Michael Genson
b6ccb9fbdb add shared group self to composable 2024-03-15 19:41:26 +00:00
Hayden
f83ab6ecc1 New Crowdin updates (#3319)
* New translations en-us.json (Japanese)

* New translations en-us.json (Slovak)

* New translations en-us.json (Slovak)
2024-03-15 16:15:41 +01:00
Hayden
1af0f426ae fix: remove deprecated lifecycle and consolidate startup actions (#3311)
* remove deprecated lifecycle and consolidate startup actions

* fix import
2024-03-14 19:27:26 +00:00
Michael Genson
d960947258 fix: Purge Group Exports type mismatch (#3314)
* cast string to datetime

* added test
2024-03-14 11:20:59 -08:00
Hayden
f2735ba22b proxy get_all to page_all (#3312) 2024-03-14 15:30:38 +00:00
Hayden
aa4c02ef30 New Crowdin updates (#3313)
* New translations en-us.json (Romanian)

* New translations en-us.json (Dutch)
2024-03-14 15:31:55 +01:00
Michael Genson
f1fbf0d120 fix: delete shopping list if no users are found (#3290) 2024-03-14 00:29:47 +00:00
Michael Genson
63a362a48a fix: Limit shopping list owners to current group (#3305)
* add route for getting group-only users

* add new api route to frontend

* update shopping list user getAll call

* tests

* fixed bad import

* replace UserOut with UserSummary

* fix params
2024-03-13 18:29:00 +00:00
Hayden
e0d7341139 New Crowdin updates (#3307)
* New translations en-us.json (Spanish)

* New translations en-us.json (Swedish)

* New translations en-us.json (English, United Kingdom)

* New translations en-us.json (Polish)

* New translations en-us.json (Romanian)

* New translations en-us.json (French)

* New translations en-us.json (Afrikaans)

* New translations en-us.json (Arabic)

* New translations en-us.json (Bulgarian)

* New translations en-us.json (Catalan)

* New translations en-us.json (Czech)

* New translations en-us.json (Danish)

* New translations en-us.json (German)

* New translations en-us.json (Greek)

* New translations en-us.json (Finnish)

* New translations en-us.json (Hebrew)

* New translations en-us.json (Hungarian)

* New translations en-us.json (Italian)

* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)

* New translations en-us.json (Lithuanian)

* New translations en-us.json (Dutch)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Russian)

* New translations en-us.json (Slovak)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Serbian (Cyrillic))

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)

* New translations en-us.json (Chinese Simplified)

* New translations en-us.json (Chinese Traditional)

* New translations en-us.json (Vietnamese)

* New translations en-us.json (Galician)

* New translations en-us.json (Icelandic)

* New translations en-us.json (Portuguese, Brazilian)

* New translations en-us.json (Croatian)

* New translations en-us.json (Latvian)

* New translations en-us.json (French, Canada)
2024-03-13 15:34:58 +01:00
Michael Genson
5f5b06683a fix: add locale and first day of week to all date pickers (#3303) 2024-03-12 22:46:34 +00:00
Michael Genson
42523bbfc9 fix: Only call store APIs once (#3306)
* move loading value to inside async function

* share loading state and use it for throttling
2024-03-12 14:36:30 -08:00
Michael Genson
0a344731c8 feat: Timeline Filters (#3284)
* added timeline event filters

* updated empty timeline text

* simplify icons/labels for event types

* added missing translations

* cloned sort improvements to explore page

* added filter indicator

* lint

* removed lint warning

* add top margin to "no events found" text

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>

* fixed reversed sort icons

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>

* fixed sort dir on timeline filter

* sync checkbox state with preferences state

---------

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
2024-03-12 15:20:48 +00:00
renovate[bot]
e83fa89ec4 fix(deps): update dependency pydantic to v2.6.4 (#3300)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-12 14:26:11 +00:00
Hayden
13cd7a1c0f New Crowdin updates (#3299)
* New translations en-us.json (French)

* New translations en-us.json (German)

* New translations en-us.json (Hungarian)

* New translations en-us.json (Dutch)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)

* New translations en-us.json (French, Canada)
2024-03-12 14:16:34 +00:00
Hayden
0e23a41bdb New Crowdin updates (#3286)
* New translations en-us.json (Spanish)

* New translations en-us.json (Swedish)

* New translations en-us.json (English, United Kingdom)

* New translations en-us.json (Polish)

* New translations en-us.json (Romanian)

* New translations en-us.json (French)

* New translations en-us.json (Afrikaans)

* New translations en-us.json (Arabic)

* New translations en-us.json (Bulgarian)

* New translations en-us.json (Catalan)

* New translations en-us.json (Czech)

* New translations en-us.json (Danish)

* New translations en-us.json (German)

* New translations en-us.json (Greek)

* New translations en-us.json (Finnish)

* New translations en-us.json (Hebrew)

* New translations en-us.json (Hungarian)

* New translations en-us.json (Italian)

* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)

* New translations en-us.json (Lithuanian)

* New translations en-us.json (Dutch)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Russian)

* New translations en-us.json (Slovak)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Serbian (Cyrillic))

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)

* New translations en-us.json (Chinese Simplified)

* New translations en-us.json (Chinese Traditional)

* New translations en-us.json (Vietnamese)

* New translations en-us.json (Galician)

* New translations en-us.json (Icelandic)

* New translations en-us.json (Portuguese, Brazilian)

* New translations en-us.json (Croatian)

* New translations en-us.json (Latvian)

* New translations en-us.json (French, Canada)
2024-03-11 14:13:19 +00:00
renovate[bot]
e17b320dc8 fix(deps): update dependency tzdata to v2024 (#3281)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 13:37:22 +00:00
Michael Genson
403038a5b2 feat: First Time Setup Wizard (#3204)
* extract user registration form into a composable

* added base wizard component

* added partial setup implementation

* removed unused attrs

* added setup bypass

* made setup page more readable

* add checkbox hints to autoform

* added common settings pages and initial submit logic

* bypass setup in demo

* add full name to user registration

* added fullname and pw handling to setup

* fixed wizard indentation

* added post-setup suggestions

* added tests for backend changes

* renamed Wizard to BaseWizard

* lint fixes

* pass hardcoded default password instead of backend nonsense

* removed old test

* fix e2e

* added setup skip to e2e testing for all admin users

---------

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
2024-03-11 13:28:54 +00:00
boc-the-git
430e1d7d4e Merge pull request #3283 from michael-genson/fix/recipe-favorite-slug-handling
fix: Allow UserOut to accept list of slugs for recipe favorites
2024-03-11 21:31:43 +11:00
boc-the-git
c44cd7ffab Merge branch 'mealie-next' into fix/recipe-favorite-slug-handling 2024-03-11 21:25:16 +11:00
boc-the-git
73dfb523ec Fix typos (#3285) 2024-03-11 09:08:32 +00:00
Michael Genson
21d57735c9 added failsafe for bad input data 2024-03-11 00:25:44 +00:00
Michael Genson
05e13e6078 account for slugs or recipes when constructing user favorites 2024-03-11 00:13:57 +00:00
Hayden
5f6844eceb feat: Login with OAuth via OpenID Connect (OIDC) (#3280)
* initial oidc implementation

* add dynamic scheme

* e2e test setup

* add caching

* fix

* try this

* add libldap-2.5 to runtime dependencies (#2849)

* New translations en-us.json (Norwegian) (#2851)

* New Crowdin updates (#2855)

* New translations en-us.json (Italian)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Portuguese)

* fix

* remove cache

* cache yarn deps

* cache docker image

* cleanup action

* lint

* fix tests

* remove not needed variables

* run code gen

* fix tests

* add docs

* move code into custom scheme

* remove unneeded type

* fix oidc admin

* add more tests

* add better spacing on login page

* create auth providers

* clean up testing stuff

* type fixes

* add OIDC auth method to postgres enum

* add option to bypass login screen and go directly to iDP

* remove check so we can fallback to another auth method oauth fails

* Add provider name to be shown at the login screen

* add new properties to admin about api

* fix spec

* add a prompt to change auth method when changing password

* Create new auth section. Add more info on auth methods

* update docs

* run ruff

* update docs

* format

* docs gen

* formatting

* initialize logger in class

* mypy type fixes

* docs gen

* add models to get proper fields in docs and fix serialization

* validate id token before using it

* only request a mealie token on initial callback

* remove unused method

* fix unit tests

* docs gen

* check for valid idToken before getting token

* add iss to mealie token

* check to see if we already have a mealie token before getting one

* fix lock file

* update authlib

* update lock file

* add remember me environment variable

* add user group setting to allow only certain groups to log in

---------

Co-authored-by: Carter Mintey <cmintey8@gmail.com>
Co-authored-by: Carter <35710697+cmintey@users.noreply.github.com>
2024-03-10 13:51:36 -05:00
github-actions[bot]
bea1a592d7 docs: Update image tag, for release v1.3.2 (#3279)
Co-authored-by: hay-kot <64056131+hay-kot@users.noreply.github.com>
2024-03-10 10:14:48 -08:00
Hayden
b54cdf6425 fix: sync locales in user registration validation (#3278)
* Add ability to inject into Python files

* Update outdated references to gen_global_components.py

* Add code gen for registration locale validation

* sort validators

* update for pydantic 2

* run generator again

---------

Co-authored-by: Gasper Gril <gasper@gril.si>
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2024-03-10 09:58:52 -08:00
Hayden
02da2114f9 New Crowdin updates (#3277)
* New translations en-us.json (Spanish)

* New translations en-us.json (Swedish)

* New translations en-us.json (English, United Kingdom)

* New translations en-us.json (Polish)

* New translations en-us.json (Romanian)

* New translations en-us.json (French)

* New translations en-us.json (Afrikaans)

* New translations en-us.json (Arabic)

* New translations en-us.json (Bulgarian)

* New translations en-us.json (Catalan)

* New translations en-us.json (Czech)

* New translations en-us.json (Danish)

* New translations en-us.json (German)

* New translations en-us.json (Greek)

* New translations en-us.json (Finnish)

* New translations en-us.json (Hebrew)

* New translations en-us.json (Hungarian)

* New translations en-us.json (Italian)

* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)

* New translations en-us.json (Lithuanian)

* New translations en-us.json (Dutch)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Russian)

* New translations en-us.json (Slovak)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Serbian (Cyrillic))

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)

* New translations en-us.json (Chinese Simplified)

* New translations en-us.json (Chinese Traditional)

* New translations en-us.json (Vietnamese)

* New translations en-us.json (Galician)

* New translations en-us.json (Icelandic)

* New translations en-us.json (Portuguese, Brazilian)

* New translations en-us.json (Croatian)

* New translations en-us.json (Latvian)

* New translations en-us.json (French, Canada)
2024-03-10 15:01:47 +01:00
boc-the-git
a67533a778 Merge pull request #3276 from mealie-recipes/renovate/apprise-1.x-lockfile
fix(deps): update dependency apprise to v1.7.4
2024-03-10 21:37:15 +11:00
renovate[bot]
59ad834c12 fix(deps): update dependency apprise to v1.7.4 2024-03-09 23:19:43 +00:00
Michael Genson
315d5b370e fix: bump ruff (#3275)
* bump ruff

* updated deprecated cli usage

* fixed deprecated pyproject layout

* fixed .format string

* fixed another deprecated setting
2024-03-09 18:40:08 +00:00
Michael Genson
130813ffe4 fix: Make Meal Planner Notes Not Clickable (#3274)
* selectively remove recipe card components when there is no recipe

* copied changes to regular card
2024-03-09 09:29:41 -09:00
renovate[bot]
65ddb7c9e2 chore(deps): update dependency pytest to v8.1.1 (#3244)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-09 11:55:16 -06:00
renovate[bot]
dbe29e15ae fix(deps): update dependency uvicorn to ^0.28.0 (#3273)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-09 16:36:18 +00:00
boc-the-git
980b3c634b Change "New" to "Add" (#3271) 2024-03-09 10:26:55 -06:00
renovate[bot]
457d8c93ce chore(deps): update dependency mypy to v1.9.0 (#3270)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-08 13:22:54 -06:00
Hayden
23aad6358c New Crowdin updates (#3269)
* New translations en-us.json (French)

* New translations en-us.json (Italian)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)
2024-03-08 14:05:19 +01:00
boc-the-git
7c896361f2 Merge pull request #3268 from mealie-recipes/docs/newrelease-update-version-v1.3.1
docs(auto): Update image tag, for release v1.3.1
2024-03-08 19:26:51 +11:00
boc-the-git
5b7f5738e3 Add a comment to kick PR3268 along, and for future reference 2024-03-08 19:20:31 +11:00
boc-the-git
5bfcb80c98 Update image tag, for release v1.3.1 2024-03-08 02:50:52 +00:00
Michael Genson
b1278b45e2 fix: Invalid Pydantic Definition On Group Model (#3264)
* fixed ambiguous pydantic definition

* removed unused import
2024-03-07 14:25:26 -09:00
Hayden
e7ae76ea48 New Crowdin updates (#3262)
* New translations en-us.json (Spanish)

* New translations en-us.json (Swedish)

* New translations en-us.json (English, United Kingdom)

* New translations en-us.json (Polish)

* New translations en-us.json (Romanian)

* New translations en-us.json (French)

* New translations en-us.json (Afrikaans)

* New translations en-us.json (Arabic)

* New translations en-us.json (Bulgarian)

* New translations en-us.json (Catalan)

* New translations en-us.json (Czech)

* New translations en-us.json (Danish)

* New translations en-us.json (German)

* New translations en-us.json (Greek)

* New translations en-us.json (Finnish)

* New translations en-us.json (Hebrew)

* New translations en-us.json (Hungarian)

* New translations en-us.json (Italian)

* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)

* New translations en-us.json (Lithuanian)

* New translations en-us.json (Dutch)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Russian)

* New translations en-us.json (Slovak)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Serbian (Cyrillic))

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)

* New translations en-us.json (Chinese Simplified)

* New translations en-us.json (Chinese Traditional)

* New translations en-us.json (Vietnamese)

* New translations en-us.json (Galician)

* New translations en-us.json (Icelandic)

* New translations en-us.json (Portuguese, Brazilian)

* New translations en-us.json (Croatian)

* New translations en-us.json (Latvian)

* New translations en-us.json (French, Canada)
2024-03-07 13:55:36 +01:00
boc-the-git
e84e5e2910 Merge pull request #3213 from michael-genson/feat/filter-shopping-lists
feat: Filter Out Shopping Lists That Aren't Yours
2024-03-07 09:27:04 +11:00
boc-the-git
5e6f5bc175 Merge branch 'mealie-next' into feat/filter-shopping-lists 2024-03-07 09:20:49 +11:00
Hayden
d577978f2f New Crowdin updates (#3258)
* New translations en-us.json (Italian)

* New translations en-us.json (Chinese Simplified)
2024-03-06 16:15:44 +01:00
Michael Genson
e30728e8e9 Merge branch 'mealie-next' into feat/filter-shopping-lists 2024-03-06 09:11:58 -06:00
Michael Genson
29368d9cc4 move showAll to user preferences 2024-03-06 15:11:43 +00:00
boc-the-git
4776da7aea Merge pull request #3257 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
chore(deps): update dependency mkdocs-material to v9.5.13
2024-03-06 18:52:58 +11:00
renovate[bot]
87518b1fbd chore(deps): update dependency mkdocs-material to v9.5.13 2024-03-06 07:39:41 +00:00
renovate[bot]
d7deb5a3f8 fix(deps): update dependency rapidfuzz to v3.6.2 (#3256)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-06 05:39:17 +00:00
boc-the-git
445ec18bb4 Merge pull request #3170 from michael-genson/fix/make-mealie-alpha-migrations-more-fault-tolerant
fix: Make Mealie Alpha Migrations More Fault Tolerant
2024-03-06 11:39:35 +11:00
boc-the-git
3ecc289e1a Merge branch 'mealie-next' into fix/make-mealie-alpha-migrations-more-fault-tolerant 2024-03-06 11:33:33 +11:00
boc-the-git
805e1c2d7d feat: Add shortcuts for PWA (#3255)
* Add PWA shortcuts, for Meal Planner and Shopping List

* Remove icons from shortcuts - they don't seem to work with nuxt

* Remove icon
2024-03-05 23:40:57 +00:00
boc-the-git
58286013c9 Merge pull request #3248 from mealie-recipes/renovate/sqlalchemy-2.x-lockfile
fix(deps): update dependency sqlalchemy to v2.0.28
2024-03-06 10:10:56 +11:00
renovate[bot]
1afdc400a8 fix(deps): update dependency sqlalchemy to v2.0.28 2024-03-05 22:59:54 +00:00
boc-the-git
f6d526741b Merge pull request #3196 from michael-genson/fix/bump-sqlalchemy
fix: Bump SQLAlchemy
2024-03-06 09:58:27 +11:00
boc-the-git
c9b21f862e Merge branch 'mealie-next' into fix/bump-sqlalchemy 2024-03-06 09:51:24 +11:00
renovate[bot]
4ae7f6eca4 fix(deps): update dependency apprise to v1.7.3 (#3246)
* fix(deps): update dependency apprise to v1.7.3

* Pin paho-mqtt to match what Apprise has done.

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Brendan <b.oconnell14@gmail.com>
2024-03-05 16:14:37 -06:00
Michael Genson
c9fdf862a3 Merge branch 'mealie-next' into feat/filter-shopping-lists 2024-03-05 09:18:37 -06:00
Michael Genson
cf97c2247c Merge branch 'mealie-next' into fix/make-mealie-alpha-migrations-more-fault-tolerant 2024-03-05 09:17:38 -06:00
Hayden
9c95c56f0a New Crowdin updates (#3251)
* New translations en-us.json (Swedish)

* New translations en-us.json (French)

* New translations en-us.json (Bulgarian)

* New translations en-us.json (Danish)

* New translations en-us.json (Bulgarian)
2024-03-05 15:23:30 +01:00
boc-the-git
9f3aca5a3f Merge pull request #3249 from eneiss/fix-doc-links
Fix broken docs links and nested Markdown list
2024-03-05 16:55:18 +11:00
boc-the-git
dd87779476 Merge branch 'mealie-next' into fix-doc-links 2024-03-05 16:49:06 +11:00
boc-the-git
2e7078e90b Merge pull request #3245 from michael-genson/fix/missing-name-in-timeline-event
fix: Missing Name in Timeline Event
2024-03-05 16:48:44 +11:00
boc-the-git
6b52b61604 Merge branch 'mealie-next' into fix/missing-name-in-timeline-event 2024-03-05 16:42:45 +11:00
eneiss
41e2643755 Fix broken docs links and nested Markdown list 2024-03-05 00:05:01 +00:00
Hayden
170b4d338d New Crowdin updates (#3247)
* New translations en-us.json (Spanish)

* New translations en-us.json (Swedish)

* New translations en-us.json (English, United Kingdom)

* New translations en-us.json (Polish)

* New translations en-us.json (Romanian)

* New translations en-us.json (French)

* New translations en-us.json (Afrikaans)

* New translations en-us.json (Arabic)

* New translations en-us.json (Bulgarian)

* New translations en-us.json (Catalan)

* New translations en-us.json (Czech)

* New translations en-us.json (Danish)

* New translations en-us.json (German)

* New translations en-us.json (Greek)

* New translations en-us.json (Finnish)

* New translations en-us.json (Hebrew)

* New translations en-us.json (Hungarian)

* New translations en-us.json (Italian)

* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)

* New translations en-us.json (Lithuanian)

* New translations en-us.json (Dutch)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Russian)

* New translations en-us.json (Slovak)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Serbian (Cyrillic))

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)

* New translations en-us.json (Chinese Simplified)

* New translations en-us.json (Chinese Traditional)

* New translations en-us.json (Vietnamese)

* New translations en-us.json (Galician)

* New translations en-us.json (Icelandic)

* New translations en-us.json (Portuguese, Brazilian)

* New translations en-us.json (Croatian)

* New translations en-us.json (Latvian)

* New translations en-us.json (French, Canada)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Portuguese)
2024-03-04 19:43:36 +01:00
Michael Genson
ecd506c714 Merge branch 'mealie-next' into fix/missing-name-in-timeline-event 2024-03-03 16:45:54 -06:00
boc-the-git
e6aadc4902 feat: Recipe Instructions, add buttons for move to top or bottom (#3232)
* Add 'move to top' and 'move to bottom' to recipe steps

* Add divider functionality
2024-03-03 22:41:29 +00:00
Michael Genson
ae74e0d71c moved subject calculation 2024-03-03 22:41:25 +00:00
Michael Genson
d6db8c23ce fixed broken translate string 2024-03-03 22:40:29 +00:00
renovate[bot]
dcf7afa441 fix(deps): update dependency recipe-scrapers to v14.55.0 (#3228)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-03 16:33:12 -06:00
boc-the-git
185c93100b Merge pull request #3243 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-03-03 22:00:22 +11:00
Hayden
cf68420976 New translations en-us.json (Portuguese) 2024-03-03 04:29:47 -06:00
boc-the-git
dea3b756f1 Merge pull request #3240 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-03-02 20:19:27 +11:00
Hayden
825b19c634 New translations en-us.json (Bulgarian) 2024-03-02 03:13:11 -06:00
Hayden
8d59c35bc9 New translations en-us.json (Bulgarian) 2024-03-02 03:13:11 -06:00
Hayden
06ec8dd4f3 New translations en-us.json (Bulgarian) 2024-03-02 03:13:10 -06:00
Hayden
fc4ec3261f New translations en-us.json (Romanian) 2024-03-02 03:13:09 -06:00
boc-the-git
663716ca0f Merge pull request #3239 from mealie-recipes/renovate/python-dateutil-2.x-lockfile
fix(deps): update dependency python-dateutil to v2.9.0
2024-03-01 20:19:08 +11:00
renovate[bot]
6c4ce585d6 fix(deps): update dependency python-dateutil to v2.9.0 2024-03-01 09:12:01 +00:00
boc-the-git
0acf30db61 Merge pull request #3238 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-03-01 20:09:40 +11:00
Hayden
db9035f92c New translations en-us.json (Catalan) 2024-03-01 03:03:31 -06:00
renovate[bot]
a475afd570 chore(deps): update dependency ruff to ^0.3.0 (#3237)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-29 12:07:03 -06:00
Hayden
57ca357969 New Crowdin updates (#3236)
* New translations en-us.json (Spanish)

* New translations en-us.json (Romanian)

* New translations en-us.json (French)

* New translations en-us.json (Afrikaans)

* New translations en-us.json (Arabic)

* New translations en-us.json (Bulgarian)

* New translations en-us.json (Catalan)

* New translations en-us.json (Czech)

* New translations en-us.json (Danish)

* New translations en-us.json (German)

* New translations en-us.json (Greek)

* New translations en-us.json (Finnish)

* New translations en-us.json (Hebrew)

* New translations en-us.json (Hungarian)

* New translations en-us.json (Italian)

* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)

* New translations en-us.json (Lithuanian)

* New translations en-us.json (Swedish)

* New translations en-us.json (English, United Kingdom)

* New translations en-us.json (Polish)

* New translations en-us.json (Dutch)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Russian)

* New translations en-us.json (Slovak)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Serbian (Cyrillic))

* New translations en-us.json (Ukrainian)

* New translations en-us.json (Chinese Simplified)

* New translations en-us.json (Chinese Traditional)

* New translations en-us.json (Vietnamese)

* New translations en-us.json (Galician)

* New translations en-us.json (Icelandic)

* New translations en-us.json (Portuguese, Brazilian)

* New translations en-us.json (Croatian)

* New translations en-us.json (Latvian)

* New translations en-us.json (French, Canada)
2024-02-29 10:22:19 +01:00
boc-the-git
cac099eeb3 Merge pull request #3235 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
chore(deps): update dependency mkdocs-material to v9.5.12
2024-02-29 17:49:04 +11:00
renovate[bot]
c0929634a9 chore(deps): update dependency mkdocs-material to v9.5.12 2024-02-29 04:17:26 +00:00
Olly Welch
52de8afe2d feat: sort by labels in shopping list copy if labels toggled (#3226)
* feat: sort by labels in shopping list copy if labels toggled

* fix: call parent validator in shopping list item out (#3227)

* fix: add a unit test for (#3227)

* fixed messy post_validate logic

* feat: label headings in shopping list copy

* feat: blank line for each group in shopping list copy

---------

Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2024-02-28 22:06:04 +00:00
boc-the-git
2809b87ab0 Merge pull request #3234 from mealie-recipes/renovate/rich-13.x-lockfile
chore(deps): update dependency rich to v13.7.1
2024-02-29 05:00:02 +11:00
renovate[bot]
7aab87813c chore(deps): update dependency rich to v13.7.1 2024-02-28 15:35:59 +00:00
Michael Genson
4a67fffccd Merge branch 'mealie-next' into fix/bump-sqlalchemy 2024-02-28 09:34:58 -06:00
boc-the-git
12b7625d42 Fix typo (#3233) 2024-02-28 09:34:39 -06:00
boc-the-git
275e1dc85c Merge pull request #3231 from mealie-recipes/renovate/pydantic-2.x-lockfile
fix(deps): update dependency pydantic to v2.6.3
2024-02-28 19:30:40 +11:00
renovate[bot]
3a8e814315 fix(deps): update dependency pydantic to v2.6.3 2024-02-28 08:23:39 +00:00
boc-the-git
07ebd1e613 Merge pull request #3230 from mealie-recipes/renovate/html2text-2024.x-lockfile
fix(deps): update dependency html2text to v2024.2.26
2024-02-28 19:21:24 +11:00
renovate[bot]
a626330139 fix(deps): update dependency html2text to v2024.2.26 2024-02-27 21:34:55 +00:00
renovate[bot]
5ac7645350 fix(deps): update dependency fastapi to ^0.110.0 (#3221)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-25 14:27:10 -06:00
renovate[bot]
efc6064605 chore(deps): update dependency pylint to v3.1.0 (#3223)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-25 13:59:50 -06:00
renovate[bot]
71a6f32665 fix(deps): update dependency html2text to v2024 (#3222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-25 10:21:15 -06:00
boc-the-git
d60c4c179b Merge pull request #3220 from mealie-recipes/renovate/pytest-8.x-lockfile
chore(deps): update dependency pytest to v8.0.2
2024-02-25 12:14:37 +11:00
renovate[bot]
c5c8c59168 chore(deps): update dependency pytest to v8.0.2 2024-02-25 00:22:41 +00:00
boc-the-git
fca75c5c07 Merge pull request #3217 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
chore(deps): update dependency mkdocs-material to v9.5.11
2024-02-24 21:27:30 +11:00
renovate[bot]
012142feec chore(deps): update dependency mkdocs-material to v9.5.11 2024-02-24 07:58:56 +00:00
Michael Genson
d532395d89 Merge branch 'mealie-next' into feat/filter-shopping-lists 2024-02-23 17:56:28 -06:00
Michael Genson
b25f9f2cdf Merge branch 'mealie-next' into fix/bump-sqlalchemy 2024-02-23 17:56:21 -06:00
Michael Genson
5471e742f0 Merge branch 'mealie-next' into fix/make-mealie-alpha-migrations-more-fault-tolerant 2024-02-23 17:56:18 -06:00
renovate[bot]
c5849b2a74 fix(deps): update dependency orjson to v3.9.15 (#3212)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-23 23:26:13 +00:00
renovate[bot]
429b2adf98 chore(deps): update dependency pylint to v3.0.4 (#3216)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-23 23:18:35 +00:00
renovate[bot]
df366cd82a chore(deps): update dependency coverage to v7.4.3 (#3215)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-23 23:10:37 +00:00
renovate[bot]
0a4bb583ff fix(deps): update dependency pydantic to v2.6.2 (#3211)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-23 16:58:15 -06:00
Michael Genson
dfb650c4b1 Merge remote-tracking branch 'upstream/mealie-next' into fix/bump-sqlalchemy 2024-02-23 19:33:01 +00:00
Michael Genson
aa4527e5f7 replace v-for/v-if with computed ref 2024-02-23 19:22:39 +00:00
Michael Genson
ae8ea16dab lint 2024-02-23 19:17:08 +00:00
Michael Genson
d321c69244 Merge branch 'mealie-next' into feat/filter-shopping-lists 2024-02-23 13:12:43 -06:00
Michael Genson
478a4e5d73 fixed showAll centering and added to recipe dialog 2024-02-23 19:11:28 +00:00
Michael Genson
44cd2fef1c fixed trailing quote 2024-02-23 18:58:47 +00:00
Michael Genson
0abe8b1921 fixed missing group_id filter 2024-02-23 18:12:06 +00:00
Michael Genson
4a13714177 updated tests to include userId 2024-02-23 18:09:35 +00:00
Michael Genson
ac3514f4c6 fixed broken migrations 2024-02-23 18:09:23 +00:00
Michael Genson
f9b71f4b4c translated owner string 2024-02-23 18:00:58 +00:00
Michael Genson
7ca50b63f9 moved settings under list contents 2024-02-23 18:00:13 +00:00
Michael Genson
62adc920a9 added settings to shopping list to change user 2024-02-23 17:54:50 +00:00
Hayden
eeda71e186 New Crowdin updates (#3210)
* New translations en-us.json (Polish)

* New translations en-us.json (Polish)
2024-02-23 18:16:17 +01:00
Michael Genson
8e5ea1df5e added "show all" toggle on list of shopping lists 2024-02-23 17:07:43 +00:00
Michael Genson
0bf3aed287 updated models/services/tests to include user_id 2024-02-23 17:02:32 +00:00
Michael Genson
74d6f58363 added user to shopping list 2024-02-23 16:49:37 +00:00
Michael Genson
3d4405cd42 order shopping lists alphabetically 2024-02-23 16:03:56 +00:00
Hayden
98c8694979 New translations en-us.json (Swedish) (#3208) 2024-02-22 18:22:35 +01:00
Hayden
32812d6a6c New Crowdin updates (#3206)
* New translations en-us.json (Swedish)

* New translations en-us.json (Swedish)

---------

Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2024-02-21 17:45:53 +00:00
renovate[bot]
1f8d7c0b21 fix(deps): update dependency httpx to ^0.27.0 (#3207)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-21 11:24:56 -06:00
boc-the-git
8b88f6892c Merge pull request #2914 from ekcom/fix/warn-on-edit-nav
fix: Warn on external navigation during editing
2024-02-21 21:02:23 +11:00
boc-the-git
618c567392 Merge branch 'mealie-next' into fix/warn-on-edit-nav 2024-02-21 20:51:50 +11:00
boc-the-git
fb44451c6f Merge pull request #3202 from mealie-recipes/renovate/coverage-7.x-lockfile
chore(deps): update dependency coverage to v7.4.2
2024-02-21 20:04:20 +11:00
renovate[bot]
9e1edbacb6 chore(deps): update dependency coverage to v7.4.2 2024-02-20 19:59:39 +00:00
Michael Genson
f45d02299a Merge branch 'mealie-next' into fix/make-mealie-alpha-migrations-more-fault-tolerant 2024-02-20 10:27:42 -06:00
Michael Genson
7afd7b2334 Merge branch 'mealie-next' into fix/bump-sqlalchemy 2024-02-20 10:25:22 -06:00
Michael Genson
0a28d36df9 remove redundant uselist indicators 2024-02-20 16:24:48 +00:00
renovate[bot]
2c1185e1d4 fix(deps): update dependency pydantic-settings to v2.2.1 (#3197)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-19 15:37:07 -06:00
boc-the-git
69bbf9fdcc Merge pull request #3195 from boc-the-git/feat/dont-build-nightly-for-docs
feat: Exclude paths from triggering nightly build
2024-02-20 06:25:48 +11:00
boc-the-git
38125fa362 Merge branch 'mealie-next' into feat/dont-build-nightly-for-docs 2024-02-20 06:19:32 +11:00
Michael Genson
5db7a735d7 Merge branch 'mealie-next' into fix/bump-sqlalchemy 2024-02-19 10:30:03 -06:00
Jurriaan Den Toonder
4d2363ea22 Add shopping list items using the enter key (#3118)
* Enables shopping list items being saved upon enter key press in notes field

Related to: https://github.com/mealie-recipes/mealie/discussions/3114
* Enter key press is caught in note field in ShoppingListItemEditor
* The create editor now stays open after saving a food item to a shopping list,
   to allow keyboard-only interaction with the shopping list

* Prevent empty shopping list items from being added

Related to: https://github.com/mealie-recipes/mealie/discussions/3114
An item is considered empty when the foodId is not set, and no note is set.
This is only handled frontend, the backend still accepts empty items.

---------

Signed-off-by: Jurriaan Den Toonder <1493561+Fastjur@users.noreply.github.com>
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2024-02-19 10:29:45 -06:00
Michael Genson
994940f270 more db model fixes 2024-02-19 16:05:50 +00:00
Michael Genson
3adb324b25 fixed more db model definitions 2024-02-19 15:47:14 +00:00
Michael Genson
fbfc5b31d6 fixed shopping list null handling 2024-02-19 15:43:59 +00:00
Michael Genson
2a016ecce9 fixed some model definitions 2024-02-19 15:43:30 +00:00
Michael Genson
782d4ec180 bump sqlalchemy 2024-02-19 15:17:40 +00:00
Brendan
8c52448da2 Exclude paths from triggering nightly build 2024-02-19 08:15:08 +00:00
boc-the-git
7e194887f5 Merge pull request #3194 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
chore(deps): update dependency mkdocs-material to v9.5.10
2024-02-19 18:50:12 +11:00
renovate[bot]
806a1b9392 chore(deps): update dependency mkdocs-material to v9.5.10 2024-02-19 06:49:26 +00:00
boc-the-git
d575a3b222 Merge pull request #3193 from mealie-recipes/renovate/pre-commit-3.x-lockfile
chore(deps): update dependency pre-commit to v3.6.2
2024-02-19 07:07:12 +11:00
renovate[bot]
f61fdb8623 chore(deps): update dependency pre-commit to v3.6.2 2024-02-18 20:00:20 +00:00
Michael Genson
ea7005e822 feat: Shopping List Editor Improvements (#3178)
* modify new item factory to default to zero qty and use last isFood value

* automatically set the label of an item when choosing a food

* fix when switching to a food with no label

* removed trivial type annotation

* more lint

* removed debug log
2024-02-19 06:59:03 +11:00
boc-the-git
a7775ea7ef Merge pull request #3100 from Kuchenpirat/feat-frontend-access-controll
feat: frontend access controll
2024-02-18 20:21:46 +11:00
boc-the-git
ba4eddccd9 Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-18 20:15:40 +11:00
boc-the-git
6fcda5e446 Merge pull request #3189 from michael-genson/fix/organizer-filters-broken
fix: Broken Recipe Organizer Filters
2024-02-18 19:30:06 +11:00
Michael Genson
34d742963a added tests 2024-02-18 06:48:09 +00:00
Michael Genson
59cd68d54a fixed UUID check 2024-02-18 06:47:21 +00:00
renovate[bot]
1e4dbe4e95 chore(deps): update dependency ruff to v0.2.2 (#3187)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-17 19:45:32 -06:00
renovate[bot]
5d89d53a4a chore(deps): update dependency pytest to v8 (#3060)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-17 11:34:00 -06:00
renovate[bot]
349ccbad6f fix(deps): update dependency pydantic-settings to v2.2.0 (#3182)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-17 11:11:10 -06:00
renovate[bot]
5d68620382 chore(deps): update dependency pytest-asyncio to v0.23.5 (#3136)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-17 10:55:06 -06:00
Hayden
cb06c8a877 New Crowdin updates (#3184)
* New translations en-us.json (Spanish)

* New translations en-us.json (Spanish)
2024-02-17 13:22:05 +01:00
boc-the-git
7d57fdcd96 Merge pull request #3149 from mealie-recipes/renovate/paho-mqtt-2.x
fix(deps): update dependency paho-mqtt to v2
2024-02-17 21:25:45 +11:00
renovate[bot]
fa60d81e26 fix(deps): update dependency paho-mqtt to v2 2024-02-17 02:43:03 +00:00
boc-the-git
6c4294dc49 chore: Only run docker build and discord notify on the main repo (not forks) (#3176) 2024-02-17 02:39:50 +00:00
Hayden
0a3542e97c New translations en-us.json (German) (#3179) 2024-02-16 13:05:46 +01:00
boc-the-git
83887e3c37 Set recipe rating (#3175) 2024-02-15 10:57:02 -06:00
boc-the-git
5fe29cdd93 Merge pull request #3133 from Kuchenpirat/chore-bump-nuxt-to-2.17.3
chore: bump nuxt version to 2.17.3
2024-02-14 21:06:58 +11:00
boc-the-git
f618c45767 Merge branch 'mealie-next' into chore-bump-nuxt-to-2.17.3 2024-02-14 20:58:48 +11:00
boc-the-git
e1a87b32d9 Merge pull request #3162 from Kuchenpirat/feat--dragable-items-in-ingredient-parser
feat: dragable items in ingredient parser
2024-02-14 20:57:57 +11:00
Kuchenpirat
9e739c8b35 Merge branch 'mealie-next' into feat--dragable-items-in-ingredient-parser 2024-02-14 10:50:40 +01:00
boc-the-git
d6fab197e7 Merge pull request #3153 from mealie-recipes/renovate/pre-commit-3.x-lockfile
chore(deps): update dependency pre-commit to v3.6.1
2024-02-14 20:49:20 +11:00
renovate[bot]
89a5326d3f chore(deps): update dependency pre-commit to v3.6.1 2024-02-14 09:42:35 +00:00
boc-the-git
f0b542c990 Merge pull request #3156 from mealie-recipes/renovate/uvicorn-0.x-lockfile
fix(deps): update dependency uvicorn to v0.27.1
2024-02-14 20:40:33 +11:00
renovate[bot]
c1a3516b37 fix(deps): update dependency uvicorn to v0.27.1 2024-02-14 09:26:56 +00:00
boc-the-git
db467105b9 Merge pull request #3174 from boc-the-git/fix/depot-connection-to-ghcr
fix: Remove permissions block, so it doesn't override what is inherited from parent workflow
2024-02-14 20:24:02 +11:00
boc-the-git
2b5372f693 Remove permissions block, so it doesn't override what is inherited from parent workflow 2024-02-14 19:58:21 +11:00
boc-the-git
1a2ff9540f Merge pull request #3172 from boc-the-git/feat/switch-docker-builds-to-depot
feat: Switch docker builds to Depot.dev
2024-02-14 19:39:07 +11:00
boc-the-git
28fdc8a9ac Merge branch 'mealie-next' into feat/switch-docker-builds-to-depot 2024-02-14 19:04:54 +11:00
renovate[bot]
b0ce1483fe fix(deps): update dependency orjson to v3.9.14 (#3173)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-13 23:34:04 -06:00
boc-the-git
ad251b2449 Merge branch 'mealie-next' into feat/switch-docker-builds-to-depot 2024-02-14 12:45:52 +11:00
Brendan
0ebc2a746b Add id-token=write permission, for Depot.dev connection 2024-02-14 01:19:12 +00:00
Michael Genson
9c6e3ebe5b fixed new var ref 2024-02-13 20:24:16 +00:00
Michael Genson
1b404ee6d8 Merge branch 'mealie-next' into fix/make-mealie-alpha-migrations-more-fault-tolerant 2024-02-13 14:01:07 -06:00
Michael Genson
72052be92f added test 2024-02-13 19:54:47 +00:00
Michael Genson
f2e7deb5cb added fault tolerance for malformed recipe json 2024-02-13 19:50:38 +00:00
Michael Genson
b2e0c51ead make sure report entries are actually saved 2024-02-13 19:46:12 +00:00
Litchi Pi
3d73e7498f feat: allow overriding of some absolute paths using environment variables (#3102)
* Allow overriding of alembic config file path using environment variable

Signed-off-by: Litchi Pi <litchi.pi@proton.me>

* Allow overriding of MODEL_PATH using environment variable

Signed-off-by: Litchi Pi <litchi.pi@proton.me>

---------

Signed-off-by: Litchi Pi <litchi.pi@proton.me>
2024-02-13 19:30:07 +00:00
Kuchenpirat
690f595491 Merge branch 'mealie-next' into chore-bump-nuxt-to-2.17.3 2024-02-13 18:44:26 +01:00
Kuchenpirat
058d968833 Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-13 18:44:01 +01:00
Kuchenpirat
da2adaa694 Merge branch 'mealie-next' into feat--dragable-items-in-ingredient-parser 2024-02-13 18:42:47 +01:00
Kuchenpirat
fb9be66f97 docs: fix webworker default and links (#3167) 2024-02-13 17:42:36 +00:00
Kuchenpirat
0a446928d7 Merge branch 'mealie-next' into feat--dragable-items-in-ingredient-parser 2024-02-13 18:42:35 +01:00
Kuchenpirat
dc01ff36dc add rendered list (#3169) 2024-02-13 11:28:25 -06:00
Brendan
2d90ae903b Add depot/setup-action 2024-02-13 10:46:35 +00:00
Brendan
d324c6ac57 Switch docker builds from running on GHA to Depot.dev. Tidy README. 2024-02-13 10:42:16 +00:00
Kuchenpirat
aebf229b86 Merge branch 'mealie-next' into feat--dragable-items-in-ingredient-parser 2024-02-13 11:30:48 +01:00
Hayden
3c76a82997 New translations en-us.json (Dutch) (#3166) 2024-02-13 10:26:16 +00:00
boc-the-git
30ec65f43c Merge pull request #3147 from Kuchenpirat/feat--send-reset-email-from-admin-dashboard
feat: email password reset link directly from admin dashboard
2024-02-13 20:57:01 +11:00
Kuchenpirat
2471c7b08e Fix wrong email config 2024-02-13 08:39:21 +00:00
Kuchenpirat
4be23ccffb 🧹 2024-02-13 08:23:13 +00:00
Kuchenpirat
99db24cdec Merge branch 'mealie-next' into feat--send-reset-email-from-admin-dashboard 2024-02-13 09:15:41 +01:00
renovate[bot]
719a33352a chore(deps): update dependency black to v24.2.0 (#3164)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-12 18:05:09 -06:00
boc-the-git
fe3bd95c85 Merge pull request #3163 from michael-genson/fix/url-encode-postgres-passwords
fix: URL-Encode Postgres Password
2024-02-13 08:50:43 +11:00
Michael Genson
8db08c21e5 removed try/catch 2024-02-12 16:58:03 +00:00
Michael Genson
a384e6716d added test 2024-02-12 16:40:17 +00:00
Michael Genson
e35b2e9fbf add fallback to urlencode the postgres password if it fails 2024-02-12 16:40:12 +00:00
Kuchenpirat
b48c2ab736 Merge branch 'mealie-next' into feat--dragable-items-in-ingredient-parser 2024-02-12 13:37:02 +01:00
Kuchenpirat
a12ee536d9 remove animation 2024-02-12 12:28:06 +00:00
Kuchenpirat
97d5439a4f add animation (bit buggy) 2024-02-12 11:42:36 +00:00
Kuchenpirat
c94a1d7c17 add ghost 2024-02-12 11:41:44 +00:00
Hayden
0ce05c781c New Crowdin updates (#3161)
* New translations en-us.json (Danish)

* New translations en-us.json (Hungarian)
2024-02-12 11:24:12 +01:00
Kuchenpirat
0e0dfbf014 Refactor ingredient-parser component to include draggable functionality 2024-02-12 09:59:19 +00:00
boc-the-git
ae03e61bb9 Merge pull request #3160 from michael-genson/fix/coerce-empty-string-to-none
fix: Pydantic Validation For Empty ID String
2024-02-12 19:36:21 +11:00
Michael Genson
f6167b1d81 add id validator for empty strings 2024-02-12 05:26:53 +00:00
Michael Genson
df75cb4034 fix: Pydantic Serialization Issues (#3157)
* replaced pydantic inits with validators

* fixed serialization dropping food and unit ids
2024-02-11 17:34:56 -06:00
boc-the-git
67313f8f03 Merge pull request #3155 from mealie-recipes/renovate/python-slugify-8.x-lockfile
fix(deps): update dependency python-slugify to v8.0.4
2024-02-12 06:37:58 +11:00
renovate[bot]
39eab01885 fix(deps): update dependency python-slugify to v8.0.4 2024-02-11 19:28:05 +00:00
boc-the-git
9fb63a00fd Merge pull request #3152 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
chore(deps): update dependency mkdocs-material to v9.5.9
2024-02-12 06:25:59 +11:00
renovate[bot]
f945cb8d2d chore(deps): update dependency mkdocs-material to v9.5.9 2024-02-11 16:49:36 +00:00
Michael Genson
7a107584c7 feat: Upgrade to Pydantic V2 (#3134)
* bumped pydantic
2024-02-11 16:47:37 +00:00
boc-the-git
248459671e Merge pull request #3148 from mealie-recipes/renovate/python-multipart-0.x
fix(deps): update dependency python-multipart to ^0.0.9
2024-02-11 22:20:24 +11:00
renovate[bot]
67e48c2fd1 fix(deps): update dependency python-multipart to ^0.0.9 2024-02-11 11:10:02 +00:00
boc-the-git
368d25fa01 Merge pull request #3150 from mealie-recipes/renovate/pre-commit-3.x-lockfile
chore(deps): update dependency pre-commit to v3.6.1
2024-02-11 22:09:09 +11:00
renovate[bot]
12b1d29413 chore(deps): update dependency pre-commit to v3.6.1 2024-02-11 11:02:18 +00:00
boc-the-git
dccc676b24 Merge pull request #3146 from mealie-recipes/renovate/uvicorn-0.x-lockfile
fix(deps): update dependency uvicorn to v0.27.1
2024-02-11 22:00:45 +11:00
Kuchenpirat
d9c1cf8bec Merge branch 'mealie-next' into feat--send-reset-email-from-admin-dashboard 2024-02-11 10:50:00 +01:00
renovate[bot]
0836c303d9 fix(deps): update dependency uvicorn to v0.27.1 2024-02-10 22:20:37 +00:00
boc-the-git
a43fd6b7fc fix: Change release workflow to create a PR, rather than commit directly to branch (#3143)
* fix: Change release workflow to create a PR, rather than commit directly to branch

* Slight wording tweak

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>

---------

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
2024-02-10 23:18:18 +01:00
boc-the-git
e7ee189fbb Merge pull request #3145 from mealie-recipes/fix-update-taskfile-email-config
fix: Taskfile Email Config
2024-02-11 06:30:45 +11:00
Kuchenpirat
b6708613b9 Merge branch 'mealie-next' into chore-bump-nuxt-to-2.17.3 2024-02-10 15:02:19 +01:00
Kuchenpirat
3317e061a8 add user reset email functionality 2024-02-10 12:51:38 +00:00
Kuchenpirat
0dc8584485 ↕️ 2024-02-10 13:30:02 +01:00
Kuchenpirat
673ad6d42b Update Taskfile.yml 2024-02-10 13:26:24 +01:00
Kuchenpirat
1450d6fc4c fix password reset link not shown (#3142) 2024-02-10 11:09:21 +00:00
boc-the-git
b082242439 Merge pull request #3139 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
chore(deps): update dependency mkdocs-material to v9.5.9
2024-02-10 21:40:53 +11:00
renovate[bot]
de69a3ca86 chore(deps): update dependency mkdocs-material to v9.5.9 2024-02-10 09:12:22 +00:00
boc-the-git
96e37b3ee1 Merge pull request #3140 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-02-10 20:10:38 +11:00
Hayden
cb2d8a9a50 New translations en-us.json (Russian) 2024-02-10 02:56:14 -06:00
Hayden
19c5b7c7ab New translations en-us.json (Ukrainian) 2024-02-10 02:56:13 -06:00
Hayden
38a4215b35 New translations en-us.json (Turkish) 2024-02-10 02:56:12 -06:00
Hayden
77a05c754e New translations en-us.json (Swedish) 2024-02-10 02:56:11 -06:00
Hayden
2226d7cbf9 New translations en-us.json (French) 2024-02-10 02:56:10 -06:00
boc-the-git
42a33cd993 fix: Give update-image-tags job write permissions to the repo, for auto doco updater (#3138) 2024-02-10 03:49:26 +00:00
boc-the-git
d73817adad Merge pull request #3137 from mealie-recipes/renovate/python-multipart-0.x
Update dependency python-multipart to ^0.0.8
2024-02-10 14:20:06 +11:00
renovate[bot]
ce58da8e18 Update dependency python-multipart to ^0.0.8 2024-02-10 01:08:10 +00:00
boc-the-git
fe89981e78 Merge pull request #3135 from Kuchenpirat/feat-add-docker-to-dev-container
dev: add docker-in-docker to dev container
2024-02-10 07:18:21 +11:00
Kuchenpirat
520bc7154a Remove old comments 2024-02-09 21:12:06 +01:00
Kuchenpirat
a38dfc094e update to use newer version of the feature 2024-02-09 17:52:41 +00:00
Kuchenpirat
0a81579da1 Merge branch 'mealie-next' into feat-add-docker-to-dev-container 2024-02-09 17:41:14 +01:00
Kuchenpirat
f4e77f6837 add docker in docker 2024-02-09 16:32:18 +00:00
Kuchenpirat
c1a2c7d485 remove not needed as string 2024-02-09 15:38:21 +00:00
Kuchenpirat
8127f48924 Merge branch 'mealie-next' into chore-bump-nuxt-to-2.17.3 2024-02-09 16:28:13 +01:00
Kuchenpirat
a0e7f85c32 fix lint 2024-02-09 15:27:46 +00:00
Kuchenpirat
b45ffd2046 fix vue-template-compiler version 2024-02-09 15:02:28 +00:00
renovate[bot]
1e04e9424f Update dependency python-slugify to v8.0.4 (#3131)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 05:54:04 -09:00
Kuchenpirat
ef4f6245d5 Merge branch 'mealie-next' into chore-bump-nuxt-to-2.17.3 2024-02-09 15:44:56 +01:00
Kuchenpirat
7bd1c8ef14 bump nuxt version 2024-02-09 14:20:44 +00:00
boc-the-git
d1bbfece9d Merge pull request #3132 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-02-09 20:00:38 +11:00
Hayden
94a85f9977 New translations en-us.json (French, Canada) 2024-02-09 02:54:34 -06:00
Hayden
3d0adda405 New translations en-us.json (English, United Kingdom) 2024-02-09 02:54:33 -06:00
Hayden
47086da6b6 New translations en-us.json (Latvian) 2024-02-09 02:54:32 -06:00
Hayden
9ce71c911f New translations en-us.json (Croatian) 2024-02-09 02:54:31 -06:00
Hayden
2244c3a8b5 New translations en-us.json (Portuguese, Brazilian) 2024-02-09 02:54:30 -06:00
Hayden
f0d0d0d463 New translations en-us.json (Icelandic) 2024-02-09 02:54:29 -06:00
Hayden
dbec3e58f9 New translations en-us.json (Galician) 2024-02-09 02:54:28 -06:00
Hayden
a5e56dc97f New translations en-us.json (Vietnamese) 2024-02-09 02:54:27 -06:00
Hayden
6d64418727 New translations en-us.json (Chinese Traditional) 2024-02-09 02:54:27 -06:00
Hayden
2b71174765 New translations en-us.json (Chinese Simplified) 2024-02-09 02:54:26 -06:00
Hayden
7f6de730a3 New translations en-us.json (Ukrainian) 2024-02-09 02:54:25 -06:00
Hayden
22cc19a085 New translations en-us.json (Turkish) 2024-02-09 02:54:24 -06:00
Hayden
b16fa49f16 New translations en-us.json (Swedish) 2024-02-09 02:54:23 -06:00
Hayden
90e373582b New translations en-us.json (Serbian (Cyrillic)) 2024-02-09 02:54:22 -06:00
Hayden
1b3cbb38ae New translations en-us.json (Slovenian) 2024-02-09 02:54:22 -06:00
Hayden
ac5a63e32d New translations en-us.json (Slovak) 2024-02-09 02:54:21 -06:00
Hayden
d5d86488a0 New translations en-us.json (Russian) 2024-02-09 02:54:20 -06:00
Hayden
3f9c46a763 New translations en-us.json (Portuguese) 2024-02-09 02:54:19 -06:00
Hayden
04176f6927 New translations en-us.json (Polish) 2024-02-09 02:54:18 -06:00
Hayden
2aa8c5810a New translations en-us.json (Norwegian) 2024-02-09 02:54:17 -06:00
Hayden
a071a7d16b New translations en-us.json (Dutch) 2024-02-09 02:54:16 -06:00
Hayden
a14c1b48c6 New translations en-us.json (Lithuanian) 2024-02-09 02:54:15 -06:00
Hayden
43174dcebe New translations en-us.json (Korean) 2024-02-09 02:54:13 -06:00
Hayden
3ee53977ec New translations en-us.json (Japanese) 2024-02-09 02:54:12 -06:00
Hayden
de1486c57f New translations en-us.json (Italian) 2024-02-09 02:54:12 -06:00
Hayden
a12aba6b9d New translations en-us.json (Hungarian) 2024-02-09 02:54:11 -06:00
Hayden
fb70bc76b3 New translations en-us.json (Hebrew) 2024-02-09 02:54:10 -06:00
Hayden
e6351273e2 New translations en-us.json (Finnish) 2024-02-09 02:54:09 -06:00
Hayden
82dcfb5635 New translations en-us.json (Greek) 2024-02-09 02:54:08 -06:00
Hayden
dddeed6359 New translations en-us.json (German) 2024-02-09 02:54:07 -06:00
Hayden
5f4a36bbd8 New translations en-us.json (Danish) 2024-02-09 02:54:06 -06:00
Hayden
f74610a0f7 New translations en-us.json (Czech) 2024-02-09 02:54:05 -06:00
Hayden
166f2486a2 New translations en-us.json (Catalan) 2024-02-09 02:54:04 -06:00
Hayden
88a5209237 New translations en-us.json (Bulgarian) 2024-02-09 02:54:03 -06:00
Hayden
d954869dd7 New translations en-us.json (Bulgarian) 2024-02-09 02:54:02 -06:00
Hayden
9cf181b415 New translations en-us.json (Arabic) 2024-02-09 02:54:01 -06:00
Hayden
5a7dc14a48 New translations en-us.json (Afrikaans) 2024-02-09 02:54:00 -06:00
Hayden
d916c0a472 New translations en-us.json (Spanish) 2024-02-09 02:54:00 -06:00
Hayden
a3693d83a3 New translations en-us.json (French) 2024-02-09 02:53:59 -06:00
Hayden
bb9620b67e New translations en-us.json (Romanian) 2024-02-09 02:53:58 -06:00
boc-the-git
3174216931 Merge pull request #2810 from michael-genson/fix/translation-issues-when-scraping
fix: Translate ISO 8601 Datetime Durations During Scraping/Parsing/Migrating
2024-02-09 06:37:28 +11:00
Michael Genson
94342081f9 I don't know why I changed this 2024-02-08 14:43:13 +00:00
boc-the-git
5d049d5696 Merge branch 'mealie-next' into fix/warn-on-edit-nav 2024-02-08 22:21:35 +11:00
boc-the-git
36088f0db9 Merge branch 'mealie-next' into fix/translation-issues-when-scraping 2024-02-08 20:58:43 +11:00
boc-the-git
4c60febb9c Merge pull request #3130 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-02-08 19:58:51 +11:00
Hayden
0283185913 New translations en-us.json (Hebrew) 2024-02-08 02:52:45 -06:00
Kuchenpirat
704d0a8392 Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-07 18:22:55 +01:00
Michael Genson
f42114e966 feat: Redirect Logged Out Users to Default Group, If It's Public (#2772)
* add default group slug to app info if public

* redirect public user to default group

* added tests

---------

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
2024-02-07 07:53:55 -09:00
Michael Genson
d4de15ba1e Merge branch 'mealie-next' into fix/translation-issues-when-scraping 2024-02-07 09:58:45 -06:00
RealFoxie
e686fa671c Better bruteforce parsing for units (#3066)
* try to match units when brute parsing and no amount is matched

* brute parser: better handle multiple word food items

Also checks the case when a food might have been split in a unit + ingredient

* fix formatting

* add test cases for ingredient parsing that don't start with an amount

* parametrized tests and added ingredient data fixture

* fixed group_id ref in tests

* fixed test inputs

* add extra tests for units as third token

---------

Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2024-02-07 09:16:20 -06:00
Kuchenpirat
12547feb4c Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-07 12:29:08 +01:00
Kuchenpirat
7dbc031725 update comments 2024-02-07 11:28:26 +00:00
renovate[bot]
597e6c8e0f chore(deps): update dependency mkdocs-material to v9.5.8 (#3124)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-07 04:38:04 +00:00
boc-the-git
d5ba69d828 Merge pull request #3123 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-02-07 12:12:02 +11:00
boc-the-git
564f43085b Merge branch 'mealie-next' into l10n_mealie-next 2024-02-07 12:05:57 +11:00
Hayden
a0b6cc3e62 New translations en-us.json (Turkish) 2024-02-06 17:52:01 -06:00
Hayden
c960c00cbe New translations en-us.json (Swedish) 2024-02-06 17:52:00 -06:00
Hayden
47b60e9ad5 New translations en-us.json (Hungarian) 2024-02-06 17:51:59 -06:00
renovate[bot]
026ca0364e chore(deps): update dependency ruff to v0.2.1 (#3122)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-06 09:12:30 -06:00
Elijah Mock
70ce34d6c9 Remove logging 2024-02-05 20:22:10 +00:00
Kuchenpirat
dff351a8eb Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-05 15:37:27 +01:00
Kuchenpirat
13e7dfe920 getAll if array is empty or non existant (#3120) 2024-02-05 07:37:15 -06:00
boc-the-git
abf4b7706f Merge branch 'mealie-next' into fix/warn-on-edit-nav 2024-02-05 22:30:35 +11:00
Kuchenpirat
813a124250 Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-05 11:47:14 +01:00
boc-the-git
8a3173094e Merge pull request #3111 from mealie-recipes/renovate/orjson-3.x-lockfile
fix(deps): update dependency orjson to v3.9.13
2024-02-05 20:53:34 +11:00
renovate[bot]
0d16a2a943 fix(deps): update dependency orjson to v3.9.13 2024-02-05 04:25:39 +00:00
Hayden
2918a824e4 New Crowdin updates (#3116)
* New translations en-us.json (Chinese Traditional)

* New translations en-us.json (Italian)

* New translations en-us.json (Romanian)

* New translations en-us.json (French)

* New translations en-us.json (Spanish)

* New translations en-us.json (Afrikaans)

* New translations en-us.json (Arabic)

* New translations en-us.json (Bulgarian)

* New translations en-us.json (Catalan)

* New translations en-us.json (Czech)

* New translations en-us.json (Danish)

* New translations en-us.json (German)

* New translations en-us.json (Greek)

* New translations en-us.json (Finnish)

* New translations en-us.json (Hebrew)

* New translations en-us.json (Hungarian)

* New translations en-us.json (Japanese)

* New translations en-us.json (Korean)

* New translations en-us.json (Lithuanian)

* New translations en-us.json (Dutch)

* New translations en-us.json (Norwegian)

* New translations en-us.json (Polish)

* New translations en-us.json (Portuguese)

* New translations en-us.json (Russian)

* New translations en-us.json (Slovak)

* New translations en-us.json (Slovenian)

* New translations en-us.json (Serbian (Cyrillic))

* New translations en-us.json (Swedish)

* New translations en-us.json (Turkish)

* New translations en-us.json (Ukrainian)

* New translations en-us.json (Chinese Simplified)

* New translations en-us.json (Vietnamese)

* New translations en-us.json (Galician)

* New translations en-us.json (Portuguese, Brazilian)

* New translations en-us.json (Croatian)

* New translations en-us.json (Latvian)

* New translations en-us.json (English, United Kingdom)

* New translations en-us.json (French, Canada)

* New translations en-us.json (Icelandic)

* New translations en-us.json (Dutch)
2024-02-04 22:24:02 -06:00
renovate[bot]
00e5e4384d fix(deps): update dependency fastapi to v0.109.2 (#3115)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-04 16:22:12 -06:00
Michael Genson
634b0590ed Merge branch 'mealie-next' into fix/translation-issues-when-scraping 2024-02-04 13:20:44 -06:00
Kuchenpirat
52c58e1dc0 feat: bulk deletion on "Manage Data" page (#3056)
* labels bulk delete

* add foods

* bulk delete units

* add categories

* add tags

* add tools

* update translations

* fix types for text

* fix reactivity for stores

---------

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
2024-02-04 12:55:14 -06:00
Kuchenpirat
67b7fb007b feat: Cookbook Create & Delete Improvements (#2902)
* add delete dialog

* put editor into component

* return data on createCookbook store action

* verry basic dialog with create & cancel functions

* 🧹

* cleanup

* add translation

* add dialog-closed to BaseDialog

* update delete dialog messaging

* use cancel instead of dialog-closed
2024-02-04 07:15:25 -09:00
Kuchenpirat
7299c9ec9a Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-04 10:35:23 +01:00
Hayden
292672601c New Crowdin updates (#3110)
* New translations en-us.json (Romanian)

* New translations en-us.json (Romanian)
2024-02-03 22:44:30 +00:00
boc-the-git
fa3bbdcde1 Merge pull request #3106 from mealie-recipes/renovate/python-multipart-0.x
fix(deps): update dependency python-multipart to ^0.0.7
2024-02-04 05:42:19 +11:00
renovate[bot]
7e519c6b5a fix(deps): update dependency python-multipart to ^0.0.7 2024-02-03 18:35:27 +00:00
boc-the-git
57c11b23c4 Merge pull request #3107 from mealie-recipes/renovate/fastapi-0.x-lockfile
fix(deps): update dependency fastapi to v0.109.1
2024-02-04 05:34:02 +11:00
renovate[bot]
ba60428b03 fix(deps): update dependency fastapi to v0.109.1 2024-02-03 13:07:43 +00:00
renovate[bot]
e48619bae6 chore(deps): update dependency mkdocs-material to v9.5.7 (#3105)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 14:05:27 +01:00
Kuchenpirat
3a0e4ff119 Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-03 10:18:24 +01:00
Hayden
6d38960a5a New translations en-us.json (Turkish) (#3103) 2024-02-03 00:31:30 +01:00
Kuchenpirat
9cc59e81d6 add comment to group-only 2024-02-02 16:41:42 +00:00
Kuchenpirat
a04b6983e7 Merge branch 'mealie-next' into feat-frontend-access-controll 2024-02-02 17:27:58 +01:00
Kuchenpirat
6beea06a41 show group settings option only to users that can manage the group 2024-02-02 16:17:38 +00:00
Kuchenpirat
e75b5f2f15 add shopping lists 2024-02-02 16:00:18 +00:00
Kuchenpirat
c9acc48bd6 add group reports 2024-02-02 15:56:26 +00:00
Kuchenpirat
f4df68a9e2 restrict access to /group pages 2024-02-02 15:36:10 +00:00
Kuchenpirat
4cee8ea879 add can manage restriction 2024-02-02 15:14:48 +00:00
Kuchenpirat
e7f5a4adff move middleware for manage data page to parrent component 2024-02-02 14:58:39 +00:00
Kuchenpirat
0301713214 add auth and group only to groupSlug pages 2024-02-02 14:45:30 +00:00
Kuchenpirat
5ef23e0330 add group-only middleware 2024-02-02 14:43:59 +00:00
renovate[bot]
9bf2e3fabd chore(deps): update dependency ruff to ^0.2.0 (#3097)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-01 18:17:42 -06:00
Hayden
dcf50b9a00 New translations en-us.json (Turkish) (#3096) 2024-02-01 22:46:14 +00:00
Joeri
073efd7a2f Rectify email message ID, change multipart order (#3094) 2024-02-01 13:59:21 +01:00
Kuchenpirat
88529457bf 🧹 2024-02-01 07:50:34 +00:00
Kuchenpirat
890b5d93a7 access controll coobook index page 2024-02-01 07:50:09 +00:00
renovate[bot]
95b7990f26 fix(deps): update dependency python-slugify to v8.0.3 (#3090)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-31 16:10:05 -06:00
Michael Genson
7947aa99ae fix: Migration Issue With Duplicate Labels (#3085)
* fixed eager queries

* test

---------

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
2024-01-31 13:37:12 -06:00
Kuchenpirat
c3f7ad8954 chore: delete unused file (#3089) 2024-01-31 10:10:59 -09:00
Kuchenpirat
7dafa6c7fe add access controll to user pages 2024-01-31 15:25:21 +00:00
Kuchenpirat
8d2d571683 add avanced-only 2024-01-31 11:56:15 +00:00
Kuchenpirat
19e776a772 manage-data pages 2024-01-31 10:33:05 +00:00
boc-the-git
8df7848c96 Merge pull request #3088 from mealie-recipes/chore-update-build-link-to-org
chore: update build link to org
2024-01-31 21:21:11 +11:00
Kuchenpirat
6097440781 Merge branch 'mealie-next' into chore-update-build-link-to-org 2024-01-31 10:51:56 +01:00
Kuchenpirat
208608b32e chore update build link to org 2024-01-31 09:49:58 +00:00
Hayden
02997cd36e New Crowdin updates (#3086)
* New translations en-us.json (Russian)

* New translations en-us.json (Slovenian)
2024-01-30 22:31:11 +00:00
Michael Genson
e1cd2717d3 fix: Update Group Slug When Updating Group (#3084)
* added slug update hook to group updates

* added test

* force refresh if group slug changes

* added alert if something goes wrong
2024-01-30 18:41:37 +00:00
renovate[bot]
694511cb60 chore(deps): update dependency ruff to v0.1.15 (#3076)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-30 14:39:30 +00:00
boc-the-git
f0c89525f6 Add paho-mqtt package, as needed by Apprise to send MQTT messages (#3078)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2024-01-30 14:31:24 +00:00
Kuchenpirat
a05ede5e05 fix recipeOrganizerPage edit dialog label localization (#3079) 2024-01-30 08:24:46 -06:00
boc-the-git
7e51cf0352 feat: On new release publish, update image tags in sample docker-compose files (#3072)
* WIP

* Add sed commands for image versions

---------

Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
2024-01-30 07:36:28 +00:00
boc-the-git
ce110c23e4 Merge pull request #3075 from mealie-recipes/l10n_mealie-next
New Crowdin updates
2024-01-30 12:49:44 +11:00
Hayden
8247f21101 New translations en-us.json (Slovenian) 2024-01-29 16:23:32 -06:00
Hayden
60f9a3be5c New translations en-us.json (Slovenian) 2024-01-29 16:23:31 -06:00
Hayden
dddcb644bf New translations en-us.json (Spanish) 2024-01-29 16:23:30 -06:00
boc-the-git
84e981fd03 Merge pull request #3058 from mealie-recipes/renovate/apprise-1.x-lockfile
fix(deps): update dependency apprise to v1.7.2
2024-01-29 22:21:35 +11:00
renovate[bot]
937464115e fix(deps): update dependency apprise to v1.7.2 2024-01-29 11:14:39 +00:00
boc-the-git
24aee11607 Merge pull request #3063 from mealie-recipes/renovate/mkdocs-material-9.x-lockfile
chore(deps): update dependency mkdocs-material to v9.5.6
2024-01-29 22:12:20 +11:00
renovate[bot]
023c57dd61 chore(deps): update dependency mkdocs-material to v9.5.6 2024-01-29 09:32:53 +00:00
renovate[bot]
14d8ff8754 fix(deps): update dependency recipe-scrapers to v14.54.0 (#3070)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-29 10:31:34 +01:00
Hayden
e6f531c111 New translations en-us.json (Hungarian) (#3071) 2024-01-28 16:21:47 -06:00
renovate[bot]
c0a4f624d1 chore(deps): update dependency pytest-asyncio to v0.23.4 (#3069)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-28 15:50:46 -06:00
boc-the-git
a32dc4baa0 docs: Update example docker-compose files (#3065)
* Update README.md

* Update version. Add note re where to find latest version.

* Update version. Add note re where to find latest version.
2024-01-28 10:43:55 +00:00
boc-the-git
7c4690a7a9 docs: Change org to mealie-recipes (#3064)
* Change org to mealie-recipes

* Change org to mealie-recipes

* Change org to mealie-recipes
2024-01-28 11:32:11 +01:00
boc-the-git
b44487596d Merge pull request #3062 from mealie-recipes/renovate/black-24.x-lockfile
chore(deps): update dependency black to v24.1.1
2024-01-28 19:38:22 +11:00
renovate[bot]
2cb4c21db3 chore(deps): update dependency black to v24.1.1 2024-01-28 08:31:34 +00:00
Hayden
2dcc765e86 New translations en-us.json (Hungarian) (#3059) 2024-01-27 21:41:33 +00:00
Michael Genson
a5ef18669b fix: Upgrade Black (#3057)
* bump black

* bump black on precommit

* run black

* fix backend test runner
2024-01-27 15:11:54 -06:00
Michael Genson
14497b9b5e Merge branch 'mealie-next' into fix/translation-issues-when-scraping 2024-01-10 11:35:28 -06:00
Elijah Mock
f77649abc8 Disarm on internal site navigation 2024-01-06 22:18:55 +00:00
Elijah Mock
33870dc845 Set up navigation warning while editing recipe 2024-01-06 21:52:56 +00:00
Elijah Mock
265313919c Vue-ify and add documentation 2024-01-06 21:51:35 +00:00
Elijah Mock
dd5d1b9cba Add helpers to activate and deactivate warning 2024-01-06 21:49:29 +00:00
Michael Genson
e90f05d2dc Merge branch 'mealie-next' into fix/translation-issues-when-scraping 2024-01-02 19:17:26 -06:00
Michael Genson
677dc8f36a Merge branch 'mealie-next' into fix/translation-issues-when-scraping 2023-12-14 17:43:11 -06:00
Michael Genson
449eeb0d53 Merge branch 'mealie-next' into fix/translation-issues-when-scraping 2023-12-11 13:01:26 -06:00
Michael Genson
41204ca7f9 Merge branch 'mealie-next' into fix/translation-issues-when-scraping 2023-12-09 16:38:21 -06:00
Michael Genson
437f5c454f fixed missing translator 2023-12-09 22:04:21 +00:00
Michael Genson
3a30b3216e fixed tests 2023-12-09 17:19:27 +00:00
Michael Genson
408df286fd added translator to scraper 2023-12-09 17:19:19 +00:00
Michael Genson
2cfc63b302 added timedelta translations 2023-12-09 17:19:06 +00:00
Michael Genson
a8583c8e69 added backend translation support for plurals 2023-12-09 17:12:07 +00:00
510 changed files with 16144 additions and 7226 deletions

View File

@@ -30,7 +30,6 @@
"dbaeumer.vscode-eslint",
"matangover.mypy",
"ms-python.black-formatter",
"ms-python.isort",
"ms-python.pylint",
"ms-python.python",
"ms-python.vscode-pylance",
@@ -42,6 +41,7 @@
"forwardPorts": [
3000,
9000,
9091, // used by docker production
24678 // used by nuxt when hot-reloading using polling
],
// Use 'onCreateCommand' to run commands at the end of container creation.
@@ -49,7 +49,9 @@
"onCreateCommand": "sudo chown -R vscode:vscode /workspaces/mealie/frontend/node_modules && task setup",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
// "features": {
// "git": "latest"
// }
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"dockerDashComposeVersion": "v2"
}
}
}

View File

@@ -11,7 +11,7 @@ body:
options:
- label: I used the GitHub search to find a similar requests and didn't find it.
required: true
- label: Checked the [tasks tagged](https://github.com/hay-kot/mealie/issues?q=is%3Aissue+is%3Aopen+label%3Atask+) issues and verified my feature is not covered
- label: Checked the [tasks tagged](https://github.com/mealie-recipes/mealie/issues?q=is%3Aissue+is%3Aopen+label%3Atask+) issues and verified my feature is not covered
required: true
- type: textarea
id: problem

View File

@@ -0,0 +1,9 @@
---
title: OAuth setup with <PROVIDER>
body:
- type: textarea
attributes:
label: Configuration Example
description: Add your example configuration. You can provide code blocks, screenshots, and links.
validations:
required: true

View File

@@ -1,7 +1,7 @@
---
name: v1.0.0b Task
name: Task
description: "CONTRIBUTORS ONLY: Submit a Task that needs to be completed"
title: "[v1.0.0b] [Task] - TASK DESCRIPTION"
title: "[Task] - TASK DESCRIPTION"
labels:
- task
- v1
@@ -11,17 +11,17 @@ body:
value: |
Thanks for your interest in Mealie! 🚀
This is a place for Mealie contributors to find tasks that need to get done around the repository. Tasks are different than issues as they are generally related to providing a new feature or improve an existing feature. They are _generally_ not related to an issue.
This is a place for Mealie contributors to find tasks that need to get done around the repository. Tasks are different than issues as they are generally related to providing a new feature or improving an existing feature. They are _generally_ not related to an issue.
**DO NOT** create a task unless
- You are a contributors who has prior approval via discord/discussions
- You are a contributor who has prior approval via discord/discussions
- You have otherwise been given approval to post the tasks
Otherwise, your post will be closed/deleted.
**Interested in Taking This?**
If you're interested in completing this tasks and it hasn't already been taken, comment below and to let others know you're working on it. As you work through the task, I ask that you submit a draft pull request as soon as possible, and tag this issue so we can all collaborate as best as possible.
If you're interested in completing this task and it hasn't already been taken, comment below and to let others know you're working on it. As you work through the task, I ask that you submit a draft pull request as soon as possible, and tag this issue so we can all collaborate as best as possible.
- type: textarea
id: problem
attributes:
@@ -33,6 +33,6 @@ body:
id: solution
attributes:
label: Proposed/Possible Solution(s)?
placeholder: Provide as much context around the idea as possible with potential files and roadblocks that may come up
placeholder: Provide as much context around the idea as possible with potential files and roadblocks that may come up.
validations:
required: true

46
.github/workflows/e2e.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: E2E Tests
on:
pull_request:
branches:
- mealie-next
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./tests/e2e
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'yarn'
cache-dependency-path: ./tests/e2e/yarn.lock
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Image
uses: docker/build-push-action@v5
with:
file: ./docker/Dockerfile
context: .
push: false
load: true
tags: mealie:e2e
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Deploy E2E Test Environment
run: docker compose up -d
working-directory: ./tests/e2e/docker
- name: Install dependencies
run: npm install -g yarn && yarn
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Check test environment
run: docker ps
- name: Run Playwright tests
run: yarn playwright test
- name: Destroy Test Environment
if: always()
run: docker compose down --volumes
working-directory: ./tests/e2e/docker

View File

@@ -4,6 +4,12 @@ on:
push:
branches:
- mealie-next
paths-ignore:
- '*.md'
- '.devcontainer/**'
# I'm not excluding .github as changes in there might be to workflows etc
- '.vscode/**'
- 'docs/**'
concurrency:
group: nightly-${{ github.ref }}
@@ -22,7 +28,13 @@ jobs:
permissions:
contents: read
packages: write
# The id-token write permission is needed to connect to Depot.dev
# as part of the partial-builder.yml action. It needs to be declared
# in the parent action, as noted here:
# https://github.com/orgs/community/discussions/76409#discussioncomment-8131390
id-token: write
name: Build Tagged Release
if: github.repository == 'mealie-recipes/mealie'
uses: ./.github/workflows/partial-builder.yml
needs:
- frontend-tests
@@ -35,6 +47,7 @@ jobs:
notify-discord:
name: Notify Discord
if: github.repository == 'mealie-recipes/mealie'
needs:
- build-release
runs-on: ubuntu-latest

View File

@@ -66,7 +66,7 @@ jobs:
id: cache-validate
if: steps.cached-poetry-dependencies.outputs.cache-hit == 'true'
run: |
echo "import black;print('venv good?')" > test.py && poetry run python test.py && echo "cache-hit-success=true" >> $GITHUB_OUTPUT
echo "import fastapi;print('venv good?')" > test.py && poetry run python test.py && echo "cache-hit-success=true" >> $GITHUB_OUTPUT
rm test.py
continue-on-error: true
@@ -75,12 +75,12 @@ jobs:
sudo apt-get update
sudo apt-get install libsasl2-dev libldap2-dev libssl-dev
poetry install
poetry add "psycopg2-binary==2.8.6"
poetry add "psycopg2-binary==2.9.9"
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' || steps.cache-validate.outputs.cache-hit-success != 'true'
- name: Formatting (Black)
- name: Formatting (Ruff)
run: |
poetry run black . --check
poetry run ruff format . --check
- name: Lint (Ruff)
run: |

View File

@@ -35,19 +35,16 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Override __init__.py
run: |
echo "__version__ = \"${{ inputs.tag }}\"" > ./mealie/__init__.py
- name: Build and push Docker image
uses: docker/build-push-action@v5
- uses: depot/setup-action@v1
- name: Build and push Docker image, via Depot.dev
uses: depot/build-push-action@v1
with:
project: srzjb6mhzm
file: ./docker/Dockerfile
context: .
platforms: linux/amd64,linux/arm64
@@ -58,6 +55,3 @@ jobs:
${{ inputs.tags }}
build-args: |
COMMIT=${{ github.sha }}
# https://docs.docker.com/build/ci/github-actions/cache/#github-cache
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@@ -17,6 +17,11 @@ jobs:
permissions:
contents: read
packages: write
# The id-token write permission is needed to connect to Depot.dev
# as part of the partial-builder.yml action. It needs to be declared
# in the parent action, as noted here:
# https://github.com/orgs/community/discussions/76409#discussioncomment-8131390
id-token: write
name: Build Tagged Release
uses: ./.github/workflows/partial-builder.yml
needs:
@@ -42,4 +47,34 @@ jobs:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
uses: Ilshidur/action-discord@0.3.2
with:
args: "🚀 Version {{ EVENT_PAYLOAD.release.tag_name }} of Mealie has been released. See the release notes https://github.com/hay-kot/mealie/releases/tag/{{ EVENT_PAYLOAD.release.tag_name }}"
args: "🚀 Version {{ EVENT_PAYLOAD.release.tag_name }} of Mealie has been released. See the release notes https://github.com/mealie-recipes/mealie/releases/tag/{{ EVENT_PAYLOAD.release.tag_name }}"
update-image-tags:
name: Update image tag in sample docker-compose files
needs:
- build-release
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout 🛎
uses: actions/checkout@v4
- name: Modify version strings
run: |
sed -i 's/:v[0-9]*.[0-9]*.[0-9]*/:${{ github.event.release.tag_name }}/' docs/docs/documentation/getting-started/installation/sqlite.md
sed -i 's/:v[0-9]*.[0-9]*.[0-9]*/:${{ github.event.release.tag_name }}/' docs/docs/documentation/getting-started/installation/postgres.md
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
# This doesn't currently work for us because it creates the PR but the workflows don't run.
# TODO: Provide a personal access token as a parameter here, that solves that problem.
# https://github.com/peter-evans/create-pull-request
with:
commit-message: "Update image tag, for release ${{ github.event.release.tag_name }}"
branch: "docs/newrelease-update-version-${{ github.event.release.tag_name }}"
delete-branch: true
base: mealie-next
title: "docs(auto): Update image tag, for release ${{ github.event.release.tag_name }}"
body: "Auto-generated by `.github/workflows/release.yml`, on publish of release ${{ github.event.release.tag_name }}"

View File

@@ -10,7 +10,8 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
exclude: ^tests/data/
- repo: https://github.com/psf/black
rev: 23.1.0
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.3.5
hooks:
- id: black
- id: ruff-format

View File

@@ -60,8 +60,5 @@
},
"[vue]": {
"editor.formatOnSave": false
},
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
},
}
}

10
.vscode/tasks.json vendored
View File

@@ -24,16 +24,6 @@
},
"problemMatcher": []
},
{
"label": "Init Database",
"command": "poetry run python mealie/db/init_db.py",
"type": "shell",
"presentation": {
"reveal": "always",
"group": "groupA"
},
"problemMatcher": []
},
{
"label": "Dev: Start Frontend",
"command": "task ui",

View File

@@ -71,12 +71,9 @@ Distributed under the AGPL License. See `LICENSE` for more information.
Huge thanks to all the sponsors of this project on [Github Sponsors](https://github.com/sponsors/hay-kot) and Buy Me a Coffee. Without you, this project would surely not be possible.
Thanks to Linode for providing Hosting for the Demo, Beta, and Documentation sites! Another big thanks to JetBrains for providing their IDEs for development.
Thanks to Depot for providing build instances for our Docker image builds.
<div align='center'>
<img height="100" src="docs/docs/assets/img/sponsors-linode.svg" />
<img height="100" src="docs/docs/assets/img/sponsors-jetbrains.png" />
</div>
[![Built with Depot](https://depot.dev/badges/built-with-depot.svg)](https://depot.dev?utm_source=Mealie)
@@ -91,7 +88,7 @@ Thanks to Linode for providing Hosting for the Demo, Beta, and Documentation sit
[stars-url]: https://github.com/mealie-recipes/mealie/stargazers
[issues-shield]: https://img.shields.io/github/issues/mealie-recipes/mealie.svg?style=flat-square
[issues-url]: https://github.com/mealie-recipes/mealie/issues
[latest-release-shield]: https://img.shields.io/github/v/release/mealie-recipes/mealie.svg?style=flat-square
[latest-release-shield]: https://img.shields.io/github/v/release/mealie-recipes/mealie?style=flat-square&label=latest%20release
[latest-release-url]: https://img.shields.io/github/v/release/mealie-recipes/mealie
[license-shield]: https://img.shields.io/github/license/mealie-recipes/mealie.svg?style=flat-square
[license-url]: https://github.com/mealie-recipes/mealie/blob/mealie-next/LICENSE

View File

@@ -14,7 +14,9 @@ env:
SMTP_HOST: localhost
SMTP_PORT: 1025
SMTP_FROM_NAME: MealieDev
SMTP_FROM_EMAIL: mealie@example.com
SMTP_AUTH_STRATEGY: NONE
BASE_URL: http://localhost:3000
LANG: en-US
# loads .env file if it exists
@@ -72,6 +74,7 @@ tasks:
desc: run code generators
cmds:
- poetry run python dev/code-generation/main.py
- task: py:format
dev:services:
desc: starts postgres and mailpit containers
@@ -103,12 +106,12 @@ tasks:
py:format:
desc: runs python code formatter
cmds:
- poetry run black mealie
- poetry run ruff format .
py:lint:
desc: runs python linter
cmds:
- poetry run ruff mealie
- poetry run ruff check mealie
py:check:
desc: runs all linters, type checkers, and formatters
@@ -130,7 +133,6 @@ tasks:
py:
desc: runs the backend server
cmds:
- poetry run python mealie/db/init_db.py
- poetry run python mealie/app.py
py:postgres:
@@ -143,9 +145,14 @@ tasks:
POSTGRES_PORT: 5432
POSTGRES_DB: mealie
cmds:
- poetry run python mealie/db/init_db.py
- poetry run python mealie/app.py
py:migrate:
desc: generates a new migration file e.g. task py:migrate:generate "add new column"
cmds:
- poetry run alembic revision --autogenerate -m "{{ .CLI_ARGS }}"
- task: py:format
ui:build:
desc: builds the frontend in frontend/dist
dir: frontend

View File

@@ -58,15 +58,3 @@ sqlalchemy.url =
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples
hooks = isort, black
# format using "isort" - use the console_scripts runner, against the "isort" entrypoint
isort.type = console_scripts
isort.entrypoint = isort
isort.options = REVISION_SCRIPT_FILENAME
# format using "black" - use the console_scripts runner, against the "black" entrypoint
black.type = console_scripts
black.entrypoint = black
black.options = REVISION_SCRIPT_FILENAME

View File

@@ -22,7 +22,11 @@ target_metadata = SqlAlchemyBase.metadata
# Set DB url from config
settings = get_app_settings()
config.set_main_option("sqlalchemy.url", settings.DB_URL)
if not settings.DB_URL:
raise Exception("DB URL not set in config")
config.set_main_option("sqlalchemy.url", settings.DB_URL.replace("%", "%%"))
def run_migrations_offline():

View File

@@ -1,10 +1,11 @@
"""Initial tables
Revision ID: 6b0f5f32d602
Revises:
Revises:
Create Date: 2022-02-21 19:56:24.351115
"""
import sqlalchemy as sa
from sqlalchemy import engine_from_config

View File

@@ -5,6 +5,7 @@ Revises: 6b0f5f32d602
Create Date: 2022-03-23 17:43:34.727829
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -5,6 +5,7 @@ Revises: 263dd6707191
Create Date: 2022-03-27 19:30:28.545846
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -5,6 +5,7 @@ Revises: f1a2dbee5fe9
Create Date: 2022-03-31 19:19:55.428965
"""
import sqlalchemy as sa
import mealie.db.migration_types

View File

@@ -5,6 +5,7 @@ Revises: 59eb59135381
Create Date: 2022-04-03 10:48:51.379968
"""
import sqlalchemy as sa
import mealie.db.migration_types # noqa: F401

View File

@@ -5,6 +5,7 @@ Revises: 09dfc897ad62
Create Date: 2022-06-01 11:12:06.748383
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -6,6 +6,7 @@ Revises: ab0bae02578f
Create Date: 2022-06-15 21:05:34.851857
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -5,6 +5,7 @@ Revises: f30cf048c228
Create Date: 2022-08-12 19:05:59.776361
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -5,6 +5,7 @@ Revises: 188374910655
Create Date: 2022-08-05 17:07:07.389271
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -5,6 +5,7 @@ Revises: 089bfa50d0ed
Create Date: 2022-08-29 13:57:40.452245
"""
import sqlalchemy as sa
import mealie.db.migration_types

View File

@@ -5,6 +5,7 @@ Revises: 44e8d670719d
Create Date: 2022-09-27 14:53:14.111054
"""
import sqlalchemy as sa
import mealie.db.migration_types

View File

@@ -5,6 +5,7 @@ Revises: 2ea7a807915c
Create Date: 2022-11-03 13:10:24.811134
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -5,6 +5,7 @@ Revises: 1923519381ad
Create Date: 2022-11-22 03:42:45.494567
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -5,6 +5,7 @@ Revises: 167eb69066ad
Create Date: 2023-01-21 16:54:44.368768
"""
import sqlalchemy as sa
import mealie.db.migration_types

View File

@@ -5,6 +5,7 @@ Revises: ff5f73b01a7a
Create Date: 2023-02-10 21:18:32.405130
"""
import sqlalchemy as sa
import mealie.db.migration_types

View File

@@ -5,6 +5,7 @@ Revises: 16160bf731a0
Create Date: 2023-02-14 20:45:41.102571
"""
import sqlalchemy as sa
from sqlalchemy import orm, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

View File

@@ -5,10 +5,11 @@ Revises: 5ab195a474eb
Create Date: 2023-21-02 22:03:19.837244
"""
from uuid import uuid4
import sqlalchemy as sa
from sqlalchemy.orm.session import Session
from sqlalchemy import orm
import mealie.db.migration_types
from alembic import op
@@ -22,8 +23,10 @@ branch_labels = None
depends_on = None
def populate_shopping_lists_multi_purpose_labels(shopping_lists_multi_purpose_labels_table: sa.Table, session: Session):
shopping_lists = session.query(ShoppingList).all()
def populate_shopping_lists_multi_purpose_labels(
shopping_lists_multi_purpose_labels_table: sa.Table, session: orm.Session
):
shopping_lists = session.query(ShoppingList).options(orm.load_only(ShoppingList.id, ShoppingList.group_id)).all()
shopping_lists_labels_data: list[dict] = []
for shopping_list in shopping_lists:
@@ -59,7 +62,7 @@ def upgrade():
)
# ### end Alembic commands ###
session = Session(bind=op.get_bind())
session = orm.Session(bind=op.get_bind())
populate_shopping_lists_multi_purpose_labels(shopping_lists_multi_purpose_labels_table, session)

View File

@@ -5,6 +5,7 @@ Revises: b04a08da2108
Create Date: 2023-02-22 21:45:52.900964
"""
import sqlalchemy as sa
import mealie.db.migration_types

View File

@@ -5,6 +5,7 @@ Revises: 38514b39a824
Create Date: 2023-04-13 06:47:04.617131
"""
import sqlalchemy as sa
import mealie.db.migration_types

View File

@@ -5,6 +5,7 @@ Revises: b3dbb554ba53
Create Date: 2023-08-06 21:00:34.582905
"""
import sqlalchemy as sa
from slugify import slugify
from sqlalchemy.orm import Session

View File

@@ -5,6 +5,7 @@ Revises: 04ac51cbe9a4
Create Date: 2023-08-14 19:30:49.103185
"""
import sqlalchemy as sa
from alembic import op

View File

@@ -5,6 +5,7 @@ Revises: 1825b5225403
Create Date: 2023-08-15 16:25:07.058929
"""
from alembic import op
# revision identifiers, used by Alembic.

View File

@@ -5,6 +5,7 @@ Revises: bcfdad6b7355
Create Date: 2023-09-01 14:55:42.166766
"""
import sqlalchemy as sa
from sqlalchemy import orm, select

View File

@@ -5,6 +5,7 @@ Revises: 0341b154f79a
Create Date: 2023-10-04 14:29:26.688065
"""
from collections import defaultdict
from dataclasses import dataclass
from typing import Any
@@ -58,7 +59,12 @@ def _resolve_duplicate_food(
keep_food_id: UUID4,
dupe_food_id: UUID4,
):
for shopping_list_item in session.query(ShoppingListItem).filter_by(food_id=dupe_food_id).all():
for shopping_list_item in (
session.query(ShoppingListItem)
.options(load_only(ShoppingListItem.id, ShoppingListItem.food_id))
.filter_by(food_id=dupe_food_id)
.all()
):
shopping_list_item.food_id = keep_food_id
for recipe_ingredient in (
@@ -81,10 +87,20 @@ def _resolve_duplicate_unit(
keep_unit_id: UUID4,
dupe_unit_id: UUID4,
):
for shopping_list_item in session.query(ShoppingListItem).filter_by(unit_id=dupe_unit_id).all():
for shopping_list_item in (
session.query(ShoppingListItem)
.options(load_only(ShoppingListItem.id, ShoppingListItem.unit_id))
.filter_by(unit_id=dupe_unit_id)
.all()
):
shopping_list_item.unit_id = keep_unit_id
for recipe_ingredient in session.query(RecipeIngredientModel).filter_by(unit_id=dupe_unit_id).all():
for recipe_ingredient in (
session.query(RecipeIngredientModel)
.options(load_only(RecipeIngredientModel.id, RecipeIngredientModel.unit_id))
.filter_by(unit_id=dupe_unit_id)
.all()
):
recipe_ingredient.unit_id = keep_unit_id
session.commit()
@@ -99,10 +115,20 @@ def _resolve_duplicate_label(
keep_label_id: UUID4,
dupe_label_id: UUID4,
):
for shopping_list_item in session.query(ShoppingListItem).filter_by(label_id=dupe_label_id).all():
for shopping_list_item in (
session.query(ShoppingListItem)
.options(load_only(ShoppingListItem.id, ShoppingListItem.label_id))
.filter_by(label_id=dupe_label_id)
.all()
):
shopping_list_item.label_id = keep_label_id
for ingredient_food in session.query(IngredientFoodModel).filter_by(label_id=dupe_label_id).all():
for ingredient_food in (
session.query(IngredientFoodModel)
.options(load_only(IngredientFoodModel.id, IngredientFoodModel.label_id))
.filter_by(label_id=dupe_label_id)
.all()
):
ingredient_food.label_id = keep_label_id
session.commit()

View File

@@ -5,6 +5,7 @@ Revises: dded3119c1fe
Create Date: 2023-10-19 19:22:55.369319
"""
import sqlalchemy as sa
import mealie.db.migration_types

View File

@@ -0,0 +1,101 @@
"""added user to shopping list
Revision ID: 2298bb460ffd
Revises: ba1e4a6cfe99
Create Date: 2024-02-23 16:15:07.115641
"""
from uuid import UUID
import sqlalchemy as sa
from sqlalchemy import orm
import mealie.db.migration_types
from alembic import op
from mealie.core.root_logger import get_logger
logger = get_logger()
# revision identifiers, used by Alembic.
revision = "2298bb460ffd"
down_revision = "ba1e4a6cfe99"
branch_labels = None
depends_on = None
def is_postgres():
return op.get_context().dialect.name == "postgresql"
def find_user_id_for_group(group_id: UUID):
bind = op.get_bind()
session = orm.Session(bind=bind)
if is_postgres():
stmt = "SELECT id FROM users WHERE group_id=:group_id AND admin = TRUE LIMIT 1"
else:
stmt = "SELECT id FROM users WHERE group_id=:group_id AND admin = 1 LIMIT 1"
with session:
try:
# try to find an admin user
return session.execute(sa.text(stmt).bindparams(group_id=group_id)).scalar_one()
except orm.exc.NoResultFound:
pass
try:
# fallback to any user
return session.execute(
sa.text("SELECT id FROM users WHERE group_id=:group_id LIMIT 1").bindparams(group_id=group_id)
).scalar_one()
except orm.exc.NoResultFound:
pass
# no user could be found
return None
def populate_shopping_list_users():
bind = op.get_bind()
session = orm.Session(bind=bind)
with session:
list_ids_and_group_ids = session.execute(sa.text("SELECT id, group_id FROM shopping_lists")).all()
for list_id, group_id in list_ids_and_group_ids:
user_id = find_user_id_for_group(group_id)
if user_id:
session.execute(
sa.text(f"UPDATE shopping_lists SET user_id=:user_id WHERE id=:id").bindparams(
user_id=user_id, id=list_id
)
)
else:
logger.warning(
f"No user found for shopping list {list_id} with group {group_id}; deleting shopping list"
)
session.execute(sa.text(f"DELETE FROM shopping_lists WHERE id=:id").bindparams(id=list_id))
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("shopping_lists") as batch_op:
# allow nulls during migration
batch_op.add_column(sa.Column("user_id", mealie.db.migration_types.GUID(), nullable=True))
batch_op.create_index(op.f("ix_shopping_lists_user_id"), ["user_id"], unique=False)
batch_op.create_foreign_key("fk_user_shopping_lists", "users", ["user_id"], ["id"])
# ### end Alembic commands ###
populate_shopping_list_users()
# forbid nulls after migration
with op.batch_alter_table("shopping_lists") as batch_op:
batch_op.alter_column("user_id", nullable=False)
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, "shopping_lists", type_="foreignkey")
op.drop_index(op.f("ix_shopping_lists_user_id"), table_name="shopping_lists")
op.drop_column("shopping_lists", "user_id")
# ### end Alembic commands ###

View File

@@ -0,0 +1,31 @@
"""add OIDC auth method
Revision ID: 09aba125b57a
Revises: 2298bb460ffd
Create Date: 2024-03-10 05:08:32.397027
"""
import sqlalchemy as sa
import mealie.db.migration_types
from alembic import op
# revision identifiers, used by Alembic.
revision = "09aba125b57a"
down_revision = "2298bb460ffd"
branch_labels = None
depends_on = None
def is_postgres():
return op.get_context().dialect.name == "postgresql"
def upgrade():
if is_postgres():
op.execute("ALTER TYPE authmethod ADD VALUE 'OIDC'")
def downgrade():
pass

View File

@@ -0,0 +1,229 @@
"""migrate favorites and ratings to user_ratings
Revision ID: d7c6efd2de42
Revises: 09aba125b57a
Create Date: 2024-03-18 02:28:15.896959
"""
from datetime import datetime
from textwrap import dedent
from typing import Any
from uuid import uuid4
import sqlalchemy as sa
from sqlalchemy import orm
import mealie.db.migration_types
from alembic import op
# revision identifiers, used by Alembic.
revision = "d7c6efd2de42"
down_revision = "09aba125b57a"
branch_labels = None
depends_on = None
def is_postgres():
return op.get_context().dialect.name == "postgresql"
def new_user_rating(user_id: Any, recipe_id: Any, rating: float | None = None, is_favorite: bool = False):
if is_postgres():
id = str(uuid4())
else:
id = "%.32x" % uuid4().int
now = datetime.now().isoformat()
return {
"id": id,
"user_id": user_id,
"recipe_id": recipe_id,
"rating": rating,
"is_favorite": is_favorite,
"created_at": now,
"update_at": now,
}
def migrate_user_favorites_to_user_ratings():
bind = op.get_bind()
session = orm.Session(bind=bind)
with session:
user_ids_and_recipe_ids = session.execute(sa.text("SELECT user_id, recipe_id FROM users_to_favorites")).all()
rows = [
new_user_rating(user_id, recipe_id, is_favorite=True)
for user_id, recipe_id in user_ids_and_recipe_ids
if user_id and recipe_id
]
if is_postgres():
query = dedent(
"""
INSERT INTO users_to_recipes (id, user_id, recipe_id, rating, is_favorite, created_at, update_at)
VALUES (:id, :user_id, :recipe_id, :rating, :is_favorite, :created_at, :update_at)
ON CONFLICT DO NOTHING
"""
)
else:
query = dedent(
"""
INSERT OR IGNORE INTO users_to_recipes
(id, user_id, recipe_id, rating, is_favorite, created_at, update_at)
VALUES (:id, :user_id, :recipe_id, :rating, :is_favorite, :created_at, :update_at)
"""
)
for row in rows:
session.execute(sa.text(query), row)
def migrate_group_to_user_ratings(group_id: Any):
bind = op.get_bind()
session = orm.Session(bind=bind)
with session:
user_ids = (
session.execute(sa.text("SELECT id FROM users WHERE group_id=:group_id").bindparams(group_id=group_id))
.scalars()
.all()
)
recipe_ids_ratings = session.execute(
sa.text(
"SELECT id, rating FROM recipes WHERE group_id=:group_id AND rating > 0 AND rating IS NOT NULL"
).bindparams(group_id=group_id)
).all()
# Convert recipe ratings to user ratings. Since we don't know who
# rated the recipe initially, we copy the rating to all users.
rows: list[dict] = []
for recipe_id, rating in recipe_ids_ratings:
for user_id in user_ids:
rows.append(new_user_rating(user_id, recipe_id, rating, is_favorite=False))
if is_postgres():
insert_query = dedent(
"""
INSERT INTO users_to_recipes (id, user_id, recipe_id, rating, is_favorite, created_at, update_at)
VALUES (:id, :user_id, :recipe_id, :rating, :is_favorite, :created_at, :update_at)
ON CONFLICT (user_id, recipe_id) DO NOTHING;
"""
)
else:
insert_query = dedent(
"""
INSERT OR IGNORE INTO users_to_recipes
(id, user_id, recipe_id, rating, is_favorite, created_at, update_at)
VALUES (:id, :user_id, :recipe_id, :rating, :is_favorite, :created_at, :update_at);
"""
)
update_query = dedent(
"""
UPDATE users_to_recipes
SET rating = :rating, update_at = :update_at
WHERE user_id = :user_id AND recipe_id = :recipe_id;
"""
)
# Create new user ratings with is_favorite set to False
for row in rows:
session.execute(sa.text(insert_query), row)
# Update existing user ratings with the correct rating
for row in rows:
session.execute(sa.text(update_query), row)
def migrate_to_user_ratings():
migrate_user_favorites_to_user_ratings()
bind = op.get_bind()
session = orm.Session(bind=bind)
with session:
group_ids = session.execute(sa.text("SELECT id FROM groups")).scalars().all()
for group_id in group_ids:
migrate_group_to_user_ratings(group_id)
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"users_to_recipes",
sa.Column("user_id", mealie.db.migration_types.GUID(), nullable=False),
sa.Column("recipe_id", mealie.db.migration_types.GUID(), nullable=False),
sa.Column("rating", sa.Float(), nullable=True),
sa.Column("is_favorite", sa.Boolean(), nullable=False),
sa.Column("id", mealie.db.migration_types.GUID(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("update_at", sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(
["recipe_id"],
["recipes.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.PrimaryKeyConstraint("user_id", "recipe_id", "id"),
sa.UniqueConstraint("user_id", "recipe_id", name="user_id_recipe_id_rating_key"),
)
op.create_index(op.f("ix_users_to_recipes_created_at"), "users_to_recipes", ["created_at"], unique=False)
op.create_index(op.f("ix_users_to_recipes_is_favorite"), "users_to_recipes", ["is_favorite"], unique=False)
op.create_index(op.f("ix_users_to_recipes_rating"), "users_to_recipes", ["rating"], unique=False)
op.create_index(op.f("ix_users_to_recipes_recipe_id"), "users_to_recipes", ["recipe_id"], unique=False)
op.create_index(op.f("ix_users_to_recipes_user_id"), "users_to_recipes", ["user_id"], unique=False)
migrate_to_user_ratings()
if is_postgres():
op.drop_index("ix_users_to_favorites_recipe_id", table_name="users_to_favorites")
op.drop_index("ix_users_to_favorites_user_id", table_name="users_to_favorites")
op.alter_column("recipes", "rating", existing_type=sa.INTEGER(), type_=sa.Float(), existing_nullable=True)
else:
op.execute("DROP INDEX IF EXISTS ix_users_to_favorites_recipe_id")
op.execute("DROP INDEX IF EXISTS ix_users_to_favorites_user_id")
with op.batch_alter_table("recipes") as batch_op:
batch_op.alter_column("rating", existing_type=sa.INTEGER(), type_=sa.Float(), existing_nullable=True)
op.drop_table("users_to_favorites")
op.create_index(op.f("ix_recipes_rating"), "recipes", ["rating"], unique=False)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column(
"recipes_ingredients", "quantity", existing_type=sa.Float(), type_=sa.INTEGER(), existing_nullable=True
)
op.drop_index(op.f("ix_recipes_rating"), table_name="recipes")
op.alter_column("recipes", "rating", existing_type=sa.Float(), type_=sa.INTEGER(), existing_nullable=True)
op.create_unique_constraint("ingredient_units_name_group_id_key", "ingredient_units", ["name", "group_id"])
op.create_unique_constraint("ingredient_foods_name_group_id_key", "ingredient_foods", ["name", "group_id"])
op.create_table(
"users_to_favorites",
sa.Column("user_id", sa.CHAR(length=32), nullable=True),
sa.Column("recipe_id", sa.CHAR(length=32), nullable=True),
sa.ForeignKeyConstraint(
["recipe_id"],
["recipes.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["users.id"],
),
sa.UniqueConstraint("user_id", "recipe_id", name="user_id_recipe_id_key"),
)
op.create_index("ix_users_to_favorites_user_id", "users_to_favorites", ["user_id"], unique=False)
op.create_index("ix_users_to_favorites_recipe_id", "users_to_favorites", ["recipe_id"], unique=False)
op.drop_index(op.f("ix_users_to_recipes_user_id"), table_name="users_to_recipes")
op.drop_index(op.f("ix_users_to_recipes_recipe_id"), table_name="users_to_recipes")
op.drop_index(op.f("ix_users_to_recipes_rating"), table_name="users_to_recipes")
op.drop_index(op.f("ix_users_to_recipes_is_favorite"), table_name="users_to_recipes")
op.drop_index(op.f("ix_users_to_recipes_created_at"), table_name="users_to_recipes")
op.drop_table("users_to_recipes")
# ### end Alembic commands ###

View File

@@ -3,8 +3,8 @@ from pathlib import Path
from fastapi import FastAPI
from jinja2 import Template
from pydantic import BaseModel
from utils import PROJECT_DIR, CodeTemplates, HTTPRequest, RouteObject
from pydantic import BaseModel, ConfigDict
from utils import PROJECT_DIR, CodeTemplates, HTTPRequest, RouteObject, RequestType
CWD = Path(__file__).parent
@@ -12,23 +12,25 @@ OUTFILE = PROJECT_DIR / "tests" / "utils" / "api_routes" / "__init__.py"
class PathObject(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
route_object: RouteObject
http_verbs: list[HTTPRequest]
class Config:
arbitrary_types_allowed = True
def get_path_objects(app: FastAPI):
paths = []
for key, value in app.openapi().items():
if key == "paths":
for key, value in value.items():
for key, value2 in value.items():
verbs = []
for k, v in value2.items():
verbs.append(HTTPRequest(request_type=k, **v))
paths.append(
PathObject(
route_object=RouteObject(key),
http_verbs=[HTTPRequest(request_type=k, **v) for k, v in value.items()],
http_verbs=verbs,
)
)

View File

@@ -5,7 +5,7 @@ from pathlib import Path
import dotenv
import requests
from jinja2 import Template
from pydantic import Extra
from pydantic import ConfigDict
from requests import Response
from utils import CodeDest, CodeKeys, inject_inline, log
@@ -56,7 +56,7 @@ LOCALE_DATA: dict[str, LocaleData] = {
"zh-TW": LocaleData(name="繁體中文 (Chinese traditional)"),
}
LOCALE_TEMPLATE = """// This Code is auto generated by gen_global_components.py
LOCALE_TEMPLATE = """// This Code is auto generated by gen_ts_locales.py
export const LOCALES = [{% for locale in locales %}
{
name: "{{ locale.name }}",
@@ -70,6 +70,8 @@ export const LOCALES = [{% for locale in locales %}
class TargetLanguage(MealieModel):
model_config = ConfigDict(populate_by_name=True, extra="allow")
id: str
name: str
locale: str
@@ -78,10 +80,6 @@ class TargetLanguage(MealieModel):
twoLettersCode: str
progress: float = 0.0
class Config:
extra = Extra.allow
allow_population_by_field_name = True
class CrowdinApi:
project_name = "Mealie"
@@ -152,6 +150,7 @@ PROJECT_DIR = Path(__file__).parent.parent.parent
datetime_dir = PROJECT_DIR / "frontend" / "lang" / "dateTimeFormats"
locales_dir = PROJECT_DIR / "frontend" / "lang" / "messages"
nuxt_config = PROJECT_DIR / "frontend" / "nuxt.config.js"
reg_valid = PROJECT_DIR / "mealie" / "schema" / "_mealie" / "validators.py"
"""
This snippet walks the message and dat locales directories and generates the import information
@@ -175,6 +174,19 @@ def inject_nuxt_values():
inject_inline(nuxt_config, CodeKeys.nuxt_local_dates, all_date_locales)
def inject_registration_validation_values():
all_langs = []
for match in locales_dir.glob("*.json"):
lang_string = f'"{match.stem}",'
all_langs.append(lang_string)
# sort
all_langs.sort()
log.debug(f"injecting locales into user registration validation -> {reg_valid}")
inject_inline(reg_valid, CodeKeys.nuxt_local_messages, all_langs)
def generate_locales_ts_file():
api = CrowdinApi("")
models = api.get_languages()
@@ -193,6 +205,7 @@ def main():
generate_locales_ts_file()
inject_nuxt_values()
inject_registration_validation_values()
if __name__ == "__main__":

View File

@@ -6,7 +6,7 @@ from utils import log
# ============================================================
template = """// This Code is auto generated by gen_global_components.py
template = """// This Code is auto generated by gen_ts_types.py
{% for name in global %}import {{ name }} from "@/components/global/{{ name }}.vue";
{% endfor %}{% for name in layout %}import {{ name }} from "@/components/layout/{{ name }}.vue";
{% endfor %}

View File

@@ -1,9 +1,8 @@
import re
from enum import Enum
from typing import Optional
from humps import camelize
from pydantic import BaseModel, Extra, Field
from pydantic import BaseModel, ConfigDict, Field
from slugify import slugify
@@ -34,33 +33,30 @@ class ParameterIn(str, Enum):
class RouterParameter(BaseModel):
model_config = ConfigDict(extra="allow")
required: bool = False
name: str
location: ParameterIn = Field(..., alias="in")
class Config:
extra = Extra.allow
class RequestBody(BaseModel):
required: bool = False
model_config = ConfigDict(extra="allow")
class Config:
extra = Extra.allow
required: bool = False
class HTTPRequest(BaseModel):
model_config = ConfigDict(extra="allow", populate_by_name=True)
request_type: RequestType
description: str = ""
summary: str
requestBody: Optional[RequestBody]
request_body: RequestBody | None = None
parameters: list[RouterParameter] = []
tags: list[str] | None = []
class Config:
extra = Extra.allow
def list_as_js_object_string(self, parameters, braces=True):
if len(parameters) == 0:
return ""
@@ -71,11 +67,11 @@ class HTTPRequest(BaseModel):
return ", ".join(parameters)
def payload(self):
return "payload" if self.requestBody else ""
return "payload" if self.request_body else ""
def function_args(self):
all_params = [p.name for p in self.parameters]
if self.requestBody:
if self.request_body:
all_params.append("payload")
return self.list_as_js_object_string(all_params)

View File

@@ -3,8 +3,6 @@ import re
from dataclasses import dataclass
from pathlib import Path
import black
import isort
from jinja2 import Template
from rich.logging import RichHandler
@@ -23,10 +21,7 @@ def render_python_template(template_file: Path | str, dest: Path, data: dict):
text = tplt.render(data=data)
text = black.format_str(text, mode=black.FileMode())
dest.write_text(text)
isort.file(dest)
@dataclass
@@ -50,7 +45,7 @@ class CodeSlicer:
self._next_line += 1
def get_indentation_of_string(line: str, comment_char: str = "//") -> str:
def get_indentation_of_string(line: str, comment_char: str = "//|#") -> str:
return re.sub(rf"{comment_char}.*", "", line).removesuffix("\n")

View File

@@ -14,6 +14,7 @@ services:
- 9091:9000
environment:
ALLOW_SIGNUP: "false"
LOG_LEVEL: "DEBUG"
DB_ENGINE: sqlite # Optional: 'sqlite', 'postgres'
# =====================================

View File

@@ -33,9 +33,6 @@ init() {
# Activate our virtual environment here
. /opt/pysetup/.venv/bin/activate
# Initialize Database Prerun
poetry run python /app/mealie/db/init_db.py
}
change_user
@@ -43,10 +40,11 @@ init
GUNICORN_PORT=${API_PORT:-9000}
# Start API
hostip=`/sbin/ip route|awk '/default/ { print $3 }'`
HOST_IP=`/sbin/ip route|awk '/default/ { print $3 }'`
if [ "$WEB_GUNICORN" = 'true' ]; then
echo "Starting Gunicorn"
exec gunicorn mealie.app:app -b 0.0.0.0:$GUNICORN_PORT --forwarded-allow-ips=$hostip -k uvicorn.workers.UvicornWorker -c /app/gunicorn_conf.py --preload
exec gunicorn mealie.app:app -b 0.0.0.0:$GUNICORN_PORT --forwarded-allow-ips=$HOST_IP -k uvicorn.workers.UvicornWorker -c /app/gunicorn_conf.py --preload
else
exec uvicorn mealie.app:app --host 0.0.0.0 --forwarded-allow-ips=$hostip --port $GUNICORN_PORT
exec python /app/mealie/main.py
fi

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 230 90" width="2500" height="978"><path d="M93.8 27.8l5.8-1.4v28c0 3.1.9 4.9 2.7 5.5-.9 1.7-2.4 2.6-4.6 2.6-2.6 0-4-1.8-4-5.5V27.8zM108.4 62V41.8h-3.2V37h9.1v25h-5.9zm3-34.6c.9 0 1.7.3 2.4 1s1 1.5 1 2.4c0 .9-.3 1.7-1 2.4s-1.5 1-2.4 1c-.9 0-1.7-.3-2.4-1s-1-1.5-1-2.4c0-.9.3-1.7 1-2.4s1.5-1 2.4-1zM137.1 62V47.6c0-2.1-.4-3.7-1.2-4.6-.8-1-2.1-1.5-4-1.5-.9 0-1.8.2-2.7.7-1 .5-1.7 1.1-2.3 1.8v18h-5.8V37.1h4.2l1.1 2.3c1.6-1.9 3.9-2.8 7-2.8 3 0 5.3.9 7 2.7 1.7 1.8 2.6 4.3 2.6 7.4V62h-5.9zM147.5 49.5c0-3.8 1.1-6.9 3.3-9.3 2.2-2.4 5.1-3.6 8.7-3.6 3.8 0 6.7 1.1 8.8 3.4 2.1 2.3 3.1 5.4 3.1 9.4s-1.1 7.1-3.2 9.5c-2.1 2.3-5 3.5-8.8 3.5-3.8 0-6.7-1.2-8.8-3.5-2-2.4-3.1-5.5-3.1-9.4zm6.1 0c0 5.5 2 8.2 5.9 8.2 1.8 0 3.2-.7 4.3-2.1 1.1-1.4 1.6-3.5 1.6-6.1 0-5.4-2-8.1-5.9-8.1-1.8 0-3.3.7-4.3 2.1-1.1 1.4-1.6 3.4-1.6 6zM192.1 62v-1.5c-.5.5-1.3 1-2.4 1.4-1.1.4-2.3.6-3.6.6-3.5 0-6.2-1.1-8.2-3.3-2-2.2-3-5.3-3-9.2 0-3.9 1.1-7.1 3.4-9.6s5.1-3.7 8.6-3.7c1.9 0 3.6.4 5.2 1.2v-10l5.8-1.4V62h-5.8zm0-19c-1.2-1-2.5-1.5-3.9-1.5-2.3 0-4.1.7-5.4 2.1-1.3 1.4-1.9 3.5-1.9 6.1 0 5.2 2.5 7.8 7.5 7.8.6 0 1.2-.2 2.1-.5.8-.3 1.3-.7 1.6-1V43zM226 51.3h-17.8c.1 2 .8 3.5 2 4.6 1.3 1.1 2.9 1.7 5.1 1.7 2.6 0 4.7-.7 6-2.1l2.3 4.4c-2 1.7-5.1 2.5-9.2 2.5-3.8 0-6.8-1.1-9-3.3-2.2-2.2-3.3-5.3-3.3-9.3 0-3.9 1.2-7.1 3.6-9.5 2.4-2.4 5.3-3.6 8.7-3.6 3.6 0 6.5 1.1 8.7 3.2 2.2 2.2 3.3 4.9 3.3 8.2.1.7-.1 1.7-.4 3.2zm-17.6-4.4h12.2c-.4-3.6-2.4-5.5-6-5.5-3.3.1-5.4 1.9-6.2 5.5z"/><g><path fill="#004712" d="M65.9 47.4l-1 11.5-3.3-2.3.4-5.8v-.1-.1l-.1-.1-.1-.1-7.1-4.7.1-5.1 11.1 6.8zM48.5 59.9L43.4 56v.9c0 .2-.1.4-.2.5L39.4 60l4.2 3.4.1.1v.2l.2 4 4.7 3.9-.1-11.7zm-32.1 5l2.4 11.5 9.9 10.5L27 75.3 16.4 64.9zm9.3 1.7l-2.4-16.1-12-10 3.2 15.6 11.2 10.5zm-3.8-26l-3.3-22.8L4.8 9.2l4.5 21.5 12.6 9.9z"/><path fill="#00B259" d="M75.7 41.2l-1.5 10.9-8.2 6.6 1-11.2 8.7-6.3zM49.6 59.9l.1 11.8 10.5-8.4.7-11.5-11.3 8.1zm-6.8 4.8L28 75.3l1.8 12.2 13.4-10.7-.4-12.1zm-.4-8l-.7-16-17.3 9.9 2.4 16.6 15.6-10.5zm-1.1-25.3l-.9-21.6-20.8 8L23 41l18.3-9.6z"/><path d="M76.9 40c0-.1 0-.1 0 0v-.2s0-.1-.1-.1c0 0-.1 0-.1-.1l-12-6.7c-.2-.1-.4-.1-.5 0L54 39.1h-.1v.6l-.1 5.4-4.1-2.7c-.2-.1-.4-.1-.6 0L43 45.8l-.3-6v-.1-.1-.1-.1-.1h-.1l-6.2-4.1 5.8-3c.2-.1.3-.3.3-.5L41.4 9v-.1s0-.1-.1-.1c0 0 0-.1-.1-.1L25.5 1.1c-.1-.1-.2-.1-.3-.1L3.9 7.6s-.1 0-.1.1c0 0-.1 0-.1.1v.6l4.7 22.9c0 .1.1.2.2.3l6.4 5-4.7 2.2s-.1 0-.1.1c0 0 0 .1-.1.1v.2l3.6 17.2c0 .1.1.2.2.3l4.5 4.2-3 1.8-.1.1s0 .1-.1.1V63.2L18 76.5c0 .1.1.2.1.3l10.9 12h.1s.1 0 .1.1h.5l14.4-11.5c.1-.1.2-.3.2-.4l-.3-7.9 4.8 4s.1 0 .1.1h.5L61 64c.1-.1.2-.2.2-.4l.4-5.8 3.5 2.4h.4s.1 0 .1-.1l9.4-7.5c.1-.1.2-.2.2-.3L76.9 40c0 .1 0 .1 0 0zM66 58.7l1-11.2 8.8-6.3-1.5 10.9-8.3 6.6zm-4.4-2.1l.4-5.8v-.1-.1l-.1-.1-.1-.1-7.1-4.7.1-5.1 11.1 6.9-1 11.5-3.3-2.4zm-1.5 6.7l-10.5 8.4-.1-11.8 11.3-8.1-.7 11.5zM43.3 76.8L29.8 87.5 28 75.3l14.7-10.5.6 12zm-24.6-.4l-2.4-11.5L27 75.3l1.7 11.6-10-10.5zm-.2-58.6l3.3 22.8-12.5-9.9L4.8 9.2l13.7 8.6zm21.9-8l.9 21.6L23 41l-3.4-23.2 20.8-8zm2 46.9L26.8 67.1l-2.4-16.6 17.3-9.9.7 16.1zm-19.1-6.1l2.4 16.1-11.2-10.6-3.2-15.6 12 10.1zm20.5 13.1v-.1-.1l-.1-.1-4.2-3.4 3.8-2.6c.2-.1.2-.3.2-.5V56l5.1 3.9.1 11.8-4.7-3.9-.2-4.1z"/></g></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -5,8 +5,8 @@
## We Develop with Github
We use github to host code, to track issues and feature requests, as well as accept pull requests.
## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests
Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests:
## We Use [Github Flow](https://docs.github.com/en/get-started/using-github/github-flow), So All Code Changes Happen Through Pull Requests
Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://docs.github.com/en/get-started/using-github/github-flow)). We actively welcome your pull requests:
1. Fork the repo and create your branch from `mealie-next`.
2. Checkout the Discord, the PRs page, or the Projects page to get an idea of what's already being worked on.
@@ -28,8 +28,8 @@ We use GitHub issues to track public bugs. Report a bug by [opening a new issue]
- A quick summary and/or background
- Steps to reproduce
- Be specific!
- Give sample code if you can. [This stackoverflow question](http://stackoverflow.com/q/12488905/180626) includes sample code that *anyone* with a base R setup can run to reproduce what I was seeing
* Be specific!
* Give sample code if you can. [This stackoverflow question](http://stackoverflow.com/q/12488905/180626) includes sample code that *anyone* with a base R setup can run to reproduce what I was seeing
- What you expected would happen
- What actually happens
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
@@ -41,4 +41,4 @@ People *love* thorough bug reports. I'm not even kidding.
By contributing, you agree that your contributions will be licensed under its AGPL License.
## References
This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/a9316a723f9e918afde44dea68b5f9f39b7d9b00/CONTRIBUTING.md)
This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebookarchive/draft-js/blob/main/CONTRIBUTING.md)

View File

@@ -6,7 +6,7 @@ This is the start of the maintainers guide for Mealie developers. Those who have
If you are working on issues, it can be helpful to understand the workflow for our repository. When an issue comes in it is tagged with the `bug` and `triage` flags. This is to indicate that they need to be reviewed by a maintainer to determine validity.
After you've reviered an issue it will generally move into one of two states:
After you've reviewed an issue it will generally move into one of two states:
`bug:confirmed`
: Your were able to verify the issue and we determined we need to fix it

View File

@@ -0,0 +1,63 @@
# OpenID Connect (OIDC) Authentication
:octicons-tag-24: v1.4.0
Mealie supports 3rd party authentication via [OpenID Connect (OIDC)](https://openid.net/connect/), an identity layer built on top of OAuth2. OIDC is supported by many Identity Providers (IdP), including:
- [Authentik](https://goauthentik.io/integrations/sources/oauth/#openid-connect)
- [Authelia](https://www.authelia.com/configuration/identity-providers/open-id-connect/)
- [Keycloak](https://www.keycloak.org/docs/latest/securing_apps/#_oidc)
- [Okta](https://www.okta.com/openid-connect/)
## Account Linking
Signing in with OAuth will automatically find your account in Mealie and link to it. If a user does not exist in Mealie, then one will be created (if enabled), but will be unable to log in with any other authentication method. An admin can configure another authentication method for such a user.
## Provider Setup
Before you can start using OIDC Authentication, you must first configure a new client application in your identity provider. Your identity provider must support the OAuth **Authorization Code flow with PKCE**. The steps will vary by provider, but generally, the steps are as follows.
1. Create a new client application
- The Provider type should be OIDC or OAuth2
- The Grant type should be `Authorization Code`
- The Application type should be `Web`
- The Client type should be `public`
2. Configure redirect URI
The redirect URI(s) that are needed:
1. `http(s)://DOMAIN:PORT/login`
2. `https(s)://DOMAIN:PORT/login?direct=1`
1. This URI is only required if your IdP supports [RP-Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) such as Keycloak. You may also be able to combine this into the previous URI by using a wildcard: `http(s)://DOMAIN:PORT/login*`
The redirect URI(s) should include any URL that Mealie is accessible from. Some examples include
http://localhost:9091/login
https://mealie.example.com/login
3. Configure origins
If your identity provider enforces CORS on any endpoints, you will need to specify your Mealie URL as an Allowed Origin.
4. Configure allowed scopes
The scopes required are `openid profile email groups`
## Mealie Setup
Take the client id and your discovery URL and update your environment variables to include the required OIDC variables described in [Installation - Backend Configuration](../installation/backend-config.md#openid-connect-oidc).
### Groups
There are two (optional) [environment variables](../installation/backend-config.md#openid-connect-oidc) that can control which of the users in your IdP can log in to Mealie and what permissions they will have. The groups should be **defined in your IdP** and be returned in the `groups` claim.
`OIDC_USER_GROUP`: Users must be a part of this group (within your IdP) to be able to log in.
`OIDC_ADMIN_GROUP`: Users that are in this group (within your IdP) will be made an **admin** in Mealie.
## Examples
Example configurations for several Identity Providers have been provided by the Community in the [GitHub Discussions](https://github.com/mealie-recipes/mealie/discussions/categories/oauth-provider-example).
If you don't see your provider and have successfully set it up, please consider [creating your own example](https://github.com/mealie-recipes/mealie/discussions/new?category=oauth-provider-example) so that others can have a smoother setup.

View File

@@ -94,6 +94,10 @@ docker exec -it mealie-next bash
python /app/mealie/scripts/change_password.py
```
## I can't log in with external auth. How can I change my authentication method?
Follow the [steps above](#how-can-i-change-my-password) for changing your password. You will be prompted if you would like to switch your authentication method back to local auth so you can log in again.
## How do private groups and recipes work?
Managing private groups and recipes can be confusing. The following diagram and notes should help explain how they work to determine if a recipe can be shared publicly.

View File

@@ -4,17 +4,21 @@
### General
| Variables | Default | Description |
| ------------- | :-------------------: | ----------------------------------------------------------------------------------- |
| PUID | 911 | UserID permissions between host OS and container |
| PGID | 911 | GroupID permissions between host OS and container |
| DEFAULT_GROUP | Home | The default group for users |
| BASE_URL | http://localhost:8080 | Used for Notifications |
| TOKEN_TIME | 48 | The time in hours that a login/auth token is valid |
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
| API_DOCS | True | Turns on/off access to the API documentation locally. |
| TZ | UTC | Must be set to get correct date/time on the server |
| ALLOW_SIGNUP | true | Allow user sign-up without token |
| Variables | Default | Description |
| ----------------------------- | :-------------------: | ----------------------------------------------------------------------------------- |
| PUID | 911 | UserID permissions between host OS and container |
| PGID | 911 | GroupID permissions between host OS and container |
| DEFAULT_GROUP | Home | The default group for users |
| BASE_URL | http://localhost:8080 | Used for Notifications |
| TOKEN_TIME | 48 | The time in hours that a login/auth token is valid |
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
| API_DOCS | True | Turns on/off access to the API documentation locally. |
| TZ | UTC | Must be set to get correct date/time on the server |
| ALLOW_SIGNUP<super>\*</super> | false | Allow user sign-up without token |
| LOG_CONFIG_OVERRIDE | | Override the config for logging with a custom path |
| LOG_LEVEL | info | logging level configured |
<super>\*</super> Starting in v1.4.0 this was changed to default to `false` as apart of a security review of the application.
### Security
@@ -25,14 +29,15 @@
### Database
| Variables | Default | Description |
| ----------------- | :------: | -------------------------------- |
| DB_ENGINE | sqlite | Optional: 'sqlite', 'postgres' |
| POSTGRES_USER | mealie | Postgres database user |
| POSTGRES_PASSWORD | mealie | Postgres database password |
| POSTGRES_SERVER | postgres | Postgres database server address |
| POSTGRES_PORT | 5432 | Postgres database port |
| POSTGRES_DB | mealie | Postgres database name |
| Variables | Default | Description |
| --------------------- | :------: | ----------------------------------------------------------------------- |
| DB_ENGINE | sqlite | Optional: 'sqlite', 'postgres' |
| POSTGRES_USER | mealie | Postgres database user |
| POSTGRES_PASSWORD | mealie | Postgres database password |
| POSTGRES_SERVER | postgres | Postgres database server address |
| POSTGRES_PORT | 5432 | Postgres database port |
| POSTGRES_DB | mealie | Postgres database name |
| POSTGRES_URL_OVERRIDE | None | Optional Postgres URL override to use instead of POSTGRES\_\* variables |
### Email
@@ -54,8 +59,8 @@ Changing the webworker settings may cause unforeseen memory leak issues with Mea
| ---------------- | :-----: | --------------------------------------------------------------------------------------------------------------------------------- |
| WEB_GUNICORN | false | Enables Gunicorn to manage Uvicorn web for multiple works |
| WORKERS_PER_CORE | 1 | Set the number of workers to the number of CPU cores multiplied by this value (Value \* CPUs). More info [here][workers_per_core] |
| MAX_WORKERS | 1 | Set the maximum number of workers to use. Default is not set meaning unlimited. More info [here][max_workers] |
| WEB_CONCURRENCY | 1 | Override the automatic definition of number of workers. More info [here][web_concurrency] |
| MAX_WORKERS | None | Set the maximum number of workers to use. Default is not set meaning unlimited. More info [here][max_workers] |
| WEB_CONCURRENCY | 2 | Override the automatic definition of number of workers. More info [here][web_concurrency] |
### LDAP
@@ -75,6 +80,26 @@ Changing the webworker settings may cause unforeseen memory leak issues with Mea
| LDAP_NAME_ATTRIBUTE | name | The LDAP attribute that maps to the user's name |
| LDAP_MAIL_ATTRIBUTE | mail | The LDAP attribute that maps to the user's email |
### OpenID Connect (OIDC)
:octicons-tag-24: v1.4.0
For usage, see [Usage - OpenID Connect](../authentication/oidc.md)
| Variables | Default | Description |
| ---------------------- | :-----: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OIDC_AUTH_ENABLED | False | Enables authentication via OpenID Connect |
| OIDC_SIGNUP_ENABLED | True | Enables new users to be created when signing in for the first time with OIDC |
| OIDC_CONFIGURATION_URL | None | The URL to the OIDC configuration of your provider. This is usually something like https://auth.example.com/.well-known/openid-configuration |
| OIDC_CLIENT_ID | None | The client id of your configured client in your provider |
| OIDC_USER_GROUP | None | If specified, only users belonging to this group will be able to successfully authenticate, regardless of the `OIDC_ADMIN_GROUP`. For more information see [this page](../authentication/oidc.md#groups) |
| OIDC_ADMIN_GROUP | None | If specified, users belonging to this group will be made an admin. For more information see [this page](../authentication/oidc.md#groups) |
| OIDC_AUTO_REDIRECT | False | If `True`, then the login page will be bypassed an you will be sent directly to your Identity Provider. You can still get to the login page by adding `?direct=1` to the login URL |
| OIDC_PROVIDER_NAME | OAuth | The provider name is shown in SSO login button. "Login with <OIDC_PROVIDER_NAME\>" |
| OIDC_REMEMBER_ME | False | Because redirects bypass the login screen, you cant extend your session by clicking the "Remember Me" checkbox. By setting this value to true, a session will be extended as if "Remember Me" was checked |
| OIDC_SIGNING_ALGORITHM | RS256 | The algorithm used to sign the id token (examples: RS256, HS256) |
| OIDC_USER_CLAIM | email | Optional: 'email', 'preferred_username' |
### Themeing
Setting the following environmental variables will change the theme of the frontend. Note that the themes are the same for all users. This is a break-change when migration from v0.x.x -> 1.x.x.
@@ -95,3 +120,7 @@ Setting the following environmental variables will change the theme of the front
| THEME_DARK_INFO | #1976D2 | Dark Theme Config Variable |
| THEME_DARK_WARNING | #FF6D00 | Dark Theme Config Variable |
| THEME_DARK_ERROR | #EF5350 | Dark Theme Config Variable |
[workers_per_core]: https://github.com/tiangolo/uvicorn-gunicorn-docker/blob/2daa3e3873c837d5781feb4ff6a40a89f791f81b/README.md#workers_per_core
[max_workers]: https://github.com/tiangolo/uvicorn-gunicorn-docker/blob/2daa3e3873c837d5781feb4ff6a40a89f791f81b/README.md#max_workers
[web_concurrency]: https://github.com/tiangolo/uvicorn-gunicorn-docker/blob/2daa3e3873c837d5781feb4ff6a40a89f791f81b/README.md#web_concurrency

View File

@@ -0,0 +1,16 @@
# Logs
:octicons-tag-24: v1.5.0
## Highlighs
- Logs are written to `/app/data/mealie.log` by default in the container.
- Logs are also written to stdout and stderr.
- You can adjust the log level using the `LOG_LEVEL` environment variable.
## Configuration
Starting in v1.5.0 logging is now highly configurable. Using the `LOG_CONFIG_OVERRIDE` you can provide the application with a custom configuration to log however you'd like. This configuration file is based off the [Python Logging Config](https://docs.python.org/3/library/logging.config.html#logging.config.fileConfig). It can be difficult to understand the configuration at first, so here are some resources to help get started.
- This [YouTube Video](https://www.youtube.com/watch?v=9L77QExPmI0) for a great walkthrough on the logging file format.
- Our [Logging Config](https://github.com/mealie-recipes/mealie/blob/mealie-next/mealie/core/logger/logconf.prod.json)

View File

@@ -5,40 +5,39 @@ PostgreSQL might be considered if you need to support many concurrent users. In
**For Environment Variable Configuration, see** [Backend Configuration](./backend-config.md)
```yaml
---
version: "3.7"
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v1.0.0 # (3)
image: ghcr.io/mealie-recipes/mealie:v1.4.0 # (3)
container_name: mealie
restart: always
ports:
- "9925:9000" # (1)
deploy:
resources:
limits:
memory: 1000M # (2)
depends_on:
- postgres
volumes:
- mealie-data:/app/data/
environment:
# Set Backend ENV Variables Here
- ALLOW_SIGNUP=true
- PUID=1000
- PGID=1000
- TZ=America/Anchorage
- MAX_WORKERS=1
- WEB_CONCURRENCY=1
- BASE_URL=https://mealie.yourdomain.com
# Set Backend ENV Variables Here
ALLOW_SIGNUP: true
PUID: 1000
PGID: 1000
TZ: America/Anchorage
MAX_WORKERS: 1
WEB_CONCURRENCY: 1
BASE_URL: https://mealie.yourdomain.com
# Database Settings
DB_ENGINE: postgres
POSTGRES_USER: mealie
POSTGRES_PASSWORD: mealie
POSTGRES_SERVER: postgres
POSTGRES_PORT: 5432
POSTGRES_DB: mealie
depends_on:
postgres:
condition: service_healthy
# Database Settings
- DB_ENGINE=postgres
- POSTGRES_USER=mealie
- POSTGRES_PASSWORD=mealie
- POSTGRES_SERVER=postgres
- POSTGRES_PORT=5432
- POSTGRES_DB=mealie
restart: always
postgres:
container_name: postgres
image: postgres:15
@@ -48,16 +47,19 @@ services:
environment:
POSTGRES_PASSWORD: mealie
POSTGRES_USER: mealie
healthcheck:
test: ["CMD", "pg_isready"]
interval: 30s
timeout: 20s
retries: 3
volumes:
mealie-data:
driver: local
mealie-pgdata:
driver: local
```
<!-- Updating This? Be Sure to also update the SQLite Annotations -->
1. To access the mealie interface you only need to expose port 9000 on the mealie container. Here we expose port 9925 on the host, but feel free to change this to any port you like.
2. Setting an explicit memory limit is recommended. Python can pre-allocate larger amounts of memory than is necessary if you have a machine with a lot of RAM. This can cause the container to idle at a high memory usage. Setting a memory limit will improve idle performance.
3. Whilst a 'latest' tag is available, the Mealie team advises specifying a specific version tag and consciously updating to newer versions when you have time to read the release notes and ensure you follow any manual actions required (which should be rare).
3. You should double check this value isn't out of date when setting up for the first time; check the README and use the value from the "latest release" badge at the top - the format should be `vX.Y.Z`. Whilst a 'latest' tag is available, the Mealie team advises specifying a specific version tag and consciously updating to newer versions when you have time to read the release notes and ensure you follow any manual actions required (which should be rare).

View File

@@ -0,0 +1,43 @@
---
tags:
- Security
---
# Security Considerations
This page is a collection of security considerations for Mealie. It mostly deals with reported issues and how it's possible to mitigate them. Note that this page is for you to use as a guide for how secure you want to make your deployment. It's important to note that most of these will not apply to you, if you:
1. Run behind a VPN
2. Use a strong password
3. Disable Sign-Ups
4. Don't host for malicious users
Use your best judgement when deciding what to do.
## Denial of Service
By default, the API is **not** rate limited. This leaves Mealie open to a potential **Denial of Service Attack**. While it's possible to perform a **Denial of Service Attack** on any endpoint, there are a few key endpoints that are more vulnerable than others.
- `/api/recipes/create-url`
- `/api/recipes/{id}/image`
These endpoints are used to scrape data based off a user provided URL. It is possible for a malicious user to issue multiple requests to download an arbitrarily large external file (e.g a Debian ISO) and sufficiently saturate a CPU assigned to the container. While we do implement some protections against this by chunking the response, and using a timeout strategy, it's still possible to overload the CPU if an attacker issues multiple requests concurrently.
### Mitigation
If you'd like to mitigate this risk, we suggest that you rate limit the API in general, and apply strict rate limits to these endpoints. You can do this by utilizing a reverse proxy. See the following links to get started:
- [Traefik](https://doc.traefik.io/traefik/middlewares/http/ratelimit/)
- [Nginx](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html)
- [Caddy](https://caddyserver.com/docs/modules/http.handlers.rate_limit)
## Server Side Request Forgery
- `/api/recipes/create-url`
- `/api/recipes/{id}/image`
Given the nature of these APIs it's possible to perform a **Server Side Request Forgery** attack. This is where a malicious user can issue a request to an internal network resource, and potentially exfiltrate data. We _do_ perform some checks to mitigate access to resources within your network but at the end of the day, users of Mealie are allowed to trigger HTTP requests on **your server**.
### Mitigation
If you'd like to mitigate this risk, we suggest that you isolate the container that Mealie is running in to ensure that it's access to internal resources is limited only to what is required. _Note that Mealie does require access to the internet for recipe imports._ You might consider isolating Mealie from your home network entirely and only allowing access to the external internet.

View File

@@ -9,12 +9,11 @@ SQLite is a popular, open source, self-contained, zero-configuration database th
**For Environment Variable Configuration, see** [Backend Configuration](./backend-config.md)
```yaml
---
version: "3.7"
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v1.0.0 # (3)
image: ghcr.io/mealie-recipes/mealie:v1.4.0 # (3)
container_name: mealie
restart: always
ports:
- "9925:9000" # (1)
deploy:
@@ -24,23 +23,21 @@ services:
volumes:
- mealie-data:/app/data/
environment:
# Set Backend ENV Variables Here
- ALLOW_SIGNUP=true
- PUID=1000
- PGID=1000
- TZ=America/Anchorage
- MAX_WORKERS=1
- WEB_CONCURRENCY=1
- BASE_URL=https://mealie.yourdomain.com
restart: always
# Set Backend ENV Variables Here
ALLOW_SIGNUP: true
PUID: 1000
PGID: 1000
TZ: America/Anchorage
MAX_WORKERS: 1
WEB_CONCURRENCY: 1
BASE_URL: https://mealie.yourdomain.com
volumes:
mealie-data:
driver: local
```
<!-- Updating This? Be Sure to also update the Postgres Annotations -->
1. To access the mealie interface you only need to expose port 9000 on the container. Here we expose port 9925 on the host, but feel free to change this to any port you like.
2. Setting an explicit memory limit is recommended. Python can pre-allocate larger amounts of memory than is necessary if you have a machine with a lot of RAM. This can cause the container to idle at a high memory usage. Setting a memory limit will improve idle performance.
3. Whilst a 'latest' tag is available, the Mealie team advises specifying a specific version tag and consciously updating to newer versions when you have time to read the release notes and ensure you follow any manual actions required (which should be rare).
3. You should double check this value isn't out of date when setting up for the first time; check the README and use the value from the "latest release" badge at the top - the format should be `vX.Y.Z`. Whilst a 'latest' tag is available, the Mealie team advises specifying a specific version tag and consciously updating to newer versions when you have time to read the release notes and ensure you follow any manual actions required (which should be rare).

View File

@@ -1,7 +1,7 @@
# Permissions and Public Access
Mealie provides various levels of user access and permissions. This includes:
- Authentication and registration ([check out the LDAP guide](./ldap.md) for how to configure access using LDAP)
- Authentication and registration ([LDAP](../authentication/ldap.md) and [OpenID Connect](../authentication/oidc.md) are both supported)
- Customizable user permissions
- Fine-tuned public access for non-users

File diff suppressed because one or more lines are too long

View File

@@ -41,7 +41,8 @@ markdown_extensions:
custom_checkbox: true
- admonition
- attr_list
- pymdownx.tabbed
- pymdownx.tabbed:
alternate_style: true
- pymdownx.superfences:
custom_fences:
- name: mermaid
@@ -51,8 +52,8 @@ extra_css:
- assets/stylesheets/custom.css
extra_javascript:
- assets/js/extra.js
repo_url: https://github.com/hay-kot/mealie/
repo_name: hay-kot/mealie
repo_url: https://github.com/mealie-recipes/mealie/
repo_name: mealie-recipes/mealie
edit_uri: edit/mealie-next/docs/docs/
nav:
@@ -71,9 +72,15 @@ nav:
- SQLite (Recommended): "documentation/getting-started/installation/sqlite.md"
- PostgreSQL: "documentation/getting-started/installation/postgres.md"
- Backend Configuration: "documentation/getting-started/installation/backend-config.md"
- Security: "documentation/getting-started/installation/security.md"
- Logs: "documentation/getting-started/installation/logs.md"
- Usage:
- Backup and Restoring: "documentation/getting-started/usage/backups-and-restoring.md"
- LDAP Authentication: "documentation/getting-started/usage/ldap.md"
- Permissions and Public Access: "documentation/getting-started/usage/permissions-and-public-access.md"
- Authentication:
- LDAP: "documentation/getting-started/authentication/ldap.md"
- OpenID Connect: "documentation/getting-started/authentication/oidc.md"
- Community Guides:
- iOS Shortcuts: "documentation/community-guide/ios.md"

View File

@@ -0,0 +1,55 @@
<template>
<div>
<v-card-text v-if="cookbook">
<v-text-field v-model="cookbook.name" :label="$t('cookbook.cookbook-name')"></v-text-field>
<v-textarea v-model="cookbook.description" auto-grow :rows="2" :label="$t('recipe.description')"></v-textarea>
<RecipeOrganizerSelector v-model="cookbook.categories" selector-type="categories" />
<RecipeOrganizerSelector v-model="cookbook.tags" selector-type="tags" />
<RecipeOrganizerSelector v-model="cookbook.tools" selector-type="tools" />
<v-switch v-model="cookbook.public" hide-details single-line>
<template #label>
{{ $t('cookbook.public-cookbook') }}
<HelpIcon small right class="ml-2">
{{ $t('cookbook.public-cookbook-description') }}
</HelpIcon>
</template>
</v-switch>
<div class="mt-4">
<h3 class="text-subtitle-1 d-flex align-center mb-0 pb-0">
{{ $t('cookbook.filter-options') }}
<HelpIcon right small class="ml-2">
{{ $t('cookbook.filter-options-description') }}
</HelpIcon>
</h3>
<v-switch v-model="cookbook.requireAllCategories" class="mt-0" hide-details single-line>
<template #label> {{ $t('cookbook.require-all-categories') }} </template>
</v-switch>
<v-switch v-model="cookbook.requireAllTags" hide-details single-line>
<template #label> {{ $t('cookbook.require-all-tags') }} </template>
</v-switch>
<v-switch v-model="cookbook.requireAllTools" hide-details single-line>
<template #label> {{ $t('cookbook.require-all-tools') }} </template>
</v-switch>
</div>
</v-card-text>
</div>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api";
import { ReadCookBook } from "~/lib/api/types/cookbook";
import RecipeOrganizerSelector from "~/components/Domain/Recipe/RecipeOrganizerSelector.vue";
export default defineComponent({
components: { RecipeOrganizerSelector },
props: {
cookbook: {
type: Object as () => ReadCookBook,
required: true,
},
actions: {
type: Object as () => any,
required: true,
},
},
});
</script>

View File

@@ -1,8 +1,33 @@
<template>
<div>
<!-- Edit Dialog -->
<BaseDialog
v-if="editTarget"
v-model="dialogStates.edit"
:width="650"
:icon="$globals.icons.pages"
:title="$t('general.edit')"
:submit-icon="$globals.icons.save"
:submit-text="$tc('general.save')"
@submit="editCookbook"
>
<v-card-text>
<CookbookEditor :cookbook="editTarget" :actions="actions" />
</v-card-text>
</BaseDialog>
<!-- Page -->
<v-container v-if="book" fluid>
<v-app-bar color="transparent" flat class="mt-n1 rounded">
<v-app-bar color="transparent" flat class="mt-n1">
<v-icon large left> {{ $globals.icons.pages }} </v-icon>
<v-toolbar-title class="headline"> {{ book.name }} </v-toolbar-title>
<v-spacer></v-spacer>
<BaseButton
v-if="isOwnGroup"
class="mx-1"
:edit="true"
@click="handleEditCookbook"
/>
</v-app-bar>
<v-card flat>
<v-card-text class="py-0">
@@ -22,17 +47,20 @@
/>
</v-container>
</v-container>
</template>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, useRoute, ref, useContext, useMeta } from "@nuxtjs/composition-api";
import { computed, defineComponent, useRoute, ref, useContext, useMeta, reactive, useRouter } from "@nuxtjs/composition-api";
import { useLazyRecipes } from "~/composables/recipes";
import RecipeCardSection from "@/components/Domain/Recipe/RecipeCardSection.vue";
import { useCookbook } from "~/composables/use-group-cookbooks";
import { useCookbook, useCookbooks } from "~/composables/use-group-cookbooks";
import { useLoggedInState } from "~/composables/use-logged-in-state";
import { RecipeCookBook } from "~/lib/api/types/cookbook";
import CookbookEditor from "~/components/Domain/Cookbook/CookbookEditor.vue";
export default defineComponent({
components: { RecipeCardSection },
components: { RecipeCardSection, CookbookEditor },
setup() {
const { $auth } = useContext();
const { isOwnGroup } = useLoggedInState();
@@ -43,10 +71,36 @@
const { recipes, appendRecipes, assignSorted, removeRecipe, replaceRecipes } = useLazyRecipes(isOwnGroup.value ? null : groupSlug.value);
const slug = route.value.params.slug;
const { getOne } = useCookbook(isOwnGroup.value ? null : groupSlug.value);
const { actions } = useCookbooks();
const router = useRouter();
const tab = ref(null);
const book = getOne(slug);
const dialogStates = reactive({
edit: false,
});
const editTarget = ref<RecipeCookBook | null>(null);
function handleEditCookbook() {
dialogStates.edit = true;
editTarget.value = book.value;
}
async function editCookbook() {
if (!editTarget.value) {
return;
}
const response = await actions.updateOne(editTarget.value);
// if name changed, redirect to new slug
if (response?.slug && book.value?.slug !== response?.slug) {
router.push(`/g/${route.value.params.groupSlug}/cookbooks/${response?.slug}`);
}
dialogStates.edit = false;
editTarget.value = null;
}
useMeta(() => {
return {
title: book?.value?.name || "Cookbook",
@@ -62,6 +116,12 @@
recipes,
removeRecipe,
replaceRecipes,
isOwnGroup,
dialogStates,
editTarget,
handleEditCookbook,
editCookbook,
actions,
};
},
head: {}, // Must include for useMeta

View File

@@ -107,7 +107,7 @@ export default defineComponent({
})
async function getShoppingLists() {
const { data } = await api.shopping.lists.getAll();
const { data } = await api.shopping.lists.getAll(1, -1, { orderBy: "name", orderDirection: "asc" });
if (data) {
shoppingLists.value = data.items ?? [];
}

View File

@@ -19,7 +19,7 @@
<script lang="ts">
import { defineComponent, computed, useContext } from "@nuxtjs/composition-api";
import RecipeOrganizerSelector from "~/components/Domain/Recipe/RecipeOrganizerSelector.vue";
import { RecipeTag, RecipeCategory } from "~/lib/api/types/group";
import { RecipeTag, RecipeCategory } from "~/lib/api/types/recipe";
export default defineComponent({
components: {

View File

@@ -21,7 +21,7 @@
<v-spacer></v-spacer>
<div v-if="!open" class="custom-btn-group ma-1">
<RecipeFavoriteBadge v-if="loggedIn" class="mx-1" color="info" button-style :slug="recipe.slug" show-always />
<RecipeFavoriteBadge v-if="loggedIn" class="mx-1" color="info" button-style :recipe-id="recipe.id" show-always />
<RecipeTimelineBadge v-if="loggedIn" button-style :slug="recipe.slug" :recipe-name="recipe.name" />
<div v-if="loggedIn">
<v-tooltip v-if="!locked" bottom color="info">

View File

@@ -3,8 +3,9 @@
<v-hover v-slot="{ hover }" :open-delay="50">
<v-card
:class="{ 'on-hover': hover }"
:style="{ cursor }"
:elevation="hover ? 12 : 2"
:to="route ? recipeRoute : ''"
:to="recipeRoute"
:min-height="imageHeight + 75"
@click="$emit('click')"
>
@@ -33,10 +34,10 @@
</v-card-title>
<slot name="actions">
<v-card-actions class="px-1">
<RecipeFavoriteBadge v-if="isOwnGroup" class="absolute" :slug="slug" show-always />
<v-card-actions v-if="showRecipeContent" class="px-1">
<RecipeFavoriteBadge v-if="isOwnGroup" class="absolute" :recipe-id="recipeId" show-always />
<RecipeRating class="pb-1" :value="rating" :name="name" :slug="slug" :small="true" />
<RecipeRating class="pb-1" :value="rating" :recipe-id="recipeId" :slug="slug" :small="true" />
<v-spacer></v-spacer>
<RecipeChips :truncate="true" :items="tags" :title="false" :limit="2" :small="true" url-prefix="tags" />
@@ -96,15 +97,15 @@ export default defineComponent({
required: false,
default: 0,
},
ratingColor: {
type: String,
default: "secondary",
},
image: {
type: String,
required: false,
default: "abc123",
},
route: {
type: Boolean,
default: true,
},
tags: {
type: Array,
default: () => [],
@@ -123,14 +124,18 @@ export default defineComponent({
const { isOwnGroup } = useLoggedInState();
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "")
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
const showRecipeContent = computed(() => props.recipeId && props.slug);
const recipeRoute = computed<string>(() => {
return `/g/${groupSlug.value}/r/${props.slug}`;
return showRecipeContent.value ? `/g/${groupSlug.value}/r/${props.slug}` : "";
});
const cursor = computed(() => showRecipeContent.value ? "pointer" : "auto");
return {
isOwnGroup,
recipeRoute,
showRecipeContent,
cursor,
};
},
});

View File

@@ -3,6 +3,7 @@
<v-card
:ripple="false"
:class="isFlat ? 'mx-auto flat' : 'mx-auto'"
:style="{ cursor }"
hover
:to="$listeners.selected ? undefined : recipeRoute"
@click="$emit('selected')"
@@ -37,22 +38,20 @@
</v-list-item-subtitle>
<div class="d-flex flex-wrap justify-end align-center">
<slot name="actions">
<RecipeFavoriteBadge v-if="isOwnGroup" :slug="slug" show-always />
<v-rating
color="secondary"
<RecipeFavoriteBadge v-if="isOwnGroup && showRecipeContent" :recipe-id="recipeId" show-always />
<RecipeRating
:class="isOwnGroup ? 'ml-auto' : 'ml-auto pb-2'"
background-color="secondary lighten-3"
dense
length="5"
size="15"
:value="rating"
></v-rating>
:recipe-id="recipeId"
:slug="slug"
:small="true"
/>
<v-spacer></v-spacer>
<!-- If we're not logged-in, no items display, so we hide this menu -->
<!-- We also add padding to the v-rating above to compensate -->
<RecipeContextMenu
v-if="isOwnGroup"
v-if="isOwnGroup && showRecipeContent"
:slug="slug"
:menu-icon="$globals.icons.dotsHorizontal"
:name="name"
@@ -83,12 +82,14 @@ import { computed, defineComponent, useContext, useRoute } from "@nuxtjs/composi
import RecipeFavoriteBadge from "./RecipeFavoriteBadge.vue";
import RecipeContextMenu from "./RecipeContextMenu.vue";
import RecipeCardImage from "./RecipeCardImage.vue";
import RecipeRating from "./RecipeRating.vue";
import { useLoggedInState } from "~/composables/use-logged-in-state";
export default defineComponent({
components: {
RecipeFavoriteBadge,
RecipeContextMenu,
RecipeRating,
RecipeCardImage,
},
props: {
@@ -113,10 +114,6 @@ export default defineComponent({
required: false,
default: "abc123",
},
route: {
type: Boolean,
default: true,
},
recipeId: {
type: String,
required: true,
@@ -135,14 +132,19 @@ export default defineComponent({
const { isOwnGroup } = useLoggedInState();
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "")
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
const showRecipeContent = computed(() => props.recipeId && props.slug);
const recipeRoute = computed<string>(() => {
return `/g/${groupSlug.value}/r/${props.slug}`;
return showRecipeContent.value ? `/g/${groupSlug.value}/r/${props.slug}` : "";
});
const cursor = computed(() => showRecipeContent.value ? "pointer" : "auto");
return {
isOwnGroup,
recipeRoute,
showRecipeContent,
cursor,
};
},
});

View File

@@ -9,7 +9,7 @@
color="accent"
:small="small"
dark
:to="isOwnGroup ? `${baseRecipeRoute}?${urlPrefix}=${category.id}` : undefined"
:to="`${baseRecipeRoute}?${urlPrefix}=${category.id}`"
>
{{ truncateText(category.name) }}
</v-chip>
@@ -18,8 +18,7 @@
<script lang="ts">
import { computed, defineComponent, useContext, useRoute } from "@nuxtjs/composition-api";
import { useLoggedInState } from "~/composables/use-logged-in-state";
import { RecipeCategory, RecipeTag, RecipeTool } from "~/lib/api/types/user";
import { RecipeCategory, RecipeTag, RecipeTool } from "~/lib/api/types/recipe";
export type UrlPrefixParam = "tags" | "categories" | "tools";
@@ -56,7 +55,6 @@ export default defineComponent({
},
setup(props) {
const { $auth } = useContext();
const { isOwnGroup } = useLoggedInState();
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "")
@@ -74,7 +72,6 @@ export default defineComponent({
return {
baseRecipeRoute,
isOwnGroup,
truncateText,
};
},

View File

@@ -59,7 +59,13 @@
v-on="on"
></v-text-field>
</template>
<v-date-picker v-model="newMealdate" no-title @input="pickerMenu = false"></v-date-picker>
<v-date-picker
v-model="newMealdate"
no-title
:first-day-of-week="firstDayOfWeek"
:local="$i18n.locale"
@input="pickerMenu = false"
/>
</v-menu>
<v-select
v-model="newMealType"
@@ -111,6 +117,7 @@ import RecipeDialogPrintPreferences from "./RecipeDialogPrintPreferences.vue";
import RecipeDialogShare from "./RecipeDialogShare.vue";
import { useLoggedInState } from "~/composables/use-logged-in-state";
import { useUserApi } from "~/composables/api";
import { useGroupSelf } from "~/composables/use-groups";
import { alert } from "~/composables/use-toast";
import { usePlanTypeOptions } from "~/composables/use-group-mealplan";
import { Recipe } from "~/lib/api/types/recipe";
@@ -224,11 +231,16 @@ export default defineComponent({
});
const { i18n, $auth, $globals } = useContext();
const { group } = useGroupSelf();
const { isOwnGroup } = useLoggedInState();
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
const firstDayOfWeek = computed(() => {
return group.value?.preferences?.firstDayOfWeek || 0;
});
// ===========================================================================
// Context Menu Setup
@@ -321,7 +333,7 @@ export default defineComponent({
const recipeRefWithScale = computed(() => recipeRef.value ? { scale: props.recipeScale, ...recipeRef.value } : undefined);
async function getShoppingLists() {
const { data } = await api.shopping.lists.getAll();
const { data } = await api.shopping.lists.getAll(1, -1, { orderBy: "name", orderDirection: "asc" });
if (data) {
shoppingLists.value = data.items ?? [];
}
@@ -432,6 +444,7 @@ export default defineComponent({
addRecipeToPlan,
icon,
planTypeOptions,
firstDayOfWeek,
};
},
});

View File

@@ -3,7 +3,7 @@
<BaseDialog v-if="shoppingListDialog" v-model="dialog" :title="$t('recipe.add-to-list')" :icon="$globals.icons.cartCheck">
<v-card-text>
<v-card
v-for="list in shoppingLists"
v-for="list in shoppingListChoices"
:key="list.id"
hover
class="my-2 left-border"
@@ -14,6 +14,18 @@
</v-card-title>
</v-card>
</v-card-text>
<template #card-actions>
<v-btn
text
color="grey"
@click="dialog = false"
>
{{ $t("general.cancel") }}
</v-btn>
<div class="d-flex justify-end" style="width: 100%;">
<v-checkbox v-model="preferences.viewAllLists" hide-details :label="$tc('general.show-all')" class="my-auto mr-4" />
</div>
</template>
</BaseDialog>
<BaseDialog
v-if="shoppingListIngredientDialog"
@@ -120,6 +132,7 @@ import { toRefs } from "@vueuse/core";
import RecipeIngredientListItem from "./RecipeIngredientListItem.vue";
import { useUserApi } from "~/composables/api";
import { alert } from "~/composables/use-toast";
import { useShoppingListPreferences } from "~/composables/use-users/preferences";
import { ShoppingListSummary } from "~/lib/api/types/group";
import { Recipe, RecipeIngredient } from "~/lib/api/types/recipe";
@@ -164,8 +177,9 @@ export default defineComponent({
},
},
setup(props, context) {
const { i18n } = useContext();
const { $auth, i18n } = useContext();
const api = useUserApi();
const preferences = useShoppingListPreferences();
// v-model support
const dialog = computed({
@@ -183,6 +197,10 @@ export default defineComponent({
shoppingListIngredientDialog: false,
});
const shoppingListChoices = computed(() => {
return props.shoppingLists.filter((list) => preferences.value.viewAllLists || list.userId === $auth.user?.id);
});
const recipeIngredientSections = ref<ShoppingListRecipeIngredientSection[]>([]);
const selectedShoppingList = ref<ShoppingListSummary | null>(null);
@@ -334,6 +352,8 @@ export default defineComponent({
return {
dialog,
preferences,
shoppingListChoices,
...toRefs(state),
addRecipesToList,
bulkCheckIngredients,

View File

@@ -45,7 +45,6 @@
:rating="recipe.rating"
:image="recipe.image"
:recipe-id="recipe.id"
:route="true"
v-on="$listeners.selected ? { selected: () => handleSelect(recipe) } : {}"
/>
</v-card>

View File

@@ -22,7 +22,13 @@
v-on="on"
></v-text-field>
</template>
<v-date-picker v-model="expirationDate" no-title @input="datePickerMenu = false"></v-date-picker>
<v-date-picker
v-model="expirationDate"
no-title
:first-day-of-week="firstDayOfWeek"
:local="$i18n.locale"
@input="datePickerMenu = false"
/>
</v-menu>
</v-card-text>
<v-card-actions class="justify-end">
@@ -60,6 +66,7 @@ import { defineComponent, computed, toRefs, reactive, useContext, useRoute } fro
import { useClipboard, useShare, whenever } from "@vueuse/core";
import { RecipeShareToken } from "~/lib/api/types/recipe";
import { useUserApi } from "~/composables/api";
import { useGroupSelf } from "~/composables/use-groups";
import { alert } from "~/composables/use-toast";
export default defineComponent({
@@ -106,9 +113,14 @@ export default defineComponent({
);
const { $auth, i18n } = useContext();
const { group } = useGroupSelf();
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
const firstDayOfWeek = computed(() => {
return group.value?.preferences?.firstDayOfWeek || 0;
});
// ============================================================
// Token Actions
@@ -185,6 +197,7 @@ export default defineComponent({
dialog,
createNewToken,
deleteToken,
firstDayOfWeek,
shareRecipe,
copyTokenLink,
};

View File

@@ -67,12 +67,16 @@
<v-list>
<v-list-item @click="toggleOrderDirection()">
<v-icon left>
{{ $globals.icons.sort }}
{{
state.orderDirection === "asc" ?
$globals.icons.sortDescending : $globals.icons.sortAscending
}}
</v-icon>
<v-list-item-title>
{{ state.orderDirection === "asc" ? "Sort Descending" : "Sort Ascending" }}
{{ state.orderDirection === "asc" ? $tc("general.sort-descending") : $tc("general.sort-ascending") }}
</v-list-item-title>
</v-list-item>
<v-divider />
<v-list-item
v-for="v in sortable"
:key="v.name"
@@ -120,11 +124,12 @@
<v-divider></v-divider>
<v-container class="mt-6 px-md-6">
<RecipeCardSection
v-if="state.ready"
class="mt-n5"
:icon="$globals.icons.search"
:title="$tc('search.results')"
:recipes="recipes"
:query="passedQuery"
:query="passedQueryWithSeed"
@replaceRecipes="replaceRecipes"
@appendRecipes="appendRecipes"
/>
@@ -133,11 +138,12 @@
</template>
<script lang="ts">
import { ref, defineComponent, useRouter, onMounted, useContext, computed, Ref, useRoute } from "@nuxtjs/composition-api";
import { ref, defineComponent, useRouter, onMounted, useContext, computed, Ref, useRoute, watch } from "@nuxtjs/composition-api";
import { watchDebounced } from "@vueuse/shared";
import SearchFilter from "~/components/Domain/SearchFilter.vue";
import { useLoggedInState } from "~/composables/use-logged-in-state";
import { useCategoryStore, useFoodStore, useTagStore, useToolStore } from "~/composables/store";
import { useUserSortPreferences } from "~/composables/use-users/preferences";
import RecipeCardSection from "~/components/Domain/Recipe/RecipeCardSection.vue";
import { IngredientFood, RecipeCategory, RecipeTag, RecipeTool } from "~/lib/api/types/recipe";
import { NoUndefinedField } from "~/lib/api/types/non-generated";
@@ -157,6 +163,7 @@ export default defineComponent({
const { isOwnGroup } = useLoggedInState();
const state = ref({
auto: true,
ready: false,
search: "",
orderBy: "created_at",
orderDirection: "desc" as "asc" | "desc",
@@ -170,6 +177,7 @@ export default defineComponent({
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
const preferences = useUserSortPreferences();
const { recipes, appendRecipes, assignSorted, removeRecipe, replaceRecipes } = useLazyRecipes(isOwnGroup.value ? null : groupSlug.value);
const categories = isOwnGroup.value ? useCategoryStore() : usePublicCategoryStore(groupSlug.value);
@@ -184,7 +192,30 @@ export default defineComponent({
const tools = isOwnGroup.value ? useToolStore() : usePublicToolStore(groupSlug.value);
const selectedTools = ref<NoUndefinedField<RecipeTool>[]>([]);
const passedQuery = ref<RecipeSearchQuery | null>(null);
function calcPassedQuery(): RecipeSearchQuery {
return {
search: state.value.search,
categories: toIDArray(selectedCategories.value),
foods: toIDArray(selectedFoods.value),
tags: toIDArray(selectedTags.value),
tools: toIDArray(selectedTools.value),
requireAllCategories: state.value.requireAllCategories,
requireAllTags: state.value.requireAllTags,
requireAllTools: state.value.requireAllTools,
requireAllFoods: state.value.requireAllFoods,
orderBy: state.value.orderBy,
orderDirection: state.value.orderDirection,
};
}
const passedQuery = ref<RecipeSearchQuery>(calcPassedQuery());
// we calculate this separately because otherwise we can't check for query changes
const passedQueryWithSeed = computed(() => {
return {
...passedQuery.value,
_searchSeed: Date.now().toString()
};
})
function reset() {
state.value.search = "";
@@ -199,10 +230,6 @@ export default defineComponent({
selectedTags.value = [];
selectedTools.value = [];
router.push({
query: {},
});
search();
}
@@ -211,7 +238,8 @@ export default defineComponent({
}
function toIDArray(array: { id: string }[]) {
return array.map((item) => item.id);
// we sort the array to make sure the query is always the same
return array.map((item) => item.id).sort();
}
function hideKeyboard() {
@@ -221,40 +249,33 @@ export default defineComponent({
const input: Ref<any> = ref(null);
async function search() {
await router.push({
query: {
categories: toIDArray(selectedCategories.value),
foods: toIDArray(selectedFoods.value),
tags: toIDArray(selectedTags.value),
tools: toIDArray(selectedTools.value),
// Only add the query param if it's or not default
...{
auto: state.value.auto ? undefined : "false",
search: state.value.search === "" ? undefined : state.value.search,
orderBy: state.value.orderBy === "createdAt" ? undefined : state.value.orderBy,
orderDirection: state.value.orderDirection === "desc" ? undefined : state.value.orderDirection,
requireAllCategories: state.value.requireAllCategories ? "true" : undefined,
requireAllTags: state.value.requireAllTags ? "true" : undefined,
requireAllTools: state.value.requireAllTools ? "true" : undefined,
requireAllFoods: state.value.requireAllFoods ? "true" : undefined,
},
},
});
const oldQueryValueString = JSON.stringify(passedQuery.value);
const newQueryValue = calcPassedQuery();
const newQueryValueString = JSON.stringify(newQueryValue);
if (oldQueryValueString === newQueryValueString) {
return;
}
passedQuery.value = {
search: state.value.search,
categories: toIDArray(selectedCategories.value),
foods: toIDArray(selectedFoods.value),
tags: toIDArray(selectedTags.value),
tools: toIDArray(selectedTools.value),
requireAllCategories: state.value.requireAllCategories,
requireAllTags: state.value.requireAllTags,
requireAllTools: state.value.requireAllTools,
requireAllFoods: state.value.requireAllFoods,
orderBy: state.value.orderBy,
orderDirection: state.value.orderDirection,
_searchSeed: Date.now().toString()
};
passedQuery.value = newQueryValue;
const query = {
categories: passedQuery.value.categories,
foods: passedQuery.value.foods,
tags: passedQuery.value.tags,
tools: passedQuery.value.tools,
// Only add the query param if it's or not default
...{
auto: state.value.auto ? undefined : "false",
search: passedQuery.value.search === "" ? undefined : passedQuery.value.search,
orderBy: passedQuery.value.orderBy === "created_at" ? undefined : passedQuery.value.orderBy,
orderDirection: passedQuery.value.orderDirection === "desc" ? undefined : passedQuery.value.orderDirection,
requireAllCategories: passedQuery.value.requireAllCategories ? "true" : undefined,
requireAllTags: passedQuery.value.requireAllTags ? "true" : undefined,
requireAllTools: passedQuery.value.requireAllTools ? "true" : undefined,
requireAllFoods: passedQuery.value.requireAllFoods ? "true" : undefined,
},
}
await router.push({ query });
preferences.value.searchQuery = JSON.stringify(query);
}
function waitUntilAndExecute(
@@ -325,13 +346,20 @@ export default defineComponent({
},
];
onMounted(() => {
// Hydrate Search
// wait for stores to be hydrated
watch(
() => route.value.query,
() => {
if (state.value.ready) {
hydrateSearch();
}
},
{
deep: true,
},
)
// read query params
async function hydrateSearch() {
const query = router.currentRoute.query;
if (query.auto) {
state.value.auto = query.auto === "true";
}
@@ -363,6 +391,8 @@ export default defineComponent({
}
)
);
} else {
selectedCategories.value = [];
}
if (query.foods) {
@@ -380,6 +410,8 @@ export default defineComponent({
}
)
);
} else {
selectedFoods.value = [];
}
if (query.tags) {
@@ -392,6 +424,8 @@ export default defineComponent({
}
)
);
} else {
selectedTags.value = [];
}
if (query.tools) {
@@ -404,11 +438,28 @@ export default defineComponent({
}
)
);
} else {
selectedTools.value = [];
}
Promise.allSettled(promises).then(() => {
search();
});
await Promise.allSettled(promises);
};
onMounted(async () => {
// restore the user's last search query
if (preferences.value.searchQuery && !(Object.keys(route.value.query).length > 0)) {
try {
const query = JSON.parse(preferences.value.searchQuery);
await router.replace({ query });
} catch (error) {
preferences.value.searchQuery = "";
router.replace({ query: {} });
}
}
await hydrateSearch();
await search();
state.value.ready = true;
});
watchDebounced(
@@ -426,7 +477,7 @@ export default defineComponent({
selectedTools,
],
async () => {
if (state.value.auto) {
if (state.value.ready && state.value.auto) {
await search();
}
},
@@ -459,7 +510,7 @@ export default defineComponent({
recipes,
removeRecipe,
replaceRecipes,
passedQuery,
passedQueryWithSeed,
};
},
head: {},

View File

@@ -22,11 +22,12 @@
<script lang="ts">
import { computed, defineComponent, useContext } from "@nuxtjs/composition-api";
import { useUserSelfRatings } from "~/composables/use-users";
import { useUserApi } from "~/composables/api";
import { UserOut } from "~/lib/api/types/user";
export default defineComponent({
props: {
slug: {
recipeId: {
type: String,
default: "",
},
@@ -42,19 +43,23 @@ export default defineComponent({
setup(props) {
const api = useUserApi();
const { $auth } = useContext();
const { userRatings, refreshUserRatings } = useUserSelfRatings();
// TODO Setup the correct type for $auth.user
// See https://github.com/nuxt-community/auth-module/issues/1097
const user = computed(() => $auth.user as unknown as UserOut);
const isFavorite = computed(() => user.value?.favoriteRecipes?.includes(props.slug));
const isFavorite = computed(() => {
const rating = userRatings.value.find((r) => r.recipeId === props.recipeId);
return rating?.isFavorite || false;
});
async function toggleFavorite() {
if (!isFavorite.value) {
await api.users.addFavorite(user.value?.id, props.slug);
await api.users.addFavorite(user.value?.id, props.recipeId);
} else {
await api.users.removeFavorite(user.value?.id, props.slug);
await api.users.removeFavorite(user.value?.id, props.recipeId);
}
$auth.fetchUser();
await refreshUserRatings();
}
return { isFavorite, toggleFavorite };

View File

@@ -41,6 +41,7 @@
<v-date-picker
v-model="newTimelineEventTimestamp"
no-title
:first-day-of-week="firstDayOfWeek"
:local="$i18n.locale"
@input="datePickerMenu = false"
/>
@@ -109,10 +110,11 @@
</template>
<script lang="ts">
import { defineComponent, reactive, ref, toRefs, useContext } from "@nuxtjs/composition-api";
import { computed, defineComponent, reactive, ref, toRefs, useContext } from "@nuxtjs/composition-api";
import { whenever } from "@vueuse/core";
import { VForm } from "~/types/vuetify";
import { useUserApi } from "~/composables/api";
import { useGroupSelf } from "~/composables/use-groups";
import { Recipe, RecipeTimelineEventIn } from "~/lib/api/types/recipe";
export default defineComponent({
@@ -129,11 +131,11 @@ export default defineComponent({
setup(props, context) {
const madeThisDialog = ref(false);
const userApi = useUserApi();
const { group } = useGroupSelf();
const { $auth, i18n } = useContext();
const domMadeThisForm = ref<VForm>();
const newTimelineEvent = ref<RecipeTimelineEventIn>({
// @ts-expect-error - TS doesn't like the $auth global user attribute
subject: i18n.t("recipe.user-made-this", { user: $auth.user.fullName } as string),
subject: "",
eventType: "comment",
eventMessage: "",
timestamp: undefined,
@@ -154,6 +156,10 @@ export default defineComponent({
}
);
const firstDayOfWeek = computed(() => {
return group.value?.preferences?.firstDayOfWeek || 0;
});
function clearImage() {
newTimelineEventImage.value = undefined;
newTimelineEventImageName.value = "";
@@ -178,6 +184,8 @@ export default defineComponent({
}
newTimelineEvent.value.recipeId = props.recipe.id
// @ts-expect-error - TS doesn't like the $auth global user attribute
newTimelineEvent.value.subject = i18n.t("recipe.user-made-this", { user: $auth.user.fullName })
// the user only selects the date, so we set the time to end of day local time
// we choose the end of day so it always comes after "new recipe" events
@@ -225,6 +233,7 @@ export default defineComponent({
...toRefs(state),
domMadeThisForm,
madeThisDialog,
firstDayOfWeek,
newTimelineEvent,
newTimelineEventImage,
newTimelineEventImagePreviewUrl,

View File

@@ -24,7 +24,7 @@
</div>
<div v-if="edit" class="d-flex justify-end">
<BaseButton class="ml-auto my-2" @click="addNote"> {{ $t("general.new") }}</BaseButton>
<BaseButton class="ml-auto my-2" @click="addNote"> {{ $t("general.add") }}</BaseButton>
</div>
</div>
</template>

View File

@@ -19,11 +19,11 @@
</div>
</v-card-text>
<v-list v-if="showViewer" dense class="mt-0 pt-0">
<v-list-item v-for="(item, key, index) in labels" :key="index" style="min-height: 25px" dense>
<v-list-item v-for="(item, key, index) in renderedList" :key="index" style="min-height: 25px" dense>
<v-list-item-content>
<v-list-item-title class="pl-4 caption flex row">
<div>{{ item.label }}</div>
<div class="ml-auto mr-1">{{ value[key] }}</div>
<div class="ml-auto mr-1">{{ item.value }}</div>
<div>{{ item.suffix }}</div>
</v-list-item-title>
</v-list-item-content>
@@ -37,6 +37,14 @@
import { computed, defineComponent, useContext } from "@nuxtjs/composition-api";
import { Nutrition } from "~/lib/api/types/recipe";
type NutritionLabelType = {
[key: string]: {
label: string;
suffix: string;
value?: string;
};
};
export default defineComponent({
props: {
value: {
@@ -50,34 +58,34 @@ export default defineComponent({
},
setup(props, context) {
const { i18n } = useContext();
const labels = {
const labels = <NutritionLabelType>{
calories: {
label: i18n.t("recipe.calories"),
suffix: i18n.t("recipe.calories-suffix"),
label: i18n.tc("recipe.calories"),
suffix: i18n.tc("recipe.calories-suffix"),
},
fatContent: {
label: i18n.t("recipe.fat-content"),
suffix: i18n.t("recipe.grams"),
label: i18n.tc("recipe.fat-content"),
suffix: i18n.tc("recipe.grams"),
},
fiberContent: {
label: i18n.t("recipe.fiber-content"),
suffix: i18n.t("recipe.grams"),
label: i18n.tc("recipe.fiber-content"),
suffix: i18n.tc("recipe.grams"),
},
proteinContent: {
label: i18n.t("recipe.protein-content"),
suffix: i18n.t("recipe.grams"),
label: i18n.tc("recipe.protein-content"),
suffix: i18n.tc("recipe.grams"),
},
sodiumContent: {
label: i18n.t("recipe.sodium-content"),
suffix: i18n.t("recipe.milligrams"),
label: i18n.tc("recipe.sodium-content"),
suffix: i18n.tc("recipe.milligrams"),
},
sugarContent: {
label: i18n.t("recipe.sugar-content"),
suffix: i18n.t("recipe.grams"),
label: i18n.tc("recipe.sugar-content"),
suffix: i18n.tc("recipe.grams"),
},
carbohydrateContent: {
label: i18n.t("recipe.carbohydrate-content"),
suffix: i18n.t("recipe.grams"),
label: i18n.tc("recipe.carbohydrate-content"),
suffix: i18n.tc("recipe.grams"),
},
};
const valueNotNull = computed(() => {
@@ -96,11 +104,25 @@ export default defineComponent({
context.emit("input", { ...props.value, [key]: event });
}
// Build a new list that only contains nutritional information that has a value
const renderedList = computed(() => {
return Object.entries(labels).reduce((item: NutritionLabelType, [key, label]) => {
if (props.value[key]?.trim()) {
item[key] = {
...label,
value: props.value[key],
};
}
return item;
}, {});
});
return {
labels,
valueNotNull,
showViewer,
updateValue,
renderedList,
};
},
});

View File

@@ -18,7 +18,7 @@
<BaseDialog v-if="updateTarget" v-model="dialogs.update" :title="$t('general.update')" @confirm="updateOne()">
<v-card-text>
<v-text-field v-model="updateTarget.name" label="$t('general.name')"> </v-text-field>
<v-text-field v-model="updateTarget.name" :label="$t('general.name')"> </v-text-field>
<v-checkbox v-if="itemType === Organizer.Tool" v-model="updateTarget.onHand" :label="$t('tool.on-hand')"></v-checkbox>
</v-card-text>
</BaseDialog>

View File

@@ -13,6 +13,9 @@
$globals.icons.tags"
return-object
v-bind="inputAttrs"
auto-select-first
:search-input.sync="searchInput"
@change="resetSearchInput"
>
<template #selection="data">
<v-chip
@@ -43,7 +46,7 @@
<script lang="ts">
import { defineComponent, ref, useContext, computed, onMounted } from "@nuxtjs/composition-api";
import RecipeOrganizerDialog from "./RecipeOrganizerDialog.vue";
import { RecipeCategory, RecipeTag } from "~/lib/api/types/user";
import { RecipeCategory, RecipeTag } from "~/lib/api/types/recipe";
import { RecipeTool } from "~/lib/api/types/admin";
import { useTagStore } from "~/composables/store/use-tag-store";
import { useCategoryStore, useToolStore } from "~/composables/store";
@@ -138,7 +141,6 @@ export default defineComponent({
}
function appendCreated(item: RecipeTag | RecipeCategory | RecipeTool) {
console.log(item);
if (selected.value === undefined) {
return;
}
@@ -148,6 +150,12 @@ export default defineComponent({
const dialog = ref(false);
const searchInput = ref("");
function resetSearchInput() {
searchInput.value = "";
}
return {
Organizer,
appendCreated,
@@ -156,6 +164,8 @@ export default defineComponent({
label,
selected,
removeByIndex,
searchInput,
resetSearchInput,
};
},
});

View File

@@ -51,7 +51,7 @@
/>
<div v-if="isEditForm" class="d-flex">
<RecipeDialogBulkAdd class="ml-auto my-2 mr-1" @bulk-data="addStep" />
<BaseButton class="my-2" @click="addStep()"> {{ $t("general.new") }}</BaseButton>
<BaseButton class="my-2" @click="addStep()"> {{ $t("general.add") }}</BaseButton>
</div>
<div v-if="!$vuetify.breakpoint.mdAndUp">
<RecipePageOrganizers :recipe="recipe" />
@@ -112,6 +112,7 @@ import { useUserApi } from "~/composables/api";
import { uuid4, deepCopy } from "~/composables/use-utils";
import RecipeDialogBulkAdd from "~/components/Domain/Recipe/RecipeDialogBulkAdd.vue";
import RecipeNotes from "~/components/Domain/Recipe/RecipeNotes.vue";
import { useNavigationWarning } from "~/composables/use-navigation-warning";
const EDITOR_OPTIONS = {
mode: "code",
@@ -151,6 +152,7 @@ export default defineComponent({
const api = useUserApi();
const { pageMode, editMode, setMode, isEditForm, isEditJSON, isCookMode, isEditMode, toggleCookMode } =
usePageState(props.recipe.slug);
const { deactivateNavigationWarning } = useNavigationWarning();
/** =============================================================
* Recipe Snapshot on Mount
@@ -175,6 +177,7 @@ export default defineComponent({
await api.recipes.updateOne(props.recipe.slug, props.recipe);
}
}
deactivateNavigationWarning();
});
/** =============================================================

View File

@@ -5,7 +5,7 @@
<v-card-text>
<v-card-title class="headline pa-0 flex-column align-center">
{{ recipe.name }}
<RecipeRating :key="recipe.slug" v-model="recipe.rating" :name="recipe.name" :slug="recipe.slug" />
<RecipeRating :key="recipe.slug" :value="recipe.rating" :recipe-id="recipe.id" :slug="recipe.slug" />
</v-card-title>
<v-divider class="my-2"></v-divider>
<SafeMarkdown :source="recipe.description" />

View File

@@ -47,7 +47,7 @@
<span>{{ parserToolTip }}</span>
</v-tooltip>
<RecipeDialogBulkAdd class="mx-1 mb-1" @bulk-data="addIngredient" />
<BaseButton class="mb-1" @click="addIngredient" > {{ $t("general.new") }} </BaseButton>
<BaseButton class="mb-1" @click="addIngredient" > {{ $t("general.add") }} </BaseButton>
</div>
</div>
</template>

View File

@@ -148,10 +148,6 @@
text: $tc('recipe.link-ingredients'),
event: 'link-ingredients',
},
{
text: $tc('recipe.merge-above'),
event: 'merge-above',
},
{
text: $tc('recipe.upload-image'),
event: 'upload-image'
@@ -160,11 +156,26 @@
icon: previewStates[index] ? $globals.icons.edit : $globals.icons.eye,
text: previewStates[index] ? $tc('recipe.edit-markdown') : $tc('markdown-editor.preview-markdown-button-label'),
event: 'preview-step',
divider: true,
},
{
text: $tc('recipe.merge-above'),
event: 'merge-above',
},
{
text: $tc('recipe.move-to-top'),
event: 'move-to-top',
},
{
text: $tc('recipe.move-to-bottom'),
event: 'move-to-bottom',
},
],
},
]"
@merge-above="mergeAbove(index - 1, index)"
@move-to-top="moveTo('top', index)"
@move-to-bottom="moveTo('bottom', index)"
@toggle-section="toggleShowTitle(step.id)"
@link-ingredients="openDialog(index, step.text, step.ingredientReferences)"
@preview-step="togglePreviewState(index)"
@@ -531,6 +542,14 @@ export default defineComponent({
}
}
function moveTo(dest: string, source: number) {
if (dest === "top") {
props.value.unshift(props.value.splice(source, 1)[0]);
} else {
props.value.push(props.value.splice(source, 1)[0]);
}
}
const previewStates = ref<boolean[]>([]);
function togglePreviewState(index: number) {
@@ -646,6 +665,7 @@ export default defineComponent({
getIngredientByRefId,
showTitleEditor,
mergeAbove,
moveTo,
openDialog,
setIngredientIds,
availableNextStep,

View File

@@ -20,7 +20,7 @@
v-if="landscape && $vuetify.breakpoint.smAndUp"
:key="recipe.slug"
v-model="recipe.rating"
:name="recipe.name"
:recipe-id="recipe.id"
:slug="recipe.slug"
/>
</div>

View File

@@ -24,7 +24,7 @@
v-if="$vuetify.breakpoint.smAndDown"
:key="recipe.slug"
v-model="recipe.rating"
:name="recipe.name"
:recipe-id="recipe.id"
:slug="recipe.slug"
/>
</div>

View File

@@ -1,34 +1,35 @@
<template>
<div @click.prevent>
<v-rating
v-model="rating"
:readonly="!isOwnGroup"
color="secondary"
background-color="secondary lighten-3"
length="5"
:dense="small ? true : undefined"
:size="small ? 15 : undefined"
hover
:value="value"
clearable
@input="updateRating"
@click="updateRating"
></v-rating>
<v-hover v-slot="{ hover }">
<v-rating
:value="rating.ratingValue"
:half-increments="(!hover) || (!isOwnGroup)"
:readonly="!isOwnGroup"
:color="hover ? attrs.hoverColor : attrs.color"
:background-color="attrs.backgroundColor"
length="5"
:dense="small ? true : undefined"
:size="small ? 15 : undefined"
hover
clearable
@input="updateRating"
@click="updateRating"
/>
</v-hover>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "@nuxtjs/composition-api";
import { computed, defineComponent, ref, useContext, watch } from "@nuxtjs/composition-api";
import { useLoggedInState } from "~/composables/use-logged-in-state";
import { useUserApi } from "~/composables/api";
import { useUserSelfRatings } from "~/composables/use-users";
export default defineComponent({
props: {
emitOnly: {
type: Boolean,
default: false,
},
// TODO Remove name prop?
name: {
recipeId: {
type: String,
default: "",
},
@@ -44,26 +45,79 @@ export default defineComponent({
type: Boolean,
default: false,
},
preferGroupRating: {
type: Boolean,
default: false,
},
},
setup(props, context) {
const { $auth } = useContext();
const { isOwnGroup } = useLoggedInState();
const { userRatings, setRating, ready: ratingsLoaded } = useUserSelfRatings();
const hideGroupRating = ref(false);
const rating = ref(props.value);
type Rating = {
ratingValue: number | undefined;
hasUserRating: boolean | undefined
};
const api = useUserApi();
function updateRating(val: number | null) {
if (val === 0) {
val = null;
// prefer user rating over group rating
const rating = computed<Rating>(() => {
if (!ratingsLoaded.value) {
return { ratingValue: undefined, hasUserRating: undefined };
}
if (!($auth.user?.id) || props.preferGroupRating) {
return { ratingValue: props.value, hasUserRating: false };
}
const userRating = userRatings.value.find((r) => r.recipeId === props.recipeId);
return {
ratingValue: userRating?.rating || (hideGroupRating.value ? 0 : props.value),
hasUserRating: !!userRating?.rating
};
});
// if a user unsets their rating, we don't want to fall back to the group rating since it's out of sync
watch(
() => rating.value.hasUserRating,
() => {
if (rating.value.hasUserRating && !props.preferGroupRating) {
hideGroupRating.value = true;
}
},
)
const attrs = computed(() => {
return isOwnGroup.value ? {
// Logged-in user
color: rating.value.hasUserRating ? "secondary" : "grey darken-1",
hoverColor: "secondary",
backgroundColor: "secondary lighten-3",
} : {
// Anonymous user
color: "secondary",
hoverColor: "secondary",
backgroundColor: "secondary lighten-3",
};
})
function updateRating(val: number | null) {
if (!isOwnGroup.value) {
return;
}
if (!props.emitOnly) {
api.recipes.patchOne(props.slug, {
rating: val,
});
setRating(props.slug, val || 0, null);
}
context.emit("input", val);
}
return { isOwnGroup, rating, updateRating };
return {
attrs,
isOwnGroup,
rating,
updateRating,
};
},
});
</script>

View File

@@ -3,9 +3,53 @@
<v-row class="my-0 mx-7">
<v-spacer />
<v-col class="text-right">
<v-btn fab small color="info" @click="reverseSort">
<v-icon> {{ preferences.orderDirection === "asc" ? $globals.icons.sortCalendarAscending : $globals.icons.sortCalendarDescending }} </v-icon>
</v-btn>
<!-- Filters -->
<v-menu offset-y bottom left nudge-bottom="3" :close-on-content-click="false">
<template #activator="{ on, attrs }">
<v-badge :content="filterBadgeCount" :value="filterBadgeCount" bordered overlap>
<v-btn fab small color="info" v-bind="attrs" v-on="on">
<v-icon> {{ $globals.icons.filter }} </v-icon>
</v-btn>
</v-badge>
</template>
<v-card>
<v-list>
<v-list-item @click="reverseSort">
<v-icon left>
{{
preferences.orderDirection === "asc" ?
$globals.icons.sortCalendarDescending : $globals.icons.sortCalendarAscending
}}
</v-icon>
<v-list-item-title>
{{ preferences.orderDirection === "asc" ? $tc("general.sort-descending") : $tc("general.sort-ascending") }}
</v-list-item-title>
</v-list-item>
<v-divider />
<v-list-item class="pa-0">
<v-list class="py-0" style="width: 100%;">
<v-list-item
v-for="option, idx in eventTypeFilterState"
:key="idx"
>
<v-checkbox
:input-value="option.checked"
readonly
@click="toggleEventTypeOption(option.value)"
>
<template #label>
<v-icon left>
{{ option.icon }}
</v-icon>
{{ option.label }}
</template>
</v-checkbox>
</v-list-item>
</v-list>
</v-list-item>
</v-list>
</v-card>
</v-menu>
</v-col>
</v-row>
<v-divider class="mx-2"/>
@@ -29,9 +73,9 @@
/>
</v-timeline>
</div>
<v-card v-else-if="!loading">
<v-card v-else-if="!loading" class="mt-2">
<v-card-title class="justify-center pa-9">
{{ $t("recipe.timeline-is-empty") }}
{{ $t("recipe.timeline-no-events-found-try-adjusting-filters") }}
</v-card-title>
</v-card>
<div v-if="loading" class="mb-3 text-center">
@@ -41,14 +85,15 @@
</template>
<script lang="ts">
import { defineComponent, onMounted, ref, useAsync, useContext } from "@nuxtjs/composition-api";
import { computed, defineComponent, onMounted, ref, useAsync, useContext } from "@nuxtjs/composition-api";
import { useThrottleFn, whenever } from "@vueuse/core";
import RecipeTimelineItem from "./RecipeTimelineItem.vue"
import { useTimelinePreferences } from "~/composables/use-users/preferences";
import { useTimelineEventTypes } from "~/composables/recipes/use-recipe-timeline-events";
import { useAsyncKey } from "~/composables/use-utils";
import { alert } from "~/composables/use-toast";
import { useUserApi } from "~/composables/api";
import { Recipe, RecipeTimelineEventOut, RecipeTimelineEventUpdate } from "~/lib/api/types/recipe"
import { Recipe, RecipeTimelineEventOut, RecipeTimelineEventUpdate, TimelineEventType } from "~/lib/api/types/recipe";
export default defineComponent({
components: { RecipeTimelineItem },
@@ -76,6 +121,7 @@ export default defineComponent({
const api = useUserApi();
const { i18n } = useContext();
const preferences = useTimelinePreferences();
const { eventTypeOptions } = useTimelineEventTypes();
const loading = ref(true);
const ready = ref(false);
@@ -85,6 +131,15 @@ export default defineComponent({
const timelineEvents = ref([] as RecipeTimelineEventOut[]);
const recipes = new Map<string, Recipe>();
const filterBadgeCount = computed(() => eventTypeOptions.value.length - preferences.value.types.length);
const eventTypeFilterState = computed(() => {
return eventTypeOptions.value.map(option => {
return {
...option,
checked: preferences.value.types.includes(option.value),
}
});
});
interface ScrollEvent extends Event {
target: HTMLInputElement;
@@ -112,7 +167,7 @@ export default defineComponent({
}
);
// Sorting
// Preferences
function reverseSort() {
if (loading.value) {
return;
@@ -122,6 +177,21 @@ export default defineComponent({
initializeTimelineEvents();
}
function toggleEventTypeOption(option: TimelineEventType) {
if (loading.value) {
return;
}
const index = preferences.value.types.indexOf(option);
if (index === -1) {
preferences.value.types.push(option);
} else {
preferences.value.types.splice(index, 1);
}
initializeTimelineEvents();
}
// Timeline Actions
async function updateTimelineEvent(index: number) {
const event = timelineEvents.value[index]
@@ -179,8 +249,11 @@ export default defineComponent({
async function scrollTimelineEvents() {
const orderBy = "timestamp";
const orderDirection = preferences.value.orderDirection === "asc" ? "asc" : "desc";
// eslint-disable-next-line quotes
const eventTypeValue = `["${preferences.value.types.join('", "')}"]`;
const queryFilter = `(${props.queryFilter}) AND eventType IN ${eventTypeValue}`
const response = await api.recipes.getAllTimelineEvents(page.value, perPage, { orderBy, orderDirection, queryFilter: props.queryFilter });
const response = await api.recipes.getAllTimelineEvents(page.value, perPage, { orderBy, orderDirection, queryFilter });
page.value += 1;
if (!response?.data) {
return;
@@ -256,11 +329,14 @@ export default defineComponent({
return {
deleteTimelineEvent,
filterBadgeCount,
loading,
onScroll,
preferences,
eventTypeFilterState,
recipes,
reverseSort,
toggleEventTypeOption,
timelineEvents,
updateTimelineEvent,
};

View File

@@ -99,6 +99,7 @@ import { computed, defineComponent, ref, useContext, useRoute } from "@nuxtjs/co
import RecipeCardMobile from "./RecipeCardMobile.vue";
import RecipeTimelineContextMenu from "./RecipeTimelineContextMenu.vue";
import { useStaticRoutes } from "~/composables/api";
import { useTimelineEventTypes } from "~/composables/recipes/use-recipe-timeline-events";
import { Recipe, RecipeTimelineEventOut } from "~/lib/api/types/recipe"
import UserAvatar from "~/components/Domain/User/UserAvatar.vue";
import SafeMarkdown from "~/components/global/SafeMarkdown.vue";
@@ -124,6 +125,7 @@ export default defineComponent({
setup(props) {
const { $auth, $globals, $vuetify } = useContext();
const { recipeTimelineEventImage } = useStaticRoutes();
const { eventTypeOptions } = useTimelineEventTypes();
const timelineEvents = ref([] as RecipeTimelineEventOut[]);
const route = useRoute();
@@ -164,21 +166,10 @@ export default defineComponent({
}
})
const icon = computed( () => {
switch (props.event.eventType) {
case "comment":
return $globals.icons.commentTextMultiple;
case "info":
return $globals.icons.informationVariant;
case "system":
return $globals.icons.cog;
default:
return $globals.icons.informationVariant;
};
})
const icon = computed(() => {
const option = eventTypeOptions.value.find((option) => option.value === props.event.eventType);
return option ? option.icon : $globals.icons.informationVariant;
});
const hideImage = ref(false);
const eventImageUrl = computed<string>( () => {

View File

@@ -25,6 +25,7 @@
:label="$t('shopping-list.note')"
rows="1"
auto-grow
@keypress="handleNoteKeyPress"
></v-textarea>
</div>
<div class="d-flex align-end" style="gap: 20px">
@@ -95,7 +96,7 @@
</template>
<script lang="ts">
import { defineComponent, computed } from "@nuxtjs/composition-api";
import { defineComponent, computed, watch } from "@nuxtjs/composition-api";
import { ShoppingListItemCreate, ShoppingListItemOut } from "~/lib/api/types/group";
import { MultiPurposeLabelOut } from "~/lib/api/types/labels";
import { IngredientFood, IngredientUnit } from "~/lib/api/types/recipe";
@@ -128,9 +129,28 @@ export default defineComponent({
context.emit("input", val);
},
});
watch(
() => props.value.food,
(newFood) => {
// @ts-ignore our logic already assumes there's a label attribute, even if TS doesn't think there is
listItem.value.label = newFood?.label || null;
listItem.value.labelId = listItem.value.label?.id || null;
}
);
return {
listItem,
};
},
methods: {
handleNoteKeyPress(event) {
// Save on Enter
if (!event.shiftKey && event.key === "Enter") {
event.preventDefault();
this.$emit("save");
}
},
}
});
</script>

View File

@@ -0,0 +1,160 @@
<template>
<div>
<v-card-title>
<v-icon large class="mr-3"> {{ $globals.icons.user }}</v-icon>
<span class="headline"> {{ $t("user-registration.account-details") }}</span>
</v-card-title>
<v-divider />
<v-card-text>
<v-form ref="domAccountForm" @submit.prevent>
<v-text-field
v-model="accountDetails.username.value"
autofocus
v-bind="inputAttrs"
:label="$tc('user.username')"
:prepend-icon="$globals.icons.user"
:rules="[validators.required]"
:error-messages="usernameErrorMessages"
@blur="validateUsername"
/>
<v-text-field
v-model="accountDetails.fullName.value"
v-bind="inputAttrs"
:label="$tc('user.full-name')"
:prepend-icon="$globals.icons.user"
:rules="[validators.required]"
/>
<v-text-field
v-model="accountDetails.email.value"
v-bind="inputAttrs"
:prepend-icon="$globals.icons.email"
:label="$tc('user.email')"
:rules="[validators.required, validators.email]"
:error-messages="emailErrorMessages"
@blur="validateEmail"
/>
<v-text-field
v-model="credentials.password1.value"
v-bind="inputAttrs"
:type="pwFields.inputType.value"
:append-icon="pwFields.passwordIcon.value"
:prepend-icon="$globals.icons.lock"
:label="$tc('user.password')"
:rules="[validators.required, validators.minLength(8), validators.maxLength(258)]"
@click:append="pwFields.togglePasswordShow"
/>
<UserPasswordStrength :value="credentials.password1.value" />
<v-text-field
v-model="credentials.password2.value"
v-bind="inputAttrs"
:type="pwFields.inputType.value"
:append-icon="pwFields.passwordIcon.value"
:prepend-icon="$globals.icons.lock"
:label="$tc('user.confirm-password')"
:rules="[validators.required, credentials.passwordMatch]"
@click:append="pwFields.togglePasswordShow"
/>
<div class="px-2">
<v-checkbox
v-model="accountDetails.advancedOptions.value"
:label="$tc('user.enable-advanced-content')"
/>
<p class="text-caption mt-n4">
{{ $tc("user.enable-advanced-content-description") }}
</p>
</div>
</v-form>
</v-card-text>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "@nuxtjs/composition-api";
import { useDark } from "@vueuse/core";
import { validators } from "~/composables/use-validators";
import { useUserRegistrationForm } from "~/composables/use-users/user-registration-form";
import { usePasswordField } from "~/composables/use-passwords";
import UserPasswordStrength from "~/components/Domain/User/UserPasswordStrength.vue";
const inputAttrs = {
filled: true,
rounded: true,
validateOnBlur: true,
class: "rounded-lg",
};
export default defineComponent({
components: { UserPasswordStrength },
layout: "blank",
setup() {
const isDark = useDark();
const langDialog = ref(false);
const pwFields = usePasswordField();
const {
accountDetails,
credentials,
emailErrorMessages,
usernameErrorMessages,
validateUsername,
validateEmail,
domAccountForm,
} = useUserRegistrationForm();
return {
accountDetails,
credentials,
emailErrorMessages,
inputAttrs,
isDark,
langDialog,
pwFields,
usernameErrorMessages,
validators,
// Validators
validateUsername,
validateEmail,
// Dom Refs
domAccountForm,
};
},
});
</script>
<style lang="css" scoped>
.icon-primary {
fill: var(--v-primary-base);
}
.icon-white {
fill: white;
}
.icon-container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
position: relative;
margin-top: 2.5rem;
}
.icon-divider {
width: 100%;
margin-bottom: -2.5rem;
}
.icon-avatar {
border-color: rgba(0, 0, 0, 0.12);
border: 2px;
}
.bg-off-white {
background: #f5f8fa;
}
.preferred-width {
width: 840px;
}
</style>

View File

@@ -6,8 +6,6 @@
v-model="sidebar"
absolute
:top-link="topLinks"
:secondary-header="cookbookLinks.length ? $tc('sidebar.cookbooks') : undefined"
:secondary-header-link="isOwnGroup && cookbookLinks.length ? `/g/${groupSlug}/cookbooks` : undefined"
:secondary-links="cookbookLinks || []"
:bottom-links="isAdmin ? bottomLinks : []"
>
@@ -146,14 +144,6 @@
to: `/g/${groupSlug.value}/r/create/new`,
restricted: true,
},
{
insertDivider: true,
icon: $globals.icons.pages,
title: i18n.tc("sidebar.cookbook"),
subtitle: i18n.tc("sidebar.create-cookbook"),
to: `/g/${groupSlug.value}/cookbooks`,
restricted: true,
},
]);
const bottomLinks = computed<SidebarLinks>(() => [
@@ -191,22 +181,35 @@
restricted: true,
},
{
icon: $globals.icons.categories,
to: `/g/${groupSlug.value}/recipes/categories`,
title: i18n.tc("sidebar.categories"),
icon: $globals.icons.book,
to: `/g/${groupSlug.value}/cookbooks`,
title: i18n.tc("cookbook.cookbooks"),
restricted: true,
},
{
icon: $globals.icons.tags,
to: `/g/${groupSlug.value}/recipes/tags`,
title: i18n.tc("sidebar.tags"),
restricted: true,
},
{
icon: $globals.icons.potSteam,
to: `/g/${groupSlug.value}/recipes/tools`,
title: i18n.tc("tool.tools"),
icon: $globals.icons.organizers,
title: i18n.tc("general.organizers"),
restricted: true,
children: [
{
icon: $globals.icons.categories,
to: `/g/${groupSlug.value}/recipes/categories`,
title: i18n.tc("sidebar.categories"),
restricted: true,
},
{
icon: $globals.icons.tags,
to: `/g/${groupSlug.value}/recipes/tags`,
title: i18n.tc("sidebar.tags"),
restricted: true,
},
{
icon: $globals.icons.potSteam,
to: `/g/${groupSlug.value}/recipes/tools`,
title: i18n.tc("tool.tools"),
restricted: true,
},
],
},
]);

View File

@@ -39,13 +39,12 @@
<v-list-item-title>{{ nav.title }}</v-list-item-title>
</template>
<v-list-item v-for="child in nav.children" :key="child.title" exact :to="child.to">
<v-list-item v-for="child in nav.children" :key="child.title" exact :to="child.to" class="ml-2">
<v-list-item-icon>
<v-icon>{{ child.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-title>{{ child.title }}</v-list-item-title>
</v-list-item>
<v-divider class="mb-4"></v-divider>
</v-list-group>
<!-- Single Item -->
@@ -68,18 +67,8 @@
</template>
<!-- Secondary Links -->
<template v-if="secondaryLinks">
<router-link v-if="secondaryHeader && secondaryHeaderLink" :to="secondaryHeaderLink" style="text-decoration: none;">
<v-subheader :to="secondaryHeaderLink" class="pb-0">
{{ secondaryHeader }}
</v-subheader>
</router-link>
<div v-else-if="secondaryHeader">
<v-subheader :to="secondaryHeaderLink" class="pb-0">
{{ secondaryHeader }}
</v-subheader>
</div>
<v-divider v-if="secondaryHeader"></v-divider>
<template v-if="secondaryLinks.length > 0">
<v-divider class="mt-2"></v-divider>
<v-list nav dense exact>
<template v-for="nav in secondaryLinks">
<div v-if="!nav.restricted || isOwnGroup" :key="nav.title">
@@ -179,14 +168,6 @@ export default defineComponent({
required: false,
default: null,
},
secondaryHeader: {
type: String,
default: null,
},
secondaryHeaderLink: {
type: String,
default: null,
},
},
setup(props, context) {
// V-Model Support

View File

@@ -15,12 +15,22 @@
v-if="inputField.type === fieldTypes.BOOLEAN"
v-model="value[inputField.varName]"
class="my-0 py-0"
:label="inputField.label"
:name="inputField.varName"
:hint="inputField.hint || ''"
:disabled="(inputField.disableUpdate && updateMode) || (!updateMode && inputField.disableCreate) || (disabledFields && disabledFields.includes(inputField.varName))"
@change="emitBlur"
/>
>
<template #label>
<div>
<v-card-text class="text-body-1 my-0 py-0">
{{ inputField.label }}
</v-card-text>
<v-card-text v-if="inputField.hint" class="text-caption my-0 py-0">
{{ inputField.hint }}
</v-card-text>
</div>
</template>
</v-checkbox>
<!-- Text Field -->
<v-text-field

View File

@@ -10,9 +10,12 @@
</v-btn>
</template>
<v-list dense>
<v-list-item v-for="(child, idx) in btn.children" :key="idx" dense @click="$emit(child.event)">
<v-list-item-title>{{ child.text }}</v-list-item-title>
</v-list-item>
<template v-for="(child, idx) in btn.children">
<v-list-item :key="idx" dense @click="$emit(child.event)">
<v-list-item-title>{{ child.text }}</v-list-item-title>
</v-list-item>
<v-divider v-if="child.divider" :key="`divider-${idx}`" class="my-1"></v-divider>
</template>
</v-list>
</v-menu>
<v-tooltip
@@ -55,6 +58,7 @@ export interface ButtonOption {
event: string;
children?: ButtonOption[];
disabled?: boolean;
divider?: boolean;
}
export default defineComponent({

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