Merge branch 'mealie-next' into fix/translation-issues-when-scraping

This commit is contained in:
Michael Genson 2023-12-11 13:01:26 -06:00 committed by GitHub
commit 449eeb0d53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 505 additions and 672 deletions

View File

@ -41,7 +41,8 @@
// Use 'forwardPorts' to make a list of ports inside the container available locally. // Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [ "forwardPorts": [
3000, 3000,
9000 9000,
24678 // used by nuxt when hot-reloading using polling
], ],
// Use 'onCreateCommand' to run commands at the end of container creation. // Use 'onCreateCommand' to run commands at the end of container creation.
// Use 'postCreateCommand' to run commands after the container is created. // Use 'postCreateCommand' to run commands after the container is created.

View File

@ -1,7 +1,7 @@
--- ---
name: Bug Report name: Bug Report
description: "Submit a bug for the latest version of Mealie" description: "Submit a bug for the latest version of Mealie"
title: "[BUG] - YOUR TITLE" title: "[BUG] - YOUR DESCRIPTIVE TITLE GOES HERE"
labels: ["bug", "triage"] labels: ["bug", "triage"]
body: body:
- type: checkboxes - type: checkboxes
@ -14,7 +14,7 @@ body:
options: options:
- label: This is not a feature request. - label: This is not a feature request.
required: true required: true
- label: I added a very descriptive title to this issue. - label: I added a very descriptive title to this issue (title field is above this).
required: true required: true
- label: I used the GitHub search to find a similar issue and didn't find it. - label: I used the GitHub search to find a similar issue and didn't find it.
required: true required: true
@ -61,7 +61,8 @@ body:
- Docker (Windows) - Docker (Windows)
- Docker (Synology) - Docker (Synology)
- Unraid - Unraid
- Other - TrueNAS
- Other (please specify below)
validations: validations:
required: true required: true
- type: textarea - type: textarea

View File

@ -36,7 +36,7 @@ jobs:
# Steps # Steps
steps: steps:
- name: Check out repository - name: Check out repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up python - name: Set up python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
@ -60,7 +60,7 @@ jobs:
id: cache-validate id: cache-validate
if: steps.cached-poetry-dependencies.outputs.cache-hit == 'true' if: steps.cached-poetry-dependencies.outputs.cache-hit == 'true'
run: | run: |
echo "import black;print('venv good?')" > test.py && poetry run python test.py && echo ::set-output name=cache-hit-success::true echo "import black;print('venv good?')" > test.py && poetry run python test.py && echo "cache-hit-success=true" >> $GITHUB_OUTPUT
rm test.py rm test.py
continue-on-error: true continue-on-error: true

View File

@ -20,26 +20,26 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Log in to the Container registry (ghcr.io) - name: Log in to the Container registry (ghcr.io)
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to the Container registry (dockerhub) - name: Log in to the Container registry (dockerhub)
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
- name: Override __init__.py - name: Override __init__.py
run: | run: |

View File

@ -9,20 +9,20 @@ jobs:
steps: steps:
- name: Checkout 🛎 - name: Checkout 🛎
uses: actions/checkout@master uses: actions/checkout@v4
- name: Setup node env 🏗 - name: Setup node env 🏗
uses: actions/setup-node@v3.7.0 uses: actions/setup-node@v4.0.0
with: with:
node-version: 16 node-version: 16
check-latest: true check-latest: true
- name: Get yarn cache directory path 🛠 - name: Get yarn cache directory path 🛠
id: yarn-cache-dir-path id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)" run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
- name: Cache node_modules 📦 - name: Cache node_modules 📦
uses: actions/cache@v3.3.1 uses: actions/cache@v3.3.2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with: with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }} path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@ -47,20 +47,20 @@ jobs:
steps: steps:
- name: Checkout 🛎 - name: Checkout 🛎
uses: actions/checkout@master uses: actions/checkout@v4
- name: Setup node env 🏗 - name: Setup node env 🏗
uses: actions/setup-node@v3.7.0 uses: actions/setup-node@v4.0.0
with: with:
node-version: 16 node-version: 16
check-latest: true check-latest: true
- name: Get yarn cache directory path 🛠 - name: Get yarn cache directory path 🛠
id: yarn-cache-dir-path id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)" run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
- name: Cache node_modules 📦 - name: Cache node_modules 📦
uses: actions/cache@v3.3.1 uses: actions/cache@v3.3.2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with: with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }} path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

@ -11,7 +11,7 @@ jobs:
fail-fast: true fail-fast: true
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Build Dockerfile - name: Build Dockerfile
run: | run: |

View File

@ -14,8 +14,8 @@
"webp" "webp"
], ],
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": true, "source.fixAll.eslint": "explicit",
"source.organizeImports": false "source.organizeImports": "never"
}, },
"editor.formatOnSave": true, "editor.formatOnSave": true,
"eslint.workingDirectories": [ "eslint.workingDirectories": [

View File

@ -9,7 +9,7 @@
<!-- PROJECT LOGO --> <!-- PROJECT LOGO -->
<br /> <br />
<p align="center"> <p align="center">
<a href="https://github.com/hay-kot/mealie"> <a href="https://github.com/mealie-recipes/mealie">
<svg style="width:100px;height:100px" viewBox="0 0 24 24"> <svg style="width:100px;height:100px" viewBox="0 0 24 24">
<path fill="currentColor" d="M8.1,13.34L3.91,9.16C2.35,7.59 2.35,5.06 3.91,3.5L10.93,10.5L8.1,13.34M13.41,13L20.29,19.88L18.88,21.29L12,14.41L5.12,21.29L3.71,19.88L13.36,10.22L13.16,10C12.38,9.23 12.38,7.97 13.16,7.19L17.5,2.82L18.43,3.74L15.19,7L16.15,7.94L19.39,4.69L20.31,5.61L17.06,8.85L18,9.81L21.26,6.56L22.18,7.5L17.81,11.84C17.03,12.62 15.77,12.62 15,11.84L14.78,11.64L13.41,13Z" /> <path fill="currentColor" d="M8.1,13.34L3.91,9.16C2.35,7.59 2.35,5.06 3.91,3.5L10.93,10.5L8.1,13.34M13.41,13L20.29,19.88L18.88,21.29L12,14.41L5.12,21.29L3.71,19.88L13.36,10.22L13.16,10C12.38,9.23 12.38,7.97 13.16,7.19L17.5,2.82L18.43,3.74L15.19,7L16.15,7.94L19.39,4.69L20.31,5.61L17.06,8.85L18,9.81L21.26,6.56L22.18,7.5L17.81,11.84C17.03,12.62 15.77,12.62 15,11.84L14.78,11.64L13.41,13Z" />
</svg> </svg>
@ -21,12 +21,12 @@
A Place for All Your Recipes A Place for All Your Recipes
<br /> <br />
<a href="https://nightly.mealie.io"><strong>Explore the docs »</strong></a> <a href="https://nightly.mealie.io"><strong>Explore the docs »</strong></a>
<a href="https://github.com/hay-kot/mealie"> <a href="https://github.com/mealie-recipes/mealie">
</a> </a>
<br /> <br />
<a href="https://demo.mealie.io/">View Demo</a> <a href="https://demo.mealie.io/">View Demo</a>
· ·
<a href="https://github.com/hay-kot/mealie/issues">Report Bug</a> <a href="https://github.com/mealie-recipes/mealie/issues">Report Bug</a>
· ·
<a href="https://github.com/mealie-recipes/mealie/pkgs/container/mealie">GitHub Container Registry</a> <a href="https://github.com/mealie-recipes/mealie/pkgs/container/mealie">GitHub Container Registry</a>
</p> </p>
@ -76,17 +76,17 @@ Thanks to Linode for providing Hosting for the Demo, Beta, and Documentation sit
<!-- MARKDOWN LINKS & IMAGES --> <!-- MARKDOWN LINKS & IMAGES -->
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links --> <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
[contributors-shield]: https://img.shields.io/github/contributors/hay-kot/mealie.svg?style=flat-square [contributors-shield]: https://img.shields.io/github/contributors/mealie-recipes/mealie.svg?style=flat-square
[docker-pull]: https://img.shields.io/docker/pulls/hkotel/mealie [docker-pull]: https://img.shields.io/docker/pulls/hkotel/mealie
[contributors-url]: https://github.com/hay-kot/mealie/graphs/contributors [contributors-url]: https://github.com/mealie-recipes/mealie/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/hay-kot/mealie.svg?style=flat-square [forks-shield]: https://img.shields.io/github/forks/mealie-recipes/mealie.svg?style=flat-square
[forks-url]: https://github.com/hay-kot/mealie/network/members [forks-url]: https://github.com/mealie-recipes/mealie/network/members
[stars-shield]: https://img.shields.io/github/stars/hay-kot/mealie.svg?style=flat-square [stars-shield]: https://img.shields.io/github/stars/mealie-recipes/mealie.svg?style=flat-square
[stars-url]: https://github.com/hay-kot/mealie/stargazers [stars-url]: https://github.com/mealie-recipes/mealie/stargazers
[issues-shield]: https://img.shields.io/github/issues/hay-kot/mealie.svg?style=flat-square [issues-shield]: https://img.shields.io/github/issues/mealie-recipes/mealie.svg?style=flat-square
[issues-url]: https://github.com/hay-kot/mealie/issues [issues-url]: https://github.com/mealie-recipes/mealie/issues
[license-shield]: https://img.shields.io/github/license/hay-kot/mealie.svg?style=flat-square [license-shield]: https://img.shields.io/github/license/mealie-recipes/mealie.svg?style=flat-square
[license-url]: https://github.com/hay-kot/mealie/blob/mealie-next/LICENSE [license-url]: https://github.com/mealie-recipes/mealie/blob/mealie-next/LICENSE
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555 [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555
[linkedin-url]: https://linkedin.com/in/hay-kot [linkedin-url]: https://linkedin.com/in/hay-kot
[product-screenshot]: docs/docs/assets/img/home_screenshot.png [product-screenshot]: docs/docs/assets/img/home_screenshot.png

View File

@ -62,7 +62,7 @@ A quality update with major props to [zackbcom](https://github.com/zackbcom) for
### Recipes ### Recipes
- Added user feedback on bad URL - Added user feedback on bad URL
- Better backend data validation for updating recipes, avoid small syntax errors corrupting database entry. [Closes #8](https://github.com/hay-kot/mealie/issues/8) - Better backend data validation for updating recipes, avoid small syntax errors corrupting database entry. [Closes #8](https://github.com/mealie-recipes/mealie/issues/8)
- Fixed spacing Closes while editing new recipes in JSON - Fixed spacing Closes while editing new recipes in JSON
## v0.0.0 - Initial Pre-release ## v0.0.0 - Initial Pre-release

View File

@ -5,7 +5,7 @@
**Database Version: v0.4.0** **Database Version: v0.4.0**
!!! error "Breaking Changes" !!! error "Breaking Changes"
1. With a recent refactor some users been experiencing issues with an environmental variable not being set correct. If you are experiencing issues, please provide your comments [Here](https://github.com/hay-kot/mealie/issues/281). 1. With a recent refactor some users been experiencing issues with an environmental variable not being set correct. If you are experiencing issues, please provide your comments [Here](https://github.com/mealie-recipes/mealie/issues/281).
2. If you are a developer, you may experience issues with development as a new environmental variable has been introduced. Setting `PRODUCTION=false` will allow you to develop as normal. 2. If you are a developer, you may experience issues with development as a new environmental variable has been introduced. Setting `PRODUCTION=false` will allow you to develop as normal.
@ -31,4 +31,4 @@
- Unify Logger across the backend - Unify Logger across the backend
- mealie.log and last_recipe.json are now downloadable from the frontend from the /admin/about - mealie.log and last_recipe.json are now downloadable from the frontend from the /admin/about
- New download schema where you request a token and then use that token to hit a single endpoint to download a file. This is a notable change if you are using the API to download backups. - New download schema where you request a token and then use that token to hit a single endpoint to download a file. This is a notable change if you are using the API to download backups.
- Recipe images can now be added directly from a URL - [See #117 for details](https://github.com/hay-kot/mealie/issues/117) - Recipe images can now be added directly from a URL - [See #117 for details](https://github.com/mealie-recipes/mealie/issues/117)

View File

@ -8,7 +8,7 @@
- Fixed #617 - Section behavior when adding a step - Fixed #617 - Section behavior when adding a step
- Fixed #615 - Recipe Settings are not available when creating new recipe - Fixed #615 - Recipe Settings are not available when creating new recipe
- Fixed #625 - API of today's image returns strange characters - Fixed #625 - API of today's image returns strange characters
- Fixed [#590](https://github.com/hay-kot/mealie/issues/590) - Duplicate Events when using Gunicorn Workers - Fixed [#590](https://github.com/mealie-recipes/mealie/issues/590) - Duplicate Events when using Gunicorn Workers
## Features and Improvements ## Features and Improvements

View File

@ -6,14 +6,14 @@
- FastAPI to 0.78.0 - FastAPI to 0.78.0
- Recipe Ingredient Editor - Recipe Ingredient Editor
- [#1140](https://github.com/hay-kot/mealie/issues/1140) - Error in processing the quantity of ingredients #1140 - UI Now prevents entering not-allowed characters in quantity field - [#1140](https://github.com/mealie-recipes/mealie/issues/1140) - Error in processing the quantity of ingredients #1140 - UI Now prevents entering not-allowed characters in quantity field
- UI now allows no value to be set in addition to a zero (0) value. - UI now allows no value to be set in addition to a zero (0) value.
- [#1237](https://github.com/hay-kot/mealie/issues/1237) - UI: Saving a 0 quantity ingredient displays 0 until the page is refreshed #1237 - UI Now properly reacts to changes in the quantity field. - [#1237](https://github.com/mealie-recipes/mealie/issues/1237) - UI: Saving a 0 quantity ingredient displays 0 until the page is refreshed #1237 - UI Now properly reacts to changes in the quantity field.
- Fix Mealie v0.5.x migration issue [#1183](https://github.com/hay-kot/mealie/issues/1183) - Fix Mealie v0.5.x migration issue [#1183](https://github.com/mealie-recipes/mealie/issues/1183)
- Consolidated Frontend Types thanks to [@PFischbeck](https://github.com/Fischbeck) - Consolidated Frontend Types thanks to [@PFischbeck](https://github.com/Fischbeck)
- Added support for SSL/No Auth Email [@nkringle](https://github.com/nkringle) - Added support for SSL/No Auth Email [@nkringle](https://github.com/nkringle)
- [Implement several notifications for server actions ](https://github.com/hay-kot/mealie/pull/1234)[@miroito](https://github.com/Miroito) - [Implement several notifications for server actions ](https://github.com/mealie-recipes/mealie/pull/1234)[@miroito](https://github.com/Miroito)
- Fix display issue for shared recipe rendering on server [@PFischbeck](https://github.com/Fischbeck) - Fix display issue for shared recipe rendering on server [@PFischbeck](https://github.com/Fischbeck)
## v1.0.0b - 2022-05-09 ## v1.0.0b - 2022-05-09
@ -36,7 +36,7 @@
- Mealie now stores the original text from parsed ingredients, with the ability to peak at the original text from a recipe. [@miroito](https://github.com/Miroito) - Mealie now stores the original text from parsed ingredients, with the ability to peak at the original text from a recipe. [@miroito](https://github.com/Miroito)
- Added some management / utility functions for administrators to manage data and cleanup artifacts from the file system. - Added some management / utility functions for administrators to manage data and cleanup artifacts from the file system.
- Fix clear url action in recipe creation [#1101](https://github.com/hay-kot/mealie/pull/1101) [@miroito](https://github.com/Miroito) - Fix clear url action in recipe creation [#1101](https://github.com/mealie-recipes/mealie/pull/1101) [@miroito](https://github.com/Miroito)
- Add group statistics calculations and data storage measurements - Add group statistics calculations and data storage measurements
- No hard limits are currently imposed on groups - though this may be implemented in the future. - No hard limits are currently imposed on groups - though this may be implemented in the future.

View File

@ -1,29 +1,29 @@
### Bug Fixes ### Bug Fixes
- Bump isomorphic-dompurify from 0.18.0 to 0.19.0 in /frontend ([#1257](https://github.com/hay-kot/mealie/issues/1257)) - Bump isomorphic-dompurify from 0.18.0 to 0.19.0 in /frontend ([#1257](https://github.com/mealie-recipes/mealie/issues/1257))
- Bump @nuxtjs/auth-next in /frontend ([#1265](https://github.com/hay-kot/mealie/issues/1265)) - Bump @nuxtjs/auth-next in /frontend ([#1265](https://github.com/mealie-recipes/mealie/issues/1265))
- Bad dev dependency ([#1281](https://github.com/hay-kot/mealie/issues/1281)) - Bad dev dependency ([#1281](https://github.com/mealie-recipes/mealie/issues/1281))
- Add touch support for mealplanner delete ([#1298](https://github.com/hay-kot/mealie/issues/1298)) - Add touch support for mealplanner delete ([#1298](https://github.com/mealie-recipes/mealie/issues/1298))
### Documentation ### Documentation
- Add references for VSCode dev containers ([#1299](https://github.com/hay-kot/mealie/issues/1299)) - Add references for VSCode dev containers ([#1299](https://github.com/mealie-recipes/mealie/issues/1299))
- Docker-compose.dev.yml is currently not functional ([#1300](https://github.com/hay-kot/mealie/issues/1300)) - Docker-compose.dev.yml is currently not functional ([#1300](https://github.com/mealie-recipes/mealie/issues/1300))
### Features ### Features
- Add reports to bulk recipe import (url) ([#1294](https://github.com/hay-kot/mealie/issues/1294)) - Add reports to bulk recipe import (url) ([#1294](https://github.com/mealie-recipes/mealie/issues/1294))
- Rewrite print implementation to support new ing ([#1305](https://github.com/hay-kot/mealie/issues/1305)) - Rewrite print implementation to support new ing ([#1305](https://github.com/mealie-recipes/mealie/issues/1305))
### Miscellaneous Tasks ### Miscellaneous Tasks
- Github stalebot changes ([#1271](https://github.com/hay-kot/mealie/issues/1271)) - Github stalebot changes ([#1271](https://github.com/mealie-recipes/mealie/issues/1271))
- Bump eslint-plugin-nuxt in /frontend ([#1258](https://github.com/hay-kot/mealie/issues/1258)) - Bump eslint-plugin-nuxt in /frontend ([#1258](https://github.com/mealie-recipes/mealie/issues/1258))
- Bump @vue/runtime-dom in /frontend ([#1259](https://github.com/hay-kot/mealie/issues/1259)) - Bump @vue/runtime-dom in /frontend ([#1259](https://github.com/mealie-recipes/mealie/issues/1259))
- Bump nuxt-vite from 0.1.3 to 0.3.5 in /frontend ([#1260](https://github.com/hay-kot/mealie/issues/1260)) - Bump nuxt-vite from 0.1.3 to 0.3.5 in /frontend ([#1260](https://github.com/mealie-recipes/mealie/issues/1260))
- Bump vue2-script-setup-transform in /frontend ([#1263](https://github.com/hay-kot/mealie/issues/1263)) - Bump vue2-script-setup-transform in /frontend ([#1263](https://github.com/mealie-recipes/mealie/issues/1263))
- Update dev dependencies ([#1282](https://github.com/hay-kot/mealie/issues/1282)) - Update dev dependencies ([#1282](https://github.com/mealie-recipes/mealie/issues/1282))
### Refactor ### Refactor
- Split up recipe create page ([#1283](https://github.com/hay-kot/mealie/issues/1283)) - Split up recipe create page ([#1283](https://github.com/mealie-recipes/mealie/issues/1283))

View File

@ -1,36 +1,36 @@
### Bug Fixes ### Bug Fixes
- Update issue links in v1.0.0beta-2 changelog ([#1312](https://github.com/hay-kot/mealie/issues/1312)) - Update issue links in v1.0.0beta-2 changelog ([#1312](https://github.com/mealie-recipes/mealie/issues/1312))
- Bad import path ([#1313](https://github.com/hay-kot/mealie/issues/1313)) - Bad import path ([#1313](https://github.com/mealie-recipes/mealie/issues/1313))
- Printer page refs ([#1314](https://github.com/hay-kot/mealie/issues/1314)) - Printer page refs ([#1314](https://github.com/mealie-recipes/mealie/issues/1314))
- Consolidate stores to fix mismatched state - Consolidate stores to fix mismatched state
- Bump @vue/composition-api from 1.6.1 to 1.6.2 in /frontend ([#1275](https://github.com/hay-kot/mealie/issues/1275)) - Bump @vue/composition-api from 1.6.1 to 1.6.2 in /frontend ([#1275](https://github.com/mealie-recipes/mealie/issues/1275))
- Shopping list label editor ([#1333](https://github.com/hay-kot/mealie/issues/1333)) - Shopping list label editor ([#1333](https://github.com/mealie-recipes/mealie/issues/1333))
### Features ### Features
- Default unit fractions to True - Default unit fractions to True
- Add unit abbreviation support ([#1332](https://github.com/hay-kot/mealie/issues/1332)) - Add unit abbreviation support ([#1332](https://github.com/mealie-recipes/mealie/issues/1332))
- Attached images by drag and drop for recipe steps ([#1341](https://github.com/hay-kot/mealie/issues/1341)) - Attached images by drag and drop for recipe steps ([#1341](https://github.com/mealie-recipes/mealie/issues/1341))
### Docs ### Docs
- Render homepage social media link images at 32x32 size ([#1310](https://github.com/hay-kot/mealie/issues/1310)) - Render homepage social media link images at 32x32 size ([#1310](https://github.com/mealie-recipes/mealie/issues/1310))
### Miscellaneous Tasks ### Miscellaneous Tasks
- Init git-cliff config - Init git-cliff config
- Bump @types/sortablejs in /frontend ([#1287](https://github.com/hay-kot/mealie/issues/1287)) - Bump @types/sortablejs in /frontend ([#1287](https://github.com/mealie-recipes/mealie/issues/1287))
- Bump @babel/eslint-parser in /frontend ([#1290](https://github.com/hay-kot/mealie/issues/1290)) - Bump @babel/eslint-parser in /frontend ([#1290](https://github.com/mealie-recipes/mealie/issues/1290))
### Refactor ### Refactor
- Unify recipe-organizer components ([#1340](https://github.com/hay-kot/mealie/issues/1340)) - Unify recipe-organizer components ([#1340](https://github.com/mealie-recipes/mealie/issues/1340))
### Security ### Security
- Delay server response whenever username is non existing ([#1338](https://github.com/hay-kot/mealie/issues/1338)) - Delay server response whenever username is non existing ([#1338](https://github.com/mealie-recipes/mealie/issues/1338))
### Wip ### Wip
- Pagination-repository ([#1316](https://github.com/hay-kot/mealie/issues/1316)) - Pagination-repository ([#1316](https://github.com/mealie-recipes/mealie/issues/1316))

View File

@ -63,57 +63,57 @@ If either of the above actions prevent the user from uploading images, the appli
### Bug Fixes ### Bug Fixes
- For erroneously-translated datetime config ([#1362](https://github.com/hay-kot/mealie/issues/1362)) - For erroneously-translated datetime config ([#1362](https://github.com/mealie-recipes/mealie/issues/1362))
- Fixed text color on RecipeCard in RecipePrintView and implemented ingredient sections ([#1351](https://github.com/hay-kot/mealie/issues/1351)) - Fixed text color on RecipeCard in RecipePrintView and implemented ingredient sections ([#1351](https://github.com/mealie-recipes/mealie/issues/1351))
- Ingredient sections lost after parsing ([#1368](https://github.com/hay-kot/mealie/issues/1368)) - Ingredient sections lost after parsing ([#1368](https://github.com/mealie-recipes/mealie/issues/1368))
- Increased float rounding precision for CRF parser ([#1369](https://github.com/hay-kot/mealie/issues/1369)) - Increased float rounding precision for CRF parser ([#1369](https://github.com/mealie-recipes/mealie/issues/1369))
- Infinite scroll bug on all recipes page ([#1393](https://github.com/hay-kot/mealie/issues/1393)) - Infinite scroll bug on all recipes page ([#1393](https://github.com/mealie-recipes/mealie/issues/1393))
- Fast fail of bulk importer ([#1394](https://github.com/hay-kot/mealie/issues/1394)) - Fast fail of bulk importer ([#1394](https://github.com/mealie-recipes/mealie/issues/1394))
- Bump @mdi/js from 5.9.55 to 6.7.96 in /frontend ([#1279](https://github.com/hay-kot/mealie/issues/1279)) - Bump @mdi/js from 5.9.55 to 6.7.96 in /frontend ([#1279](https://github.com/mealie-recipes/mealie/issues/1279))
- Bump @nuxtjs/i18n from 7.0.3 to 7.2.2 in /frontend ([#1288](https://github.com/hay-kot/mealie/issues/1288)) - Bump @nuxtjs/i18n from 7.0.3 to 7.2.2 in /frontend ([#1288](https://github.com/mealie-recipes/mealie/issues/1288))
- Bump date-fns from 2.23.0 to 2.28.0 in /frontend ([#1293](https://github.com/hay-kot/mealie/issues/1293)) - Bump date-fns from 2.23.0 to 2.28.0 in /frontend ([#1293](https://github.com/mealie-recipes/mealie/issues/1293))
- Bump fuse.js from 6.5.3 to 6.6.2 in /frontend ([#1325](https://github.com/hay-kot/mealie/issues/1325)) - Bump fuse.js from 6.5.3 to 6.6.2 in /frontend ([#1325](https://github.com/mealie-recipes/mealie/issues/1325))
- Bump core-js from 3.17.2 to 3.23.1 in /frontend ([#1383](https://github.com/hay-kot/mealie/issues/1383)) - Bump core-js from 3.17.2 to 3.23.1 in /frontend ([#1383](https://github.com/mealie-recipes/mealie/issues/1383))
- All-recipes page now sorts alphabetically ([#1405](https://github.com/hay-kot/mealie/issues/1405)) - All-recipes page now sorts alphabetically ([#1405](https://github.com/mealie-recipes/mealie/issues/1405))
- Sort recent recipes by created_at instead of date_added ([#1417](https://github.com/hay-kot/mealie/issues/1417)) - Sort recent recipes by created_at instead of date_added ([#1417](https://github.com/mealie-recipes/mealie/issues/1417))
- Only show scaler when ingredients amounts enabled ([#1426](https://github.com/hay-kot/mealie/issues/1426)) - Only show scaler when ingredients amounts enabled ([#1426](https://github.com/mealie-recipes/mealie/issues/1426))
- Add missing types for API token deletion ([#1428](https://github.com/hay-kot/mealie/issues/1428)) - Add missing types for API token deletion ([#1428](https://github.com/mealie-recipes/mealie/issues/1428))
- Entry nutrition checker ([#1448](https://github.com/hay-kot/mealie/issues/1448)) - Entry nutrition checker ([#1448](https://github.com/mealie-recipes/mealie/issues/1448))
- Use == operator instead of is_ for sql queries ([#1453](https://github.com/hay-kot/mealie/issues/1453)) - Use == operator instead of is_ for sql queries ([#1453](https://github.com/mealie-recipes/mealie/issues/1453))
- Use `mtime` instead of `ctime` for backup dates ([#1461](https://github.com/hay-kot/mealie/issues/1461)) - Use `mtime` instead of `ctime` for backup dates ([#1461](https://github.com/mealie-recipes/mealie/issues/1461))
- Mealplan pagination ([#1464](https://github.com/hay-kot/mealie/issues/1464)) - Mealplan pagination ([#1464](https://github.com/mealie-recipes/mealie/issues/1464))
- Properly use pagination for group event notifies ([#1512](https://github.com/hay-kot/mealie/pull/1512)) - Properly use pagination for group event notifies ([#1512](https://github.com/mealie-recipes/mealie/pull/1512))
### Documentation ### Documentation
- Add go bulk import example ([#1388](https://github.com/hay-kot/mealie/issues/1388)) - Add go bulk import example ([#1388](https://github.com/mealie-recipes/mealie/issues/1388))
- Fix old link - Fix old link
- Pagination and filtering, and fixed a few broken links ([#1488](https://github.com/hay-kot/mealie/issues/1488)) - Pagination and filtering, and fixed a few broken links ([#1488](https://github.com/mealie-recipes/mealie/issues/1488))
### Features ### Features
- Toggle display of ingredient references in recipe instructions ([#1268](https://github.com/hay-kot/mealie/issues/1268)) - Toggle display of ingredient references in recipe instructions ([#1268](https://github.com/mealie-recipes/mealie/issues/1268))
- Add custom scaling option ([#1345](https://github.com/hay-kot/mealie/issues/1345)) - Add custom scaling option ([#1345](https://github.com/mealie-recipes/mealie/issues/1345))
- Implemented "order by" API parameters for recipe, food, and unit queries ([#1356](https://github.com/hay-kot/mealie/issues/1356)) - Implemented "order by" API parameters for recipe, food, and unit queries ([#1356](https://github.com/mealie-recipes/mealie/issues/1356))
- Implement user favorites page ([#1376](https://github.com/hay-kot/mealie/issues/1376)) - Implement user favorites page ([#1376](https://github.com/mealie-recipes/mealie/issues/1376))
- Extend Apprise JSON notification functionality with programmatic data ([#1355](https://github.com/hay-kot/mealie/issues/1355)) - Extend Apprise JSON notification functionality with programmatic data ([#1355](https://github.com/mealie-recipes/mealie/issues/1355))
- Mealplan-webhooks ([#1403](https://github.com/hay-kot/mealie/issues/1403)) - Mealplan-webhooks ([#1403](https://github.com/mealie-recipes/mealie/issues/1403))
- Added "last-modified" header to supported record types ([#1379](https://github.com/hay-kot/mealie/issues/1379)) - Added "last-modified" header to supported record types ([#1379](https://github.com/mealie-recipes/mealie/issues/1379))
- Re-write get all routes to use pagination ([#1424](https://github.com/hay-kot/mealie/issues/1424)) - Re-write get all routes to use pagination ([#1424](https://github.com/mealie-recipes/mealie/issues/1424))
- Advanced filtering API ([#1468](https://github.com/hay-kot/mealie/issues/1468)) - Advanced filtering API ([#1468](https://github.com/mealie-recipes/mealie/issues/1468))
- Restore frontend sorting for all recipes ([#1497](https://github.com/hay-kot/mealie/issues/1497)) - Restore frontend sorting for all recipes ([#1497](https://github.com/mealie-recipes/mealie/issues/1497))
- Implemented local storage for sorting and dynamic sort icons on the new recipe sort card ([1506](https://github.com/hay-kot/mealie/pull/1506)) - Implemented local storage for sorting and dynamic sort icons on the new recipe sort card ([1506](https://github.com/mealie-recipes/mealie/pull/1506))
- create new foods and units from their Data Management pages ([#1511](https://github.com/hay-kot/mealie/pull/1511)) - create new foods and units from their Data Management pages ([#1511](https://github.com/mealie-recipes/mealie/pull/1511))
### Miscellaneous Tasks ### Miscellaneous Tasks
- Bump dev deps ([#1418](https://github.com/hay-kot/mealie/issues/1418)) - Bump dev deps ([#1418](https://github.com/mealie-recipes/mealie/issues/1418))
- Bump @vue/runtime-dom in /frontend ([#1423](https://github.com/hay-kot/mealie/issues/1423)) - Bump @vue/runtime-dom in /frontend ([#1423](https://github.com/mealie-recipes/mealie/issues/1423))
- Backend page_all route cleanup ([#1483](https://github.com/hay-kot/mealie/issues/1483)) - Backend page_all route cleanup ([#1483](https://github.com/mealie-recipes/mealie/issues/1483))
### Refactor ### Refactor
- Remove depreciated repo call ([#1370](https://github.com/hay-kot/mealie/issues/1370)) - Remove depreciated repo call ([#1370](https://github.com/mealie-recipes/mealie/issues/1370))
### Hotfix ### Hotfix
@ -121,6 +121,6 @@ If either of the above actions prevent the user from uploading images, the appli
### UI ### UI
- Improve parser ui text display ([#1437](https://github.com/hay-kot/mealie/issues/1437)) - Improve parser ui text display ([#1437](https://github.com/mealie-recipes/mealie/issues/1437))
<!-- generated by git-cliff --> <!-- generated by git-cliff -->

View File

@ -20,8 +20,8 @@ Pull requests are the best way to propose changes to the codebase (we use [Githu
## Any contributions you make will be under the AGPL Software License ## Any contributions you make will be under the AGPL Software License
In short, when you submit code changes, your submissions are understood to be under the same [AGPL License](https://choosealicense.com/licenses/agpl-3.0/) that covers the project. Feel free to contact the maintainers if that's a concern. In short, when you submit code changes, your submissions are understood to be under the same [AGPL License](https://choosealicense.com/licenses/agpl-3.0/) that covers the project. Feel free to contact the maintainers if that's a concern.
## Report bugs using Github's [issues](https://github.com/hay-kot/mealie/issues) ## Report bugs using Github's [issues](https://github.com/mealie-recipes/mealie/issues)
We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/hay-kot/mealie/issues/new); it's that easy! We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/mealie-recipes/mealie/issues/new); it's that easy!
## Write bug reports with detail, background, and sample code ## Write bug reports with detail, background, and sample code
**Great Bug Reports** tend to have: **Great Bug Reports** tend to have:

View File

@ -124,9 +124,9 @@ docker-prod 🐳 Build and Start Docker Production Stack
``` ```
## Internationalization ## Internationalization
### Frontend ### Frontend
We use vue-i18n package for internationalization. Translations are stored in json format located in [frontend/lang/messages](https://github.com/hay-kot/mealie/tree/mealie-next/frontend/lang/messages). We use vue-i18n package for internationalization. Translations are stored in json format located in [frontend/lang/messages](https://github.com/mealie-recipes/mealie/tree/mealie-next/frontend/lang/messages).
### Backend ### Backend
Translations are stored in json format located in [mealie/lang/messages](https://github.com/hay-kot/mealie/tree/mealie-next/mealie/lang/messages). Translations are stored in json format located in [mealie/lang/messages](https://github.com/mealie-recipes/mealie/tree/mealie-next/mealie/lang/messages).
### Quick frontend localization with VS Code ### Quick frontend localization with VS Code
[i18n Ally for VScode](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) is helpful for generating new strings to translate using Code Actions. It also has a nice feature, which shows translations in-place when editing code. [i18n Ally for VScode](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) is helpful for generating new strings to translate using Code Actions. It also has a nice feature, which shows translations in-place when editing code.

View File

@ -15,6 +15,6 @@ Alternatively, you can register a new parser by fulfilling the `ABCIngredientPar
## Links ## Links
- [Pretrained Model](https://github.com/hay-kot/mealie-nlp-model) - [Pretrained Model](https://github.com/mealie-recipes/mealie-nlp-model)
- [CRF++ (Forked)](https://github.com/hay-kot/crfpp) - [CRF++ (Forked)](https://github.com/hay-kot/crfpp)

File diff suppressed because one or more lines are too long

View File

@ -330,9 +330,6 @@ export default defineComponent({
.list-group { .list-group {
min-height: 38px; min-height: 38px;
} }
.list-group-item {
cursor: move;
}
.list-group-item i { .list-group-item i {
cursor: pointer; cursor: pointer;
} }

View File

@ -117,7 +117,7 @@
@click="toggleDisabled(index)" @click="toggleDisabled(index)"
> >
<v-card-title :class="{ 'pb-0': !isChecked(index) }"> <v-card-title :class="{ 'pb-0': !isChecked(index) }">
<span class="handle"> <span :class="isEditForm ? 'handle' : ''">
<v-icon v-if="isEditForm" size="26" class="pb-1">{{ $globals.icons.arrowUpDown }}</v-icon> <v-icon v-if="isEditForm" size="26" class="pb-1">{{ $globals.icons.arrowUpDown }}</v-icon>
{{ $t("recipe.step-index", { step: index + 1 }) }} {{ $t("recipe.step-index", { step: index + 1 }) }}
</span> </span>
@ -671,9 +671,6 @@ export default defineComponent({
.list-group { .list-group {
min-height: 38px; min-height: 38px;
} }
.list-group-item {
cursor: move;
}
.list-group-item i { .list-group-item i {
cursor: pointer; cursor: pointer;
} }

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Sleutelwoord", "keyword": "Sleutelwoord",
"link-copied": "Skakel gekopieer", "link-copied": "Skakel gekopieer",
"loading": "Loading",
"loading-events": "Besig om gebeurtenisse te laai", "loading-events": "Besig om gebeurtenisse te laai",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "كلمة مفتاحية", "keyword": "كلمة مفتاحية",
"link-copied": "تمّ نسْخ الرّابط", "link-copied": "تمّ نسْخ الرّابط",
"loading": "Loading",
"loading-events": "جاري تحميل الأحداث", "loading-events": "جاري تحميل الأحداث",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Ключова дума", "keyword": "Ключова дума",
"link-copied": "Линкът е копиран", "link-copied": "Линкът е копиран",
"loading": "Loading",
"loading-events": "Зареждане на събития", "loading-events": "Зареждане на събития",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Paraula clau", "keyword": "Paraula clau",
"link-copied": "S'ha copiat l'enllaç", "link-copied": "S'ha copiat l'enllaç",
"loading": "Loading",
"loading-events": "Carregant esdeveniments", "loading-events": "Carregant esdeveniments",
"loading-recipe": "Carregant la recepta...", "loading-recipe": "Carregant la recepta...",
"loading-ocr-data": "Carregant les dades OCR...", "loading-ocr-data": "Carregant les dades OCR...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Klíčové slovo", "keyword": "Klíčové slovo",
"link-copied": "Odkaz zkopírován", "link-copied": "Odkaz zkopírován",
"loading": "Loading",
"loading-events": "Načítání událostí", "loading-events": "Načítání událostí",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Nøgleord", "keyword": "Nøgleord",
"link-copied": "Link kopieret", "link-copied": "Link kopieret",
"loading": "Indlæser",
"loading-events": "Indlæser hændelser", "loading-events": "Indlæser hændelser",
"loading-recipe": "Indlæser opskrift...", "loading-recipe": "Indlæser opskrift...",
"loading-ocr-data": "Indlæser OCR data...", "loading-ocr-data": "Indlæser OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Schlüsselwort", "keyword": "Schlüsselwort",
"link-copied": "Link kopiert", "link-copied": "Link kopiert",
"loading": "Wird geladen...",
"loading-events": "Ereignisse werden geladen", "loading-events": "Ereignisse werden geladen",
"loading-recipe": "Lade Rezept...", "loading-recipe": "Lade Rezept...",
"loading-ocr-data": "Lade OCR-Daten...", "loading-ocr-data": "Lade OCR-Daten...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Λέξη-κλειδί", "keyword": "Λέξη-κλειδί",
"link-copied": "Ο Σύνδεσμος Αντιγράφηκε", "link-copied": "Ο Σύνδεσμος Αντιγράφηκε",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Keyword", "keyword": "Keyword",
"link-copied": "Link Copied", "link-copied": "Link Copied",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Keyword", "keyword": "Keyword",
"link-copied": "Link Copied", "link-copied": "Link Copied",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Etiqueta", "keyword": "Etiqueta",
"link-copied": "Enlace copiado", "link-copied": "Enlace copiado",
"loading": "Loading",
"loading-events": "Cargando Eventos", "loading-events": "Cargando Eventos",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Hakusana", "keyword": "Hakusana",
"link-copied": "Linkki kopioitu", "link-copied": "Linkki kopioitu",
"loading": "Loading",
"loading-events": "Ladataan tapahtumia", "loading-events": "Ladataan tapahtumia",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Mot-clé", "keyword": "Mot-clé",
"link-copied": "Lien copié", "link-copied": "Lien copié",
"loading": "Chargement",
"loading-events": "Chargement des événements", "loading-events": "Chargement des événements",
"loading-recipe": "Chargement de la recette...", "loading-recipe": "Chargement de la recette...",
"loading-ocr-data": "Chargement des données OCR...", "loading-ocr-data": "Chargement des données OCR...",
@ -875,7 +876,7 @@
"user-management": "Gestion des utilisateurs", "user-management": "Gestion des utilisateurs",
"reset-locked-users": "Réinitialiser les utilisateurs verrouillés", "reset-locked-users": "Réinitialiser les utilisateurs verrouillés",
"admin-user-creation": "Création d'un utilisateur admin", "admin-user-creation": "Création d'un utilisateur admin",
"admin-user-management": "Admin User Management", "admin-user-management": "Administration des utilisateurs",
"user-details": "Détails de l'utilisateur", "user-details": "Détails de l'utilisateur",
"user-name": "Nom d'utilisateur", "user-name": "Nom d'utilisateur",
"authentication-method": "Méthode d'authentification", "authentication-method": "Méthode d'authentification",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Mot-clé", "keyword": "Mot-clé",
"link-copied": "Lien copié", "link-copied": "Lien copié",
"loading": "Chargement",
"loading-events": "Chargement des événements", "loading-events": "Chargement des événements",
"loading-recipe": "Chargement de la recette...", "loading-recipe": "Chargement de la recette...",
"loading-ocr-data": "Chargement des données OCR...", "loading-ocr-data": "Chargement des données OCR...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Keyword", "keyword": "Keyword",
"link-copied": "Link Copied", "link-copied": "Link Copied",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "מילת מפתח", "keyword": "מילת מפתח",
"link-copied": "קישור הועתק", "link-copied": "קישור הועתק",
"loading": "Loading",
"loading-events": "טוען", "loading-events": "טוען",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Ključna riječ", "keyword": "Ključna riječ",
"link-copied": "Poveznica kopirana", "link-copied": "Poveznica kopirana",
"loading": "Loading",
"loading-events": "Učitavanje događaja", "loading-events": "Učitavanje događaja",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -77,7 +77,7 @@
"tag-events": "Címke események", "tag-events": "Címke események",
"category-events": "Kategória események", "category-events": "Kategória események",
"when-a-new-user-joins-your-group": "Amikor egy új felhasználó csatlakozik a csoportodba", "when-a-new-user-joins-your-group": "Amikor egy új felhasználó csatlakozik a csoportodba",
"recipe-events": "Recipe Events" "recipe-events": "Recept esemény"
}, },
"general": { "general": {
"cancel": "Mégsem", "cancel": "Mégsem",
@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Kulcsszó", "keyword": "Kulcsszó",
"link-copied": "Hivatkozás másolva", "link-copied": "Hivatkozás másolva",
"loading": "Loading",
"loading-events": "Események betöltése", "loading-events": "Események betöltése",
"loading-recipe": "Recept betöltése...", "loading-recipe": "Recept betöltése...",
"loading-ocr-data": "OCR adatok betöltése...", "loading-ocr-data": "OCR adatok betöltése...",
@ -590,7 +591,7 @@
"import-summary": "Import összefoglaló", "import-summary": "Import összefoglaló",
"partial-backup": "Részleges biztonsági mentés", "partial-backup": "Részleges biztonsági mentés",
"unable-to-delete-backup": "Nem lehetett létrehozni a biztonsági mentést.", "unable-to-delete-backup": "Nem lehetett létrehozni a biztonsági mentést.",
"experimental-description": "Backups a total snapshots of the database and data directory of the site. This includes all data and cannot be set to exclude subsets of data. You can think off this as a snapshot of Mealie at a specific time. Currently, {not-crossed-version} (data migrations are not done automatically). These serve as a database agnostic way to export and import data or backup the site to an external location.", "experimental-description": "A biztonsági mentések az oldal adatbázisának és adatkönyvtárának teljes pillanatfelvételei. Ez az összes adatot tartalmazza, és nem lehet beállítani, hogy az adatok részhalmazait kizárja. Ezt úgy is elképzelheti, mint a Mealie egy adott időpontban készült pillanatfelvételét. Ezek adatbázis-független módon szolgálnak az adatok exportálására és importálására, vagy a webhely külső helyre történő mentésére.",
"backup-restore": "Biztonsági Mentés/Visszaállítás", "backup-restore": "Biztonsági Mentés/Visszaállítás",
"back-restore-description": "A biztonsági mentés visszaállítása felülírja az adatbázisban és az adatkönyvtárban lévő összes aktuális adatot, és a biztonsági mentés tartalmával helyettesíti azokat. {cannot-be-undone} Ha a visszaállítás sikeres, akkor a rendszer kilépteti Önt.", "back-restore-description": "A biztonsági mentés visszaállítása felülírja az adatbázisban és az adatkönyvtárban lévő összes aktuális adatot, és a biztonsági mentés tartalmával helyettesíti azokat. {cannot-be-undone} Ha a visszaállítás sikeres, akkor a rendszer kilépteti Önt.",
"cannot-be-undone": "Ezt a műveletet visszavonható - óvatosan használja.", "cannot-be-undone": "Ezt a műveletet visszavonható - óvatosan használja.",
@ -1056,8 +1057,8 @@
"click": "Kattintson bármelyik mezőre a jobb oldalon, majd kattintson vissza a kép feletti téglalapra.", "click": "Kattintson bármelyik mezőre a jobb oldalon, majd kattintson vissza a kép feletti téglalapra.",
"result": "A kiválasztott szöveg a korábban kiválasztott mezőben jelenik meg." "result": "A kiválasztott szöveg a korábban kiválasztott mezőben jelenik meg."
}, },
"pan-and-zoom-mode": "Pan and Zoom Mode", "pan-and-zoom-mode": "Pásztázás és nagyítás mód",
"pan-and-zoom-desc": "Select pan and zoom by clicking the icon. This mode allows to zoom inside the image and move around to make using big images easier.", "pan-and-zoom-desc": "Válassza ki a pásztázást és a nagyítást az ikonra kattintva. Ez a mód lehetővé teszi a kép nagyítását és mozgását a nagy képek használatának megkönnyítése érdekében.",
"split-text-mode": "Szöveg felosztási módok", "split-text-mode": "Szöveg felosztási módok",
"split-modes": { "split-modes": {
"line-mode": "Vonal mód (alapértelmezett)", "line-mode": "Vonal mód (alapértelmezett)",
@ -1113,7 +1114,7 @@
"show-individual-confidence": "", "show-individual-confidence": "",
"ingredient-text": "Hozzávaló szöveg", "ingredient-text": "Hozzávaló szöveg",
"average-confident": "{0} Confident", "average-confident": "{0} Confident",
"try-an-example": "Próbáld ki", "try-an-example": "Próbáljon ki egy példát",
"parser": "Szintaxis elemző", "parser": "Szintaxis elemző",
"background-tasks": "Háttér folyamatok", "background-tasks": "Háttér folyamatok",
"background-tasks-description": "Itt megtekintheti az összes futó háttérfeladatot és azok állapotát", "background-tasks-description": "Itt megtekintheti az összes futó háttérfeladatot és azok állapotát",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Parola chiave", "keyword": "Parola chiave",
"link-copied": "Link Copiato", "link-copied": "Link Copiato",
"loading": "Loading",
"loading-events": "Caricamento eventi", "loading-events": "Caricamento eventi",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "キーワード", "keyword": "キーワード",
"link-copied": "リンクをコピーしました。", "link-copied": "リンクをコピーしました。",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "키워드", "keyword": "키워드",
"link-copied": "링크 복사됨", "link-copied": "링크 복사됨",
"loading": "Loading",
"loading-events": "이벤트를 불러오는 중", "loading-events": "이벤트를 불러오는 중",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Raktažodis", "keyword": "Raktažodis",
"link-copied": "Nuoroda nukopijuota", "link-copied": "Nuoroda nukopijuota",
"loading": "Loading",
"loading-events": "Užkrovimo įvykiai", "loading-events": "Užkrovimo įvykiai",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Keyword", "keyword": "Keyword",
"link-copied": "Link Copied", "link-copied": "Link Copied",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Trefwoord", "keyword": "Trefwoord",
"link-copied": "Link Gekopieerd", "link-copied": "Link Gekopieerd",
"loading": "Bezig met laden",
"loading-events": "Gebeurtenis laden", "loading-events": "Gebeurtenis laden",
"loading-recipe": "Recepten ophalen...", "loading-recipe": "Recepten ophalen...",
"loading-ocr-data": "OCR gegevens laden...", "loading-ocr-data": "OCR gegevens laden...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Nøkkelord", "keyword": "Nøkkelord",
"link-copied": "Lenke kopiert", "link-copied": "Lenke kopiert",
"loading": "Loading",
"loading-events": "Laster hendelser", "loading-events": "Laster hendelser",
"loading-recipe": "Laster oppskrift...", "loading-recipe": "Laster oppskrift...",
"loading-ocr-data": "Laster OCR data...", "loading-ocr-data": "Laster OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Słowo kluczowe", "keyword": "Słowo kluczowe",
"link-copied": "Odnośnik skopiowany", "link-copied": "Odnośnik skopiowany",
"loading": "Loading",
"loading-events": "Ładowanie wydarzeń", "loading-events": "Ładowanie wydarzeń",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Palavra chave", "keyword": "Palavra chave",
"link-copied": "Link Copiado", "link-copied": "Link Copiado",
"loading": "Loading",
"loading-events": "Carregando eventos", "loading-events": "Carregando eventos",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Palavra-chave", "keyword": "Palavra-chave",
"link-copied": "Ligação copiada", "link-copied": "Ligação copiada",
"loading": "Loading",
"loading-events": "A carregar Eventos", "loading-events": "A carregar Eventos",
"loading-recipe": "A carregar receita...", "loading-recipe": "A carregar receita...",
"loading-ocr-data": "A carregar dados OCR...", "loading-ocr-data": "A carregar dados OCR...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Cuvânt cheie", "keyword": "Cuvânt cheie",
"link-copied": "Link copiat", "link-copied": "Link copiat",
"loading": "Loading",
"loading-events": "Se încarcă evenimentele", "loading-events": "Se încarcă evenimentele",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Ключевое слово", "keyword": "Ключевое слово",
"link-copied": "Ссылка скопирована", "link-copied": "Ссылка скопирована",
"loading": "Loading",
"loading-events": "Загрузка событий", "loading-events": "Загрузка событий",
"loading-recipe": "Загрузка рецепта...", "loading-recipe": "Загрузка рецепта...",
"loading-ocr-data": "Загрузка данных OCR...", "loading-ocr-data": "Загрузка данных OCR...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Kľučové slovo", "keyword": "Kľučové slovo",
"link-copied": "Odkaz bol skopírovaný", "link-copied": "Odkaz bol skopírovaný",
"loading": "Loading",
"loading-events": "Načítanie udalostí", "loading-events": "Načítanie udalostí",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Ključna beseda", "keyword": "Ključna beseda",
"link-copied": "Povezava kopirana", "link-copied": "Povezava kopirana",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Ključna reč", "keyword": "Ključna reč",
"link-copied": "Линк је копиран", "link-copied": "Линк је копиран",
"loading": "Loading",
"loading-events": "Учитавање догађаја", "loading-events": "Учитавање догађаја",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Nyckelord", "keyword": "Nyckelord",
"link-copied": "Länk kopierad", "link-copied": "Länk kopierad",
"loading": "Loading",
"loading-events": "Laddar händelser", "loading-events": "Laddar händelser",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Anahtar Kelime", "keyword": "Anahtar Kelime",
"link-copied": "Bağlantı Kopyalandı", "link-copied": "Bağlantı Kopyalandı",
"loading": "Loading",
"loading-events": "Etkinlikler yükleniyor", "loading-events": "Etkinlikler yükleniyor",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "OCR verileri yükleniyor...", "loading-ocr-data": "OCR verileri yükleniyor...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Ключове слово", "keyword": "Ключове слово",
"link-copied": "Посилання скопійовано", "link-copied": "Посилання скопійовано",
"loading": "Завантаження",
"loading-events": "Завантаження подій", "loading-events": "Завантаження подій",
"loading-recipe": "Завантаження рецепта...", "loading-recipe": "Завантаження рецепта...",
"loading-ocr-data": "Завантаження даних OCR...", "loading-ocr-data": "Завантаження даних OCR...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Keyword", "keyword": "Keyword",
"link-copied": "Link Copied", "link-copied": "Link Copied",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "关键字", "keyword": "关键字",
"link-copied": "链接已复制", "link-copied": "链接已复制",
"loading": "Loading",
"loading-events": "正在加载事件", "loading-events": "正在加载事件",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -114,6 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "關鍵字", "keyword": "關鍵字",
"link-copied": "已複製連結", "link-copied": "已複製連結",
"loading": "Loading",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...", "loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",

View File

@ -1,137 +0,0 @@
<template>
<v-container fluid class="md-container">
<BannerExperimental></BannerExperimental>
<BaseCardSectionTitle title="Site Analytics">
Your instance of Mealie can send anonymous usage statistics to the Mealie project team. This is done to help us
gauge the usage of mealie, provide public statistics and to help us improve the user experience.
<p class="pt-4 pb-0 mb-0">
Your installation creates a UUID that is used to identify your installation,
<strong> this is randomly generated using the UUID4 implementation in python</strong>. This UUID is stored on
our analytics server and used to ensure your data is only counted once.
</p>
</BaseCardSectionTitle>
<section>
<BaseCardSectionTitle class="pb-0" :icon="$globals.icons.chart" title="Analytics Settings">
When you opt into analytics your install will register itself with the Analytics API to count the installation
and register your generated anonymous installation ID
</BaseCardSectionTitle>
<v-card-text>
<v-switch v-model="state.analyticsEnabled" label="Collect Anonymous Analytics" />
</v-card-text>
</section>
<section class="my-8">
<BaseCardSectionTitle class="pb-0" :icon="$globals.icons.chart" title="Analytics Data">
This is a list of all the data that is sent to the Mealie project team.
</BaseCardSectionTitle>
<v-card class="ma-2">
<template v-for="(value, idx) in data">
<v-list-item :key="`item-${idx}`">
<v-list-item-title class="py-2">
<div>{{ value.text }}</div>
<v-list-item-subtitle class="text-end"> {{ getValue(value.valueKey) }} </v-list-item-subtitle>
</v-list-item-title>
</v-list-item>
<v-divider :key="`divider-${idx}`" class="mx-2"></v-divider>
</template>
</v-card>
</section>
</v-container>
</template>
<script lang="ts">
import { defineComponent, reactive, useAsync } from "@nuxtjs/composition-api";
import { useAdminApi } from "~/composables/api";
import { useAsyncKey } from "~/composables/use-utils";
import { MealieAnalytics } from "~/lib/api/types/analytics";
type DisplayData = {
text: string;
valueKey: keyof MealieAnalytics;
};
export default defineComponent({
layout: "admin",
setup() {
const adminApi = useAdminApi();
const state = reactive({
analyticsEnabled: false,
});
const analyticsData = useAsync(async () => {
const { data } = await adminApi.analytics.getAnalytics();
return data;
}, useAsyncKey());
function getValue(key: keyof MealieAnalytics) {
if (!analyticsData.value) {
return "";
}
return analyticsData.value[key];
}
const data: DisplayData[] = [
{
text: "Installation Id",
valueKey: "installationId",
},
{
text: "Version",
valueKey: "version",
},
{
text: "Database",
valueKey: "databaseType",
},
{
text: "Using Email",
valueKey: "usingEmail",
},
{
text: "Using LDAP",
valueKey: "usingLdap",
},
{
text: "API Tokens",
valueKey: "apiTokens",
},
{
text: "Users",
valueKey: "users",
},
{
text: "Recipes",
valueKey: "recipes",
},
{
text: "Groups",
valueKey: "groups",
},
{
text: "Shopping Lists",
valueKey: "shoppingLists",
},
{
text: "Cookbooks",
valueKey: "cookbooks",
},
];
return {
data,
state,
analyticsData,
getValue,
};
},
head() {
return {
title: "Analytics",
};
},
});
</script>
<style scoped></style>

View File

@ -1,5 +1,6 @@
<template> <template>
<v-container fluid class="narrow-container"> <v-container fluid class="narrow-container">
<!-- Image -->
<BasePageTitle divider> <BasePageTitle divider>
<template #header> <template #header>
<v-img max-height="200" max-width="150" :src="require('~/static/svgs/admin-site-settings.svg')"></v-img> <v-img max-height="200" max-width="150" :src="require('~/static/svgs/admin-site-settings.svg')"></v-img>
@ -7,6 +8,7 @@
<template #title> {{ $t("settings.site-settings") }} </template> <template #title> {{ $t("settings.site-settings") }} </template>
</BasePageTitle> </BasePageTitle>
<!-- Bug Report -->
<BaseDialog v-model="bugReportDialog" :title="$t('settings.bug-report')" :width="800" :icon="$globals.icons.github"> <BaseDialog v-model="bugReportDialog" :title="$t('settings.bug-report')" :width="800" :icon="$globals.icons.github">
<v-card-text> <v-card-text>
<div class="pb-4"> <div class="pb-4">
@ -27,7 +29,6 @@
<BaseButton <BaseButton
color="info" color="info"
@click=" @click="
dockerValidate();
bugReportDialog = true; bugReportDialog = true;
" "
> >
@ -36,6 +37,7 @@
</BaseButton> </BaseButton>
</div> </div>
<!-- Configuration -->
<section> <section>
<BaseCardSectionTitle class="pb-0" :icon="$globals.icons.cog" :title="$tc('settings.configuration')"> </BaseCardSectionTitle> <BaseCardSectionTitle class="pb-0" :icon="$globals.icons.cog" :title="$tc('settings.configuration')"> </BaseCardSectionTitle>
<v-card class="mb-4"> <v-card class="mb-4">
@ -60,40 +62,7 @@
</v-card> </v-card>
</section> </section>
<section> <!-- Email -->
<BaseCardSectionTitle class="pt-2" :icon="$globals.icons.docker" :title="$tc('settings.docker-volume')" />
<v-alert
border="left"
colored-border
:type="docker.state === DockerVolumeState.Error ? 'error' : 'info'"
:icon="$globals.icons.docker"
elevation="2"
:loading="docker.loading"
>
<div class="d-flex align-center font-weight-medium">
{{ $t('settings.docker-volume') }}
<HelpIcon small class="my-n3">
{{ $t('settings.docker-volume-help') }}
</HelpIcon>
</div>
<div>
<template v-if="docker.state === DockerVolumeState.Error"> {{ $t('settings.volumes-are-misconfigured') }} </template>
<template v-else-if="docker.state === DockerVolumeState.Success">
{{ $t('settings.volumes-are-configured-correctly') }}
</template>
<template v-else-if="docker.state === DockerVolumeState.Unknown">
{{ $t('settings.status-unknown-try-running-a-validation') }}
</template>
</div>
<div class="mt-4">
<BaseButton color="info" :loading="docker.loading" @click="dockerValidate">
<template #icon> {{ $globals.icons.checkboxMarkedCircle }} </template>
{{ $t('settings.validate') }}
</BaseButton>
</div>
</v-alert>
</section>
<section> <section>
<BaseCardSectionTitle class="pt-2" :icon="$globals.icons.email" :title="$tc('user.email')" /> <BaseCardSectionTitle class="pt-2" :icon="$globals.icons.email" :title="$tc('user.email')" />
<v-alert border="left" colored-border :type="appConfig.emailReady ? 'success' : 'error'" elevation="2"> <v-alert border="left" colored-border :type="appConfig.emailReady ? 'success' : 'error'" elevation="2">
@ -130,6 +99,7 @@
<section class="mt-4"> <section class="mt-4">
<BaseCardSectionTitle class="pb-0" :icon="$globals.icons.cog" :title="$tc('settings.general-about')"> </BaseCardSectionTitle> <BaseCardSectionTitle class="pb-0" :icon="$globals.icons.cog" :title="$tc('settings.general-about')"> </BaseCardSectionTitle>
<v-card class="mb-4"> <v-card class="mb-4">
<template v-if="appInfo && appInfo.length">
<template v-for="(property, idx) in appInfo"> <template v-for="(property, idx) in appInfo">
<v-list-item :key="property.name"> <v-list-item :key="property.name">
<v-list-item-icon> <v-list-item-icon>
@ -165,6 +135,12 @@
</v-list-item> </v-list-item>
<v-divider v-if="appInfo && idx !== appInfo.length - 1" :key="`divider-${property.name}`"></v-divider> <v-divider v-if="appInfo && idx !== appInfo.length - 1" :key="`divider-${property.name}`"></v-divider>
</template> </template>
</template>
<template v-else>
<div class="mb-3 text-center">
<AppLoader :waiting-text="$tc('general.loading')" />
</div>
</template>
</v-card> </v-card>
</section> </section>
</v-container> </v-container>
@ -186,6 +162,7 @@ import { useAdminApi, useUserApi } from "~/composables/api";
import { validators } from "~/composables/use-validators"; import { validators } from "~/composables/use-validators";
import { useAsyncKey } from "~/composables/use-utils"; import { useAsyncKey } from "~/composables/use-utils";
import { CheckAppConfig } from "~/lib/api/types/admin"; import { CheckAppConfig } from "~/lib/api/types/admin";
import AppLoader from "~/components/global/AppLoader.vue";
enum DockerVolumeState { enum DockerVolumeState {
Unknown = "unknown", Unknown = "unknown",
@ -208,37 +185,9 @@ interface CheckApp extends CheckAppConfig {
} }
export default defineComponent({ export default defineComponent({
components: { AppLoader },
layout: "admin", layout: "admin",
setup() { setup() {
// ==========================================================
// Docker Volume Validation
const docker = reactive({
loading: false,
state: DockerVolumeState.Unknown,
});
async function dockerValidate() {
docker.loading = true;
// Do API Check
const { data } = await adminApi.about.checkDocker();
if (data == null) {
docker.state = DockerVolumeState.Error;
return;
}
// Get File Contents
const { data: fileContents } = await adminApi.about.getDockerValidateFileContents();
if (data.text === fileContents) {
docker.state = DockerVolumeState.Success;
} else {
docker.state = DockerVolumeState.Error;
}
docker.loading = false;
}
const state = reactive({ const state = reactive({
loading: false, loading: false,
address: "", address: "",
@ -246,7 +195,6 @@ export default defineComponent({
error: "", error: "",
tested: false, tested: false,
}); });
const appConfig = ref<CheckApp>({ const appConfig = ref<CheckApp>({
emailReady: true, emailReady: true,
baseUrlSet: true, baseUrlSet: true,
@ -254,34 +202,25 @@ export default defineComponent({
isUpToDate: false, isUpToDate: false,
ldapReady: false, ldapReady: false,
}); });
function isLocalHostOrHttps() { function isLocalHostOrHttps() {
return window.location.hostname === "localhost" || window.location.protocol === "https:"; return window.location.hostname === "localhost" || window.location.protocol === "https:";
} }
const api = useUserApi(); const api = useUserApi();
const adminApi = useAdminApi(); const adminApi = useAdminApi();
onMounted(async () => { onMounted(async () => {
const { data } = await adminApi.about.checkApp(); const { data } = await adminApi.about.checkApp();
if (data) { if (data) {
appConfig.value = { ...data, isSiteSecure: false }; appConfig.value = { ...data, isSiteSecure: false };
} }
appConfig.value.isSiteSecure = isLocalHostOrHttps(); appConfig.value.isSiteSecure = isLocalHostOrHttps();
}); });
const simpleChecks = computed<SimpleCheck[]>(() => { const simpleChecks = computed<SimpleCheck[]>(() => {
const goodIcon = $globals.icons.checkboxMarkedCircle; const goodIcon = $globals.icons.checkboxMarkedCircle;
const badIcon = $globals.icons.alert; const badIcon = $globals.icons.alert;
const warningIcon = $globals.icons.alertCircle; const warningIcon = $globals.icons.alertCircle;
const goodColor = "success"; const goodColor = "success";
const badColor = "error"; const badColor = "error";
const warningColor = "warning"; const warningColor = "warning";
const data: SimpleCheck[] = [ const data: SimpleCheck[] = [
{ {
id: "application-version", id: "application-version",
@ -305,8 +244,7 @@ export default defineComponent({
id: "server-side-base-url", id: "server-side-base-url",
text: i18n.t("settings.server-side-base-url"), text: i18n.t("settings.server-side-base-url"),
status: appConfig.value.baseUrlSet, status: appConfig.value.baseUrlSet,
errorText: errorText: i18n.t("settings.server-side-base-url-error-text"),
i18n.t("settings.server-side-base-url-error-text"),
successText: i18n.t("settings.server-side-base-url-success-text"), successText: i18n.t("settings.server-side-base-url-success-text"),
color: appConfig.value.baseUrlSet ? goodColor : badColor, color: appConfig.value.baseUrlSet ? goodColor : badColor,
icon: appConfig.value.baseUrlSet ? goodIcon : badIcon, icon: appConfig.value.baseUrlSet ? goodIcon : badIcon,
@ -315,26 +253,23 @@ export default defineComponent({
id: "ldap-ready", id: "ldap-ready",
text: i18n.t("settings.ldap-ready"), text: i18n.t("settings.ldap-ready"),
status: appConfig.value.ldapReady, status: appConfig.value.ldapReady,
errorText: errorText: i18n.t("settings.ldap-ready-error-text"),
i18n.t("settings.ldap-ready-error-text"),
successText: i18n.t("settings.ldap-ready-success-text"), successText: i18n.t("settings.ldap-ready-success-text"),
color: appConfig.value.ldapReady ? goodColor : warningColor, color: appConfig.value.ldapReady ? goodColor : warningColor,
icon: appConfig.value.ldapReady ? goodIcon : warningIcon, icon: appConfig.value.ldapReady ? goodIcon : warningIcon,
}, },
]; ];
return data; return data;
}); });
async function testEmail() { async function testEmail() {
state.loading = true; state.loading = true;
state.tested = false; state.tested = false;
const { data } = await api.email.test({ email: state.address }); const { data } = await api.email.test({ email: state.address });
if (data) { if (data) {
if (data.success) { if (data.success) {
state.success = true; state.success = true;
} else { }
else {
state.error = data.error ?? ""; state.error = data.error ?? "";
state.success = false; state.success = false;
} }
@ -342,38 +277,30 @@ export default defineComponent({
state.loading = false; state.loading = false;
state.tested = true; state.tested = true;
} }
const validEmail = computed(() => { const validEmail = computed(() => {
if (state.address === "") { if (state.address === "") {
return false; return false;
} }
const valid = validators.email(state.address); const valid = validators.email(state.address);
// Explicit bool check because validators.email sometimes returns a string // Explicit bool check because validators.email sometimes returns a string
if (valid === true) { if (valid === true) {
return true; return true;
} }
return false; return false;
}); });
// ============================================================ // ============================================================
// General About Info // General About Info
const { $globals, i18n } = useContext(); const { $globals, i18n } = useContext();
const rawAppInfo = ref({ const rawAppInfo = ref({
version: "null", version: "null",
versionLatest: "null", versionLatest: "null",
}); });
function getAppInfo() { function getAppInfo() {
const statistics = useAsync(async () => { const statistics = useAsync(async () => {
const { data } = await adminApi.about.about(); const { data } = await adminApi.about.about();
if (data) { if (data) {
rawAppInfo.value.version = data.version; rawAppInfo.value.version = data.version;
rawAppInfo.value.versionLatest = data.versionLatest; rawAppInfo.value.versionLatest = data.versionLatest;
const prettyInfo = [ const prettyInfo = [
{ {
name: i18n.t("about.version"), name: i18n.t("about.version"),
@ -428,40 +355,32 @@ export default defineComponent({
value: data.recipeScraperVersion, value: data.recipeScraperVersion,
}, },
]; ];
return prettyInfo; return prettyInfo;
} }
return data; return data;
}, useAsyncKey()); }, useAsyncKey());
return statistics; return statistics;
} }
const appInfo = getAppInfo(); const appInfo = getAppInfo();
const bugReportDialog = ref(false); const bugReportDialog = ref(false);
const bugReportText = computed(() => { const bugReportText = computed(() => {
const ignore = { const ignore = {
[i18n.tc("about.database-url")]: true, [i18n.tc("about.database-url")]: true,
[i18n.tc("about.default-group")]: true, [i18n.tc("about.default-group")]: true,
}; };
let text = "**Details**\n"; let text = "**Details**\n";
appInfo.value?.forEach((item) => { appInfo.value?.forEach((item) => {
if (ignore[item.name as string]) { if (ignore[item.name as string]) {
return; return;
} }
text += `${item.name as string}: ${item.value as string}\n`; text += `${item.name as string}: ${item.value as string}\n`;
}); });
const ignoreChecks: {
const ignoreChecks: { [key: string]: boolean } = { [key: string]: boolean;
} = {
"application-version": true, "application-version": true,
}; };
text += "\n**Checks**\n"; text += "\n**Checks**\n";
simpleChecks.value.forEach((item) => { simpleChecks.value.forEach((item) => {
if (ignoreChecks[item.id]) { if (ignoreChecks[item.id]) {
return; return;
@ -469,19 +388,13 @@ export default defineComponent({
const status = item.status ? i18n.tc("general.yes") : i18n.tc("general.no"); const status = item.status ? i18n.tc("general.yes") : i18n.tc("general.no");
text += `${item.text.toString()}: ${status}\n`; text += `${item.text.toString()}: ${status}\n`;
}); });
text += `${i18n.tc("settings.email-configured")}: ${appConfig.value.emailReady ? i18n.tc("general.yes") : i18n.tc("general.no")}\n`; text += `${i18n.tc("settings.email-configured")}: ${appConfig.value.emailReady ? i18n.tc("general.yes") : i18n.tc("general.no")}\n`;
text += `${i18n.tc("settings.docker-volume")}: ${docker.state}`;
return text; return text;
}); });
return { return {
bugReportDialog, bugReportDialog,
bugReportText, bugReportText,
DockerVolumeState, DockerVolumeState,
docker,
dockerValidate,
simpleChecks, simpleChecks,
appConfig, appConfig,
validEmail, validEmail,
@ -495,7 +408,7 @@ export default defineComponent({
return { return {
title: this.$t("settings.site-settings") as string, title: this.$t("settings.site-settings") as string,
}; };
}, }
}); });
</script> </script>

View File

@ -103,7 +103,11 @@ export default defineComponent({
if (refreshTags) { if (refreshTags) {
tags.actions.refresh(); tags.actions.refresh();
} }
router.push(`/g/${groupSlug.value}/r/${response.data}?edit=${edit.toString()}`);
// we clear the query params first so if the user hits back, they don't re-import the recipe
router.replace({ query: {} }).then(
() => router.push(`/g/${groupSlug.value}/r/${response.data}?edit=${edit.toString()}`)
);
} }
const recipeUrl = computed({ const recipeUrl = computed({

View File

@ -6,7 +6,6 @@
</template> </template>
<template #title> {{ $t('data-pages.data-management') }} </template> <template #title> {{ $t('data-pages.data-management') }} </template>
{{ $t('data-pages.data-management-description') }} {{ $t('data-pages.data-management-description') }}
<BannerExperimental class="mt-5"></BannerExperimental>
<template #content> <template #content>
<div> <div>
<BaseOverflowButton <BaseOverflowButton

View File

@ -24,8 +24,8 @@
</v-date-picker> </v-date-picker>
</v-menu> </v-menu>
<div class="d-flex align-center justify-space-between mb-2"> <div class="d-flex flex-wrap align-center justify-space-between mb-2">
<v-tabs> <v-tabs style="width: fit-content;">
<v-tab :to="`/group/mealplan/planner/view`">{{ $t('meal-plan.meal-planner') }}</v-tab> <v-tab :to="`/group/mealplan/planner/view`">{{ $t('meal-plan.meal-planner') }}</v-tab>
<v-tab :to="`/group/mealplan/planner/edit`">{{ $t('general.edit') }}</v-tab> <v-tab :to="`/group/mealplan/planner/edit`">{{ $t('general.edit') }}</v-tab>
</v-tabs> </v-tabs>

View File

@ -0,0 +1,50 @@
from slugify import slugify
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session
from mealie.core import root_logger
from mealie.db.models.group import Group
logger = root_logger.get_logger("init_db")
def _do_fix(session: Session, group: Group, counter: int):
if counter:
new_name = f"{group.id} ({counter})"
else:
new_name = str(group.id)
group.name = new_name
group.slug = slugify(group.name)
session.commit()
def fix_group_with_no_name(session: Session):
groups = session.query(Group).filter(Group.name == "").all()
if not groups:
logger.debug("No group found with an empty name; skipping fix")
return
logger.info(
f'{len(groups)} {"group" if len(groups) == 1 else "groups"} found with a missing name; '
f"applying default name"
)
offset = 0
for i, group in enumerate(groups):
attempts = 0
while True:
if attempts >= 3:
raise Exception(
f'Unable to fix empty group name for group_id "{group.id}": too many attempts ({attempts})'
)
counter = i + offset
try:
_do_fix(session, group, counter)
break
except IntegrityError:
session.rollback()
attempts += 1
offset += 1
continue

View File

@ -13,7 +13,7 @@ def fix_slug_food_names(db: AllRepositories):
logger = root_logger.get_logger("init_db") logger = root_logger.get_logger("init_db")
if not food: if not food:
logger.info(f"No food found with slug: '{check_for_food}' skipping fix") logger.debug(f"No food found with slug: '{check_for_food}' skipping fix")
return return
all_foods = db.ingredient_foods.get_all() all_foods = db.ingredient_foods.get_all()

View File

@ -10,6 +10,7 @@ from alembic.runtime import migration
from mealie.core import root_logger from mealie.core import root_logger
from mealie.core.config import get_app_settings from mealie.core.config import get_app_settings
from mealie.db.db_setup import session_context from mealie.db.db_setup import session_context
from mealie.db.fixes.fix_group_with_no_name import fix_group_with_no_name
from mealie.db.fixes.fix_slug_foods import fix_slug_food_names from mealie.db.fixes.fix_slug_foods import fix_slug_food_names
from mealie.repos.all_repositories import get_repositories from mealie.repos.all_repositories import get_repositories
from mealie.repos.repository_factory import AllRepositories from mealie.repos.repository_factory import AllRepositories
@ -104,6 +105,7 @@ def main():
init_db(db) init_db(db)
safe_try(lambda: fix_slug_food_names(db)) safe_try(lambda: fix_slug_food_names(db))
safe_try(lambda: fix_group_with_no_name(session))
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,15 +1,10 @@
import asyncio from fastapi import APIRouter
import random
import shutil
import string
from fastapi import APIRouter, BackgroundTasks
from recipe_scrapers import __version__ as recipe_scraper_version from recipe_scrapers import __version__ as recipe_scraper_version
from mealie.core.release_checker import get_latest_version from mealie.core.release_checker import get_latest_version
from mealie.core.settings.static import APP_VERSION from mealie.core.settings.static import APP_VERSION
from mealie.routes._base import BaseAdminController, controller from mealie.routes._base import BaseAdminController, controller
from mealie.schema.admin.about import AdminAboutInfo, AppStatistics, CheckAppConfig, DockerVolumeText from mealie.schema.admin.about import AdminAboutInfo, AppStatistics, CheckAppConfig
router = APIRouter(prefix="/about") router = APIRouter(prefix="/about")
@ -57,25 +52,3 @@ class AdminAboutController(BaseAdminController):
base_url_set=settings.BASE_URL != "http://localhost:8080", base_url_set=settings.BASE_URL != "http://localhost:8080",
is_up_to_date=APP_VERSION == "develop" or APP_VERSION == "nightly" or get_latest_version() == APP_VERSION, is_up_to_date=APP_VERSION == "develop" or APP_VERSION == "nightly" or get_latest_version() == APP_VERSION,
) )
@router.get("/docker/validate", response_model=DockerVolumeText)
def validate_docker_volume(self, bg: BackgroundTasks):
validation_dir = self.folders.DATA_DIR / "docker-validation"
validation_dir.mkdir(exist_ok=True)
random_string = "".join(random.choice(string.ascii_uppercase + string.digits) for _ in range(100))
with validation_dir.joinpath("validate.txt").open("w") as f:
f.write(random_string)
async def cleanup():
await asyncio.sleep(60)
try:
shutil.rmtree(validation_dir)
except Exception as e:
self.logger.error(f"Failed to remove docker validation directory: {e}")
bg.add_task(cleanup)
return DockerVolumeText(text=random_string)

View File

@ -1,5 +1,5 @@
# This file is auto-generated by gen_schema_exports.py # This file is auto-generated by gen_schema_exports.py
from .about import AdminAboutInfo, AppInfo, AppStartupInfo, AppStatistics, AppTheme, CheckAppConfig, DockerVolumeText from .about import AdminAboutInfo, AppInfo, AppStartupInfo, AppStatistics, AppTheme, CheckAppConfig
from .backup import AllBackups, BackupFile, BackupOptions, CreateBackup, ImportJob from .backup import AllBackups, BackupFile, BackupOptions, CreateBackup, ImportJob
from .email import EmailReady, EmailSuccess, EmailTest from .email import EmailReady, EmailSuccess, EmailTest
from .maintenance import MaintenanceLogs, MaintenanceStorageDetails, MaintenanceSummary from .maintenance import MaintenanceLogs, MaintenanceStorageDetails, MaintenanceSummary
@ -31,7 +31,6 @@ __all__ = [
"AppStatistics", "AppStatistics",
"AppTheme", "AppTheme",
"CheckAppConfig", "CheckAppConfig",
"DockerVolumeText",
"EmailReady", "EmailReady",
"EmailSuccess", "EmailSuccess",
"EmailTest", "EmailTest",

View File

@ -59,7 +59,3 @@ class CheckAppConfig(MealieModel):
ldap_ready: bool ldap_ready: bool
base_url_set: bool base_url_set: bool
is_up_to_date: bool is_up_to_date: bool
class DockerVolumeText(MealieModel):
text: str

View File

@ -61,7 +61,7 @@ class ChangePassword(MealieModel):
class GroupBase(MealieModel): class GroupBase(MealieModel):
name: str name: constr(strip_whitespace=True, min_length=1) # type: ignore
class Config: class Config:
orm_mode = True orm_mode = True

View File

@ -90,10 +90,10 @@ def clean_image(image: str | list | dict | None = None, default: str = "no image
image attempts to parse the image field from a recipe and return a string. Currenty image attempts to parse the image field from a recipe and return a string. Currenty
Supported Structures: Supported Structures:
- `https://exmaple.com` - A string - `https://example.com` - A string
- `{ "url": "https://exmaple.com" }` - A dictionary with a `url` key - `{ "url": "https://example.com" }` - A dictionary with a `url` key
- `["https://exmaple.com"]` - A list of strings - `["https://example.com"]` - A list of strings
- `[{ "url": "https://exmaple.com" }]` - A list of dictionaries with a `url` key - `[{ "url": "https://example.com" }]` - A list of dictionaries with a `url` key
Raises: Raises:
TypeError: If the image field is not a supported type a TypeError is raised. TypeError: If the image field is not a supported type a TypeError is raised.
@ -113,8 +113,11 @@ def clean_image(image: str | list | dict | None = None, default: str = "no image
return [x["url"] for x in image] return [x["url"] for x in image]
case {"url": str(image)}: case {"url": str(image)}:
return [image] return [image]
case [{"@id": str(_)}, *_]:
return [x["@id"] for x in image]
case _: case _:
raise TypeError(f"Unexpected type for image: {type(image)}, {image}") logger.exception(f"Unexpected type for image: {type(image)}, {image}")
return [default]
def clean_instructions(steps_object: list | dict | str, default: list | None = None) -> list[dict]: def clean_instructions(steps_object: list | dict | str, default: list | None = None) -> list[dict]:

View File

@ -212,10 +212,6 @@ class RecipeScraperPackage(ABCScraperStrategy):
class RecipeScraperOpenGraph(ABCScraperStrategy): class RecipeScraperOpenGraph(ABCScraperStrategy):
"""
Abstract class for all recipe parsers.
"""
async def get_html(self, url: str) -> str: async def get_html(self, url: str) -> str:
return await safe_scrape_html(url) return await safe_scrape_html(url)
@ -245,7 +241,7 @@ class RecipeScraperOpenGraph(ABCScraperStrategy):
"recipeIngredient": ["Could not detect ingredients"], "recipeIngredient": ["Could not detect ingredients"],
"recipeInstructions": [{"text": "Could not detect instructions"}], "recipeInstructions": [{"text": "Could not detect instructions"}],
"slug": slugify(og_field(properties, "og:title")), "slug": slugify(og_field(properties, "og:title")),
"orgURL": og_field(properties, "og:url"), "orgURL": self.url,
"categories": [], "categories": [],
"tags": og_fields(properties, "og:article:tag"), "tags": og_fields(properties, "og:article:tag"),
"dateAdded": None, "dateAdded": None,