diff --git a/.github/workflows/dockerbuild.prod.yml b/.github/workflows/dockerbuild.prod.yml
new file mode 100644
index 000000000..20f1e500a
--- /dev/null
+++ b/.github/workflows/dockerbuild.prod.yml
@@ -0,0 +1,49 @@
+name: Docker Build Dev
+
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ #
+ # Checkout
+ #
+ - name: checkout code
+ uses: actions/checkout@v2
+ #
+ # Setup QEMU
+ #
+ - name: Set up QEMU
+ id: qemu
+ uses: docker/setup-qemu-action@v1
+ with:
+ image: tonistiigi/binfmt:latest
+ platforms: all
+ #
+ # Setup Buildx
+ #
+ - name: install buildx
+ id: buildx
+ uses: docker/setup-buildx-action@v1
+ with:
+ install: true
+ #
+ # Login to Docker Hub
+ #
+ - name: Login to Docker Hub
+ uses: docker/login-action@v1
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ #
+ # Build
+ #
+ - name: build the image
+ run: |
+ docker build --push \
+ --tag hkotel/mealie:latest \
+ --platform linux/amd64,linux/arm/v7,linux/arm64 .
diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml
index 3ba6b1d6c..a384ffe31 100644
--- a/.github/workflows/pytest.yml
+++ b/.github/workflows/pytest.yml
@@ -4,7 +4,6 @@ on:
branches:
- master
- dev
- - cd/cd
pull_request:
branches:
- master
diff --git a/.gitignore b/.gitignore
index f7732da6f..83305d643 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,19 +10,18 @@ mealie/temp/api.html
.temp/
-mealie/data/backups/*
-mealie/data/debug/*
-mealie/data/img/*
-mealie/data/migration/*
-!mealie/dist/*
+app_data/backups/*
+app_data/debug/*
+app_data/img/*
+app_data/migration/*
#Exception to keep folders
!mealie/dist/.gitkeep
-!mealie/data/backups/.gitkeep
-!mealie/data/backups/dev_sample_data*
-!mealie/data/debug/.gitkeep
-!mealie/data/migration/.gitkeep
-!mealie/data/img/.gitkeep
+!app_data/backups/.gitkeep
+!app_data/backups/dev_sample_data*
+!app_data/debug/.gitkeep
+!app_data/migration/.gitkeep
+!app_data/img/.gitkeep
.DS_Store
node_modules
diff --git a/Dockerfile.arm b/Dockerfile.arm
deleted file mode 100644
index 6f35a9284..000000000
--- a/Dockerfile.arm
+++ /dev/null
@@ -1,33 +0,0 @@
-FROM node:lts-alpine as build-stage
-WORKDIR /app
-COPY ./frontend/package*.json ./
-RUN npm install
-COPY ./frontend/ .
-RUN npm run build
-
-FROM mrnr91/uvicorn-gunicorn-fastapi:python3.8
-
-
-COPY ./requirements.txt /app/requirements.txt
-
-WORKDIR /app
-
-RUN apt-get update -y && \
- apt-get install -y python-pip python-dev git curl --no-install-recommends
-
-RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | POETRY_HOME=/opt/poetry python && \
- cd /usr/local/bin && \
- ln -s /opt/poetry/bin/poetry && \
- poetry config virtualenvs.create false
-
-COPY ./pyproject.toml ./app/poetry.lock* /app/
-
-COPY ./mealie /app
-RUN poetry install --no-root --no-dev
-COPY --from=build-stage /app/dist /app/dist
-RUN rm -rf /app/test /app/.temp
-
-ENV ENV prod
-ENV APP_MODULE "app:app"
-
-VOLUME [ "/app/data" ]
diff --git a/Dockerfile.dev b/Dockerfile.dev
index 5bc4891a3..ea8f2fb5f 100644
--- a/Dockerfile.dev
+++ b/Dockerfile.dev
@@ -8,7 +8,6 @@ RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-
ln -s /opt/poetry/bin/poetry && \
poetry config virtualenvs.create false
-RUN mkdir /app/
COPY ./pyproject.toml ./app/poetry.lock* /app/
WORKDIR /app
@@ -17,7 +16,6 @@ RUN poetry install --no-root
COPY ./mealie /app
-
ENTRYPOINT [ "python" ]
CMD [ "app.py" ]
\ No newline at end of file
diff --git a/README.md b/README.md
index ddf6db3d2..91a1ae3a1 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@
Request Feature
ยท
- Docker Hub
+ Docker Hub
diff --git a/mealie/data/backups/.gitkeep b/app_data/backups/.gitkeep
similarity index 100%
rename from mealie/data/backups/.gitkeep
rename to app_data/backups/.gitkeep
diff --git a/mealie/data/backups/dev_sample_data_2021-Jan-12.zip b/app_data/backups/dev_sample_data_2021-Jan-12.zip
similarity index 100%
rename from mealie/data/backups/dev_sample_data_2021-Jan-12.zip
rename to app_data/backups/dev_sample_data_2021-Jan-12.zip
diff --git a/mealie/data/debug/.gitkeep b/app_data/debug/.gitkeep
similarity index 100%
rename from mealie/data/debug/.gitkeep
rename to app_data/debug/.gitkeep
diff --git a/mealie/data/img/.gitkeep b/app_data/img/.gitkeep
similarity index 100%
rename from mealie/data/img/.gitkeep
rename to app_data/img/.gitkeep
diff --git a/mealie/data/migration/.gitkeep b/app_data/migration/.gitkeep
similarity index 100%
rename from mealie/data/migration/.gitkeep
rename to app_data/migration/.gitkeep
diff --git a/mealie/data/templates/recipes.md b/app_data/templates/recipes.md
similarity index 100%
rename from mealie/data/templates/recipes.md
rename to app_data/templates/recipes.md
diff --git a/docker-compose.arm.yml b/docker-compose.arm.yml
deleted file mode 100644
index 5c7bc88de..000000000
--- a/docker-compose.arm.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-# Use root/example as user/password credentials
-# Frontend/Backend Served via the same Uvicorn Server
-version: "3.1"
-services:
- mealie:
- build:
- context: ./
- dockerfile: Dockerfile.arm
- container_name: mealie
- restart: always
- ports:
- - 9090:80
- environment:
- db_type: sql
- volumes:
- - ./mealie/data/:/app/data
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index c7ea72e98..c8fb6a749 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -26,39 +26,17 @@ services:
ports:
- 9921:9000
environment:
+ db_type: sqlite
TZ: America/Anchorage # Specify Correct Timezone for Date/Time to line up correctly.
- db_username: root
- db_password: example
- db_host: mongo
- db_port: 27017
volumes:
+ - ./app_data:/app_data
- ./mealie:/app
mealie-docs:
image: squidfunk/mkdocs-material
restart: always
ports:
- - 9924:8000
+ - 9923:8000
volumes:
- ./docs:/docs
- # Database
- mongo:
- image: mongo
- restart: always
- ports:
- - 9923:27017
- environment:
- TZ: America/Anchorage # Specify Correct Timezone for Date/Time to line up correctly.
- MONGO_INITDB_ROOT_USERNAME: root
- MONGO_INITDB_ROOT_PASSWORD: example
-
- # Database UI
- mongo-express:
- image: mongo-express
- restart: always
- ports:
- - 9922:8081
- environment:
- ME_CONFIG_MONGODB_ADMINUSERNAME: root
- ME_CONFIG_MONGODB_ADMINPASSWORD: example
diff --git a/docker-compose.yml b/docker-compose.yml
index 181370e27..c8363c44f 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -10,23 +10,7 @@ services:
- 9090:80
environment:
db_type: sql
- db_username: root
- db_password: example
- db_host: mongo
- db_port: 27017
+
# volumes:
# - ./mealie/data/:/app/data
- # mongo:
- # image: mongo
- # restart: always
- # environment:
- # MONGO_INITDB_ROOT_USERNAME: root
- # MONGO_INITDB_ROOT_PASSWORD: example
- # mongo-express: # Optional Mongo GUI
- # image: mongo-express
- # restart: always
- # ports:
- # - 9091:8081
- # environment:
- # ME_CONFIG_MONGODB_ADMINUSERNAME: root
- # ME_CONFIG_MONGODB_ADMINPASSWORD: example
+
diff --git a/docs/docs/roadmap.md b/docs/docs/roadmap.md
index c436a6a97..1094ceb13 100644
--- a/docs/docs/roadmap.md
+++ b/docs/docs/roadmap.md
@@ -45,8 +45,7 @@ Feature placement is not set in stone. This is much more of a guideline than any
- [ ] Setup SQL Migrations
## Breaking Changes
-- Internal port 9000 changed to port 80 for better Traefik support
- MongoDB support dropped
## Code Chores
-- [ ] Remove MongoDB Interface Code
+- [x] Remove MongoDB Interface Code
- [ ] Dockerfile Trim
diff --git a/frontend/.vscode/settings.json b/frontend/.vscode/settings.json
deleted file mode 100644
index b0b5a72c6..000000000
--- a/frontend/.vscode/settings.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "cSpell.enableFiletypes": [
- "!javascript"
- ]
-}
\ No newline at end of file
diff --git a/frontend/src/api/backup.js b/frontend/src/api/backup.js
index da5e36711..c326b684d 100644
--- a/frontend/src/api/backup.js
+++ b/frontend/src/api/backup.js
@@ -28,15 +28,8 @@ export default {
await apiReq.delete(backupURLs.deleteBackup(fileName));
},
- async create(tag, template) {
- if (typeof template == String) {
- template = [template];
- }
- console.log(tag, template);
- let response = apiReq.post(backupURLs.createBackup, {
- tag: tag,
- template: template,
- });
+ async create(data) {
+ let response = apiReq.post(backupURLs.createBackup, data);
return response;
},
};
diff --git a/frontend/src/components/Settings/Backup/AvailableBackupCard.vue b/frontend/src/components/Settings/Backup/AvailableBackupCard.vue
new file mode 100644
index 000000000..c89d6915f
--- /dev/null
+++ b/frontend/src/components/Settings/Backup/AvailableBackupCard.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+ mdi-backup-restore
+
+
+
+ {{ backup.name }}
+
+ {{ readableTime(backup.date) }}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/Settings/Backup/ImportDialog.vue b/frontend/src/components/Settings/Backup/ImportDialog.vue
index f61705a5b..7a298d756 100644
--- a/frontend/src/components/Settings/Backup/ImportDialog.vue
+++ b/frontend/src/components/Settings/Backup/ImportDialog.vue
@@ -8,7 +8,7 @@
-
+
+
+ {{ $t("settings.backup.create-heading") }}
+
+
+
+
+
+
+
+ {{ $t("general.create") }}
+
+
+
+
+
+
+ {{ $t("general.options") }}:
+
+
+
+ {{ $t("general.templates") }}:
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/Settings/Backup/index.vue b/frontend/src/components/Settings/Backup/index.vue
index cec0045a5..defa661b2 100644
--- a/frontend/src/components/Settings/Backup/index.vue
+++ b/frontend/src/components/Settings/Backup/index.vue
@@ -1,34 +1,33 @@
- {{$t('settings.backup-and-exports')}}
+ {{ $t("settings.backup-and-exports") }}
-
- {{$t('settings.backup-info')}}
-
-
-
-
-
+
+
+
-
-
-
-
-
- {{$t('settings.backup-recipes')}}
-
+
+
+ {{ $t("settings.backup-info") }}
+
-
+
+ Available Backups
+
+
+
+ Upload
+ mdi-cloud-upload
+
+
+
+
import api from "../../../api";
import SuccessFailureAlert from "../../UI/SuccessFailureAlert";
-import BackupCard from "./BackupCard";
+import AvailableBackupCard from "./AvailableBackupCard";
+import NewBackupCard from "./NewBackupCard";
export default {
components: {
SuccessFailureAlert,
- BackupCard,
+ AvailableBackupCard,
+ NewBackupCard,
},
data() {
return {
failedImports: [],
successfulImports: [],
backupLoading: false,
- backupTag: null,
- selectedBackup: null,
- selectedTemplate: null,
availableBackups: [],
- availableTemplates: [],
};
},
mounted() {
@@ -85,17 +82,6 @@ export default {
this.backupLoading = false;
}
},
- async createBackup() {
- this.backupLoading = true;
-
- let response = await api.backups.create(this.backupTag, this.templates);
-
- if (response.status == 201) {
- this.selectedBackup = null;
- this.getAvailableBackups();
- this.backupLoading = false;
- }
- },
processFinished(successful = null, failed = null) {
this.getAvailableBackups();
this.backupLoading = false;
diff --git a/frontend/src/components/Settings/Migration/UploadMigrationButton.vue b/frontend/src/components/Settings/Migration/UploadMigrationButton.vue
index 7c9e65be0..b34ff6b27 100644
--- a/frontend/src/components/Settings/Migration/UploadMigrationButton.vue
+++ b/frontend/src/components/Settings/Migration/UploadMigrationButton.vue
@@ -11,7 +11,7 @@
>
-
+c
+
+
\ No newline at end of file
diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json
index 35a65e033..6b302ba08 100644
--- a/frontend/src/locales/en.json
+++ b/frontend/src/locales/en.json
@@ -29,7 +29,11 @@
"enabled": "Enabled",
"download": "Download",
"import": "Import",
- "delete-data": "Delete Data"
+ "delete-data": "Delete Data",
+ "options": "Options",
+ "templates": "Templates",
+ "recipes": "Recipes",
+ "themes": "Themes"
},
"login": {
"stay-logged-in": "Stay logged in?",
@@ -77,7 +81,7 @@
"latest": "Latest",
"explore-the-docs": "Explore the Docs",
"contribute": "Contribute",
- "backup-and-exports": "Backup and Exports",
+ "backup-and-exports": "Backups",
"backup-info": "Backups are exported in standard JSON format along with all the images stored on the file system. In your backup folder you'll find a .zip file that contains all of the recipe JSON and images from the database. Additionally, if you selected a markdown file, those will also be stored in the .zip file. To import a backup, it must be located in your backups folder. Automated backups are done each day at 3:00 AM.",
"backup-tag": "Backup Tag",
"markdown-template": "Markdown Template",
@@ -114,7 +118,9 @@
"backup": {
"import-recipes": "Import Recipes",
"import-themes": "Import Themes",
- "import-settings": "Import Settings"
+ "import-settings": "Import Settings",
+ "create-heading": "Create a Backup",
+ "backup-tag": "Backup Tag"
}
},
"migration": {
diff --git a/mealie/app.py b/mealie/app.py
index 2d65933c7..049764bba 100644
--- a/mealie/app.py
+++ b/mealie/app.py
@@ -13,7 +13,7 @@ from routes import (
static_routes,
user_routes,
)
-from utils.api_docs import generate_api_docs
+# from utils.api_docs import generate_api_docs
from utils.logger import logger
app = FastAPI(
@@ -54,8 +54,8 @@ app.include_router(static_routes.router)
# Generate API Documentation
-if not PRODUCTION:
- generate_api_docs(app)
+# if not PRODUCTION:
+# generate_api_docs(app)
if __name__ == "__main__":
logger.info("-----SYSTEM STARTUP-----")
diff --git a/mealie/app_config.py b/mealie/app_config.py
index ef65b5250..671da0d9e 100644
--- a/mealie/app_config.py
+++ b/mealie/app_config.py
@@ -17,7 +17,7 @@ dotenv.load_dotenv(ENV)
# Helpful Globals
BASE_DIR = CWD
-DATA_DIR = CWD.joinpath("data")
+DATA_DIR = CWD.parent.joinpath("app_data")
WEB_PATH = CWD.joinpath("dist")
IMG_DIR = DATA_DIR.joinpath("img")
BACKUP_DIR = DATA_DIR.joinpath("backups")
@@ -55,14 +55,8 @@ SQLITE_FILE = None
DATABASE_TYPE = os.getenv("db_type", "sqlite") # mongo, sqlite
if DATABASE_TYPE == "sqlite":
USE_SQL = True
- USE_MONGO = False
SQLITE_FILE = SQLITE_DIR.joinpath("mealie.sqlite")
-
-elif DATABASE_TYPE == "mongo":
- USE_MONGO = True
- USE_SQL = False
-
else:
raise Exception(
"Unable to determine database type. Acceptible options are 'mongo' or 'tinydb' "
diff --git a/mealie/data/debug/last_recipe.json b/mealie/data/debug/last_recipe.json
deleted file mode 100644
index e26cfbf66..000000000
--- a/mealie/data/debug/last_recipe.json
+++ /dev/null
@@ -1,107 +0,0 @@
-{
- "@context": "http://schema.org",
- "@type": "Recipe",
- "articleBody": "\u201cMy great-grandmothers were Indigenous and mostly nomadic, which means lots of fungi foraging,\u201d says Maricela Vega, the chef at Atlanta restaurant 8ARM and founder of Chicomec\u00f3atl, an organization centering the foodways of Indigenous Mexican diaspora. \u201cWhen I serve lion\u2019s mane mushrooms to vegans they sometimes mistake them for chicken, but they\u2019re more affordable, better for the planet, and help strengthen your immune system! They grow wild during Georgia winters, but at-home cultivation kits are easy for those without forest access. I use pumpkin hot sauce, oil, and fresh herbs as a marinade, then bust out a baby grill or cast-iron skillet to get them nice and crispy.\u201d This is a multistep recipe but perfect for long winter days when you want to flood the house with toasty, irresistible aromas. When you chop the mixed herbs, save the stems and throw them into the blanching water for the vegetables to add flavor.",
- "alternativeHeadline": "This dish is perfect for long winter days when you want to flood the house with toasty, irresistible aromas.",
- "dateModified": "2021-01-11 18:32:43.962000",
- "datePublished": "2021-01-12 04:00:00",
- "keywords": [
- "recipes",
- "healthyish",
- "vegan",
- "herb",
- "apple cider vinegar",
- "kosher salt",
- "carrot",
- "potato",
- "radicchio",
- "mushroom",
- "oyster mushrooms",
- "oil",
- "black pepper",
- "lemon",
- "web"
- ],
- "thumbnailUrl": "https://assets.bonappetit.com/photos/5ffc74b39cbb0a3c54d7400f/1:1/w_1199,h_1199,c_limit/HLY-Maricela-Vega-Grilled%20Mushrooms%20and%20Root%20Vegetables.jpg",
- "publisher": {
- "@context": "https://schema.org",
- "@type": "Organization",
- "name": "Bon App\u00e9tit",
- "logo": {
- "@type": "ImageObject",
- "url": "https://www.bonappetit.com/verso/static/bon-appetit/assets/logo-seo.328de564b950e3d5d1fbe3e42f065290ca1d3844.png",
- "width": "479px",
- "height": "100px"
- },
- "url": "https://www.bonappetit.com"
- },
- "isPartOf": {
- "@type": [
- "CreativeWork",
- "Product"
- ],
- "name": "Bon App\u00e9tit"
- },
- "isAccessibleForFree": true,
- "author": [
- {
- "@type": "Person",
- "name": "Maricela Vega",
- "sameAs": "https://bon-appetit.com/contributor/maricela-vega/"
- }
- ],
- "description": "This dish is perfect for long winter days when you want to flood the house with toasty, irresistible aromas.",
- "image": "grilled-mushrooms-and-root-vegetables.jpg",
- "headline": "Grilled Mushrooms and Root Vegetables",
- "name": "Grilled Mushrooms and Root Vegetables",
- "recipeIngredient": [
- "1 cup Sesame Cr\u00e8me",
- "2 Tbsp. Allium Confit",
- "2 Tbsp. finely chopped mixed tender herbs (parsley, oregano, and/or mint), stems reservedfor blanching vegetables",
- "2 Tbsp. apple cider vinegar",
- "Kosher salt, freshly ground pepper",
- "1 cup finely chopped mixed herbs (parsley, oregano, and/or mint), stems reserved for blanching vegetables",
- "Kosher salt",
- "4 medium carrots (about 1 lb.), preferably rainbow, scrubbed, halved lengthwise, cut crosswise into thirds",
- "4 lb. baby potatoes, halved",
- "1 head of radicchio, coarsely chopped, divided",
- "1 lb. lion\u2019s mane, king trumpet, or oyster mushrooms, cut into 2\" pieces",
- "\u00bd cup Pumpkin Hot Sauce",
- "\u00bd cup grapeseed or vegetable oil",
- "Freshly ground black pepper",
- "1 cup Spiced Pecans",
- "1 lemon, halved"
- ],
- "recipeInstructions": [
- {
- "text": "Pur\u00e9e Sesame Cr\u00e8me, Allium Confit, chopped herbs, and vinegar in a blender on high speed, adding ice water by the tablespoonful as needed to achieve a pourable consistency, until smooth and creamy. Season sauce with salt and pepper."
- },
- {
- "text": "Fill a large pot three quarters full with water, add reserved herb stems, and season heavily with salt. Bring water to a boil, then add carrots and cook until just tender, about 3 minutes. Using a slotted spoon, immediately transfer carrots to a large bowl of ice water and let cool."
- },
- {
- "text": "Place potatoes in same pot and return to a boil. Cook until tender (flesh should be easy to pierce with a fork), about 10 minutes. Using slotted spoon, transfer potatoes to bowl of ice water and let cool. Drain carrots and potatoes; place in a clean large bowl and add half of the radicchio. Place mushrooms in a medium bowl."
- },
- {
- "text": "Whisk Pumpkin Hot Sauce, oil, and chopped herbs in another medium bowl. Pour half of mixture over carrots and potatoes and the other half over mushrooms; toss each to coat. Season with salt and pepper."
- },
- {
- "text": "Prepare a grill for medium-high heat. (Alternatively, heat a large cast-iron skillet over medium-high.) Grill mushrooms, turning occasionally, until deep golden brown and crisp around the edges (or cook in batches, stirring often, if using a skillet), 12\u201314 minutes. Transfer mushrooms to a large shallow serving bowl."
- },
- {
- "text": "Grill carrots, potatoes, and radicchio, turning occasionally, until deep golden brown all over (or cook in batches, tossing often, if using a skillet), about 4 minutes. Transfer vegetables to bowl with mushrooms and toss to combine."
- },
- {
- "text": "To serve, drizzle generously with sesame sauce; top with Spiced Pecans and remaining radicchio. Squeeze juice from each lemon half over."
- }
- ],
- "recipeYield": "4 Servings",
- "url": "https://www.bonappetit.com/recipe/grilled-mushrooms-and-root-vegetables",
- "slug": "grilled-mushrooms-and-root-vegetables",
- "orgURL": "https://www.bonappetit.com/recipe/grilled-mushrooms-and-root-vegetables",
- "categories": [],
- "tags": [],
- "dateAdded": null,
- "notes": [],
- "extras": []
-}
\ No newline at end of file
diff --git a/mealie/db/database.py b/mealie/db/database.py
index 72e02911b..c44bf5d3c 100644
--- a/mealie/db/database.py
+++ b/mealie/db/database.py
@@ -1,7 +1,62 @@
-from db.db_mealplan import _Meals
-from db.db_recipes import _Recipes
-from db.db_settings import _Settings
-from db.db_themes import _Themes
+from db.db_base import BaseDocument
+from db.sql.db_session import create_session
+from db.sql.meal_models import MealPlanModel
+from db.sql.recipe_models import RecipeModel
+from db.sql.settings_models import SiteSettingsModel
+from db.sql.theme_models import SiteThemeModel
+
+"""
+# TODO
+ - [ ] Abstract Classes to use save_new, and update from base models
+ - [ ] Create Category and Tags Table with Many to Many relationship
+"""
+class _Recipes(BaseDocument):
+ def __init__(self) -> None:
+ self.primary_key = "slug"
+ self.sql_model = RecipeModel
+ self.create_session = create_session
+
+ def update_image(self, slug: str, extension: str) -> None:
+ pass
+
+
+class _Meals(BaseDocument):
+ def __init__(self) -> None:
+ self.primary_key = "uid"
+ self.sql_model = MealPlanModel
+ self.create_session = create_session
+
+
+class _Settings(BaseDocument):
+ def __init__(self) -> None:
+ self.primary_key = "name"
+ self.sql_model = SiteSettingsModel
+ self.create_session = create_session
+
+ def save_new(self, main: dict, webhooks: dict) -> str:
+ session = create_session()
+ new_settings = self.sql_model(main.get("name"), webhooks)
+
+ session.add(new_settings)
+ session.commit()
+
+ return new_settings.dict()
+
+
+class _Themes(BaseDocument):
+ def __init__(self) -> None:
+ self.primary_key = "name"
+ self.sql_model = SiteThemeModel
+ self.create_session = create_session
+
+ def update(self, data: dict) -> dict:
+ session, theme_model = self._query_one(
+ match_value=data["name"], match_key="name"
+ )
+
+ theme_model.update(**data)
+ session.commit()
+ session.close()
class Database:
diff --git a/mealie/db/db_base.py b/mealie/db/db_base.py
index e8a9a7281..730c262aa 100644
--- a/mealie/db/db_base.py
+++ b/mealie/db/db_base.py
@@ -1,8 +1,5 @@
-import json
from typing import Union
-import mongoengine
-from app_config import USE_MONGO, USE_SQL
from sqlalchemy.orm.session import Session
from db.sql.db_session import create_session
@@ -13,65 +10,18 @@ class BaseDocument:
def __init__(self) -> None:
self.primary_key: str
self.store: str
- self.document: mongoengine.Document
self.sql_model: SqlAlchemyBase
self.create_session = create_session
- @staticmethod # TODO: Probably Put a version in each class to speed up reads?
- def _unpack_mongo(document) -> dict:
- document = json.loads(document.to_json())
- del document["_id"]
-
- # Recipe Cleanup
- try:
- document["dateAdded"] = document["dateAdded"]["$date"]
- except:
- pass
-
- try:
- document["uid"] = document["uid"]["$uuid"]
- except:
- pass
-
- # Meal Plan
- try:
- document["startDate"] = document["startDate"]["$date"]
- document["endDate"] = document["endDate"]["$date"]
-
- meals = []
- for meal in document["meals"]:
- meal["date"] = meal["date"]["$date"]
- meals.append(meal)
- document["meals"] = meals
- except:
- pass
-
- return document
-
def get_all(self, limit: int = None, order_by: str = None):
- if USE_MONGO:
- if order_by:
- documents = self.document.objects.order_by(str(order_by)).limit(limit)
- elif limit == None:
- documents = self.document.objects()
- else:
- documents = self.document.objects().limit(limit)
+ session = create_session()
+ list = [x.dict() for x in session.query(self.sql_model).all()]
+ session.close()
- docs = [BaseDocument._unpack_mongo(item) for item in documents]
+ if limit == 1:
+ return list[0]
- if limit == 1:
- return docs[0]
- return docs
-
- elif USE_SQL:
- session = create_session()
- list = [x.dict() for x in session.query(self.sql_model).all()]
- session.close()
-
- if limit == 1:
- return list[0]
-
- return list
+ return list
def _query_one(
self, match_value: str, match_key: str = None
@@ -115,77 +65,46 @@ class BaseDocument:
if match_key == None:
match_key = self.primary_key
- if USE_MONGO:
- document = self.document.objects.get(**{str(match_key): match_value})
- db_entry = BaseDocument._unpack_mongo(document)
+ session = self.create_session()
+ result = (
+ session.query(self.sql_model).filter_by(**{match_key: match_value}).one()
+ )
+ db_entry = result.dict()
+ session.close()
- elif USE_SQL:
- session = self.create_session()
- result = (
- session.query(self.sql_model)
- .filter_by(**{match_key: match_value})
- .one()
- )
- db_entry = result.dict()
- session.close()
-
- return db_entry
-
- else:
- raise Exception("No database type established")
-
- if limit == 1 and type(db_entry) == list:
- return db_entry[0]
- else:
- return db_entry
+ return db_entry
def save_new(self, document: dict) -> dict:
- if USE_MONGO:
- new_document = self.document(**document)
- new_document.save()
- return BaseDocument._unpack_mongo(new_document)
- elif USE_SQL:
- session = self.create_session()
- new_document = self.sql_model(**document)
- session.add(new_document)
- return_data = new_document.dict()
- session.commit()
+ session = self.create_session()
+ new_document = self.sql_model(**document)
+ session.add(new_document)
+ return_data = new_document.dict()
+ session.commit()
- return return_data
+
+ session.close()
+ return return_data
def update(self, match_value, new_data) -> dict:
- if USE_MONGO:
- return_data = self.update_mongo(match_value, new_data)
- elif USE_SQL:
- session, entry = self._query_one(match_value=match_value)
- entry.update(session=session, **new_data)
- return_data = entry.dict()
- session.commit()
+ session, entry = self._query_one(match_value=match_value)
+ entry.update(session=session, **new_data)
+ return_data = entry.dict()
+ session.commit()
- session.close()
- else:
- raise Exception("No Database Configured")
+ session.close()
return return_data
def delete(self, primary_key_value) -> dict:
- if USE_MONGO:
- document = self.document.objects.get(
- **{str(self.primary_key): primary_key_value}
- )
+ session = create_session()
- if document:
- document.delete()
- elif USE_SQL:
- session = create_session()
+ result = (
+ session.query(self.sql_model)
+ .filter_by(**{self.primary_key: primary_key_value})
+ .one()
+ )
- result = (
- session.query(self.sql_model)
- .filter_by(**{self.primary_key: primary_key_value})
- .one()
- )
+ session.delete(result)
- session.delete(result)
-
- session.commit()
- session.close()
+ session.commit()
+ session.close()
diff --git a/mealie/db/db_mealplan.py b/mealie/db/db_mealplan.py
deleted file mode 100644
index 96907390f..000000000
--- a/mealie/db/db_mealplan.py
+++ /dev/null
@@ -1,63 +0,0 @@
-from typing import List
-
-from app_config import USE_MONGO, USE_SQL
-
-from db.db_base import BaseDocument
-from db.db_setup import USE_MONGO, USE_SQL
-from db.mongo.meal_models import MealDocument, MealPlanDocument
-from db.sql.db_session import create_session
-from db.sql.meal_models import MealPlanModel
-
-
-class _Meals(BaseDocument):
- def __init__(self) -> None:
- self.primary_key = "uid"
- if USE_SQL:
- self.sql_model = MealPlanModel
- self.create_session = create_session
-
- self.document = MealPlanDocument
-
- @staticmethod
- def _process_meals(meals: List[dict]) -> List[MealDocument]:
- """Turns a list of Meals in dictionary form into a list of
- MealDocuments that can be attached to a MealPlanDocument
-
-
- Args: \n
- meals (List[dict]): From a Pydantic Class in meal_services.py \n
-
- Returns:
- a List of MealDocuments
- """
- meal_docs = []
- for meal in meals:
- meal_doc = MealDocument(**meal)
- meal_docs.append(meal_doc)
-
- return meal_docs
-
- def save_new_mongo(self, plan_data: dict) -> None:
- """Saves a new meal plan into the database
-
- Args: \n
- plan_data (dict): From a Pydantic Class in meal_services.py \n
- """
-
- if USE_MONGO:
- plan_data["meals"] = _Meals._process_meals(plan_data["meals"])
- document = self.document(**plan_data)
-
- document.save()
- elif USE_SQL:
- pass
-
- def update_mongo(self, uid: str, plan_data: dict) -> dict:
- if USE_MONGO:
- document = self.document.objects.get(uid=uid)
- if document:
- new_meals = _Meals._process_meals(plan_data["meals"])
- document.update(set__meals=new_meals)
- document.save()
- elif USE_SQL:
- pass
diff --git a/mealie/db/db_recipes.py b/mealie/db/db_recipes.py
deleted file mode 100644
index 945ee079d..000000000
--- a/mealie/db/db_recipes.py
+++ /dev/null
@@ -1,68 +0,0 @@
-from app_config import USE_MONGO, USE_SQL
-
-from db.db_base import BaseDocument
-from db.mongo.recipe_models import RecipeDocument
-from db.sql.db_session import create_session
-from db.sql.recipe_models import RecipeModel
-
-
-class _Recipes(BaseDocument):
- def __init__(self) -> None:
- self.primary_key = "slug"
- if USE_SQL:
- self.sql_model = RecipeModel
- self.create_session = create_session
- else:
- self.document = RecipeDocument
-
- def save_new_sql(self, recipe_data: dict):
- session = self.create_session()
- new_recipe = self.sql_model(**recipe_data)
- session.add(new_recipe)
- session.commit()
-
- return recipe_data
-
- def update_mongo(self, slug: str, new_data: dict) -> None:
- if USE_MONGO:
- document = self.document.objects.get(slug=slug)
-
- if document:
- document.update(set__name=new_data.get("name"))
- document.update(set__description=new_data.get("description"))
- document.update(set__image=new_data.get("image"))
- document.update(set__recipeYield=new_data.get("recipeYield"))
- document.update(set__recipeIngredient=new_data.get("recipeIngredient"))
- document.update(
- set__recipeInstructions=new_data.get("recipeInstructions")
- )
- document.update(set__totalTime=new_data.get("totalTime"))
-
- document.update(set__slug=new_data.get("slug"))
- document.update(set__categories=new_data.get("categories"))
- document.update(set__tags=new_data.get("tags"))
- document.update(set__notes=new_data.get("notes"))
- document.update(set__orgURL=new_data.get("orgURL"))
- document.update(set__rating=new_data.get("rating"))
- document.update(set__extras=new_data.get("extras"))
- document.save()
-
- return new_data
- # elif USE_SQL:
- # session, recipe = self._query_one(match_value=slug)
- # recipe.update(session=session, **new_data)
- # recipe_dict = recipe.dict()
- # session.commit()
-
- # session.close()
-
- # return recipe_dict
-
- def update_image(self, slug: str, extension: str) -> None:
- if USE_MONGO:
- document = self.document.objects.get(slug=slug)
-
- if document:
- document.update(set__image=f"{slug}.{extension}")
- elif USE_SQL:
- pass
diff --git a/mealie/db/db_settings.py b/mealie/db/db_settings.py
deleted file mode 100644
index 2f3089500..000000000
--- a/mealie/db/db_settings.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from app_config import USE_MONGO, USE_SQL
-
-from db.db_base import BaseDocument
-from db.db_setup import USE_MONGO, USE_SQL
-from db.mongo.settings_models import SiteSettingsDocument, WebhooksDocument
-from db.sql.db_session import create_session
-from db.sql.settings_models import SiteSettingsModel
-
-
-class _Settings(BaseDocument):
- def __init__(self) -> None:
-
- self.primary_key = "name"
-
- if USE_SQL:
- self.sql_model = SiteSettingsModel
- self.create_session = create_session
-
- self.document = SiteSettingsDocument
-
- def save_new(self, main: dict, webhooks: dict) -> str:
-
- if USE_MONGO:
- main["webhooks"] = WebhooksDocument(**webhooks)
- new_doc = self.document(**main)
- return new_doc.save()
-
- elif USE_SQL:
- session = create_session()
- new_settings = self.sql_model(main.get("name"), webhooks)
-
- session.add(new_settings)
- session.commit()
-
- return new_settings.dict()
-
- def update_mongo(self, name: str, new_data: dict) -> dict:
- if USE_MONGO:
- document = self.document.objects.get(name=name)
- if document:
- document.update(set__webhooks=WebhooksDocument(**new_data["webhooks"]))
- document.save()
- elif USE_SQL:
- return
diff --git a/mealie/db/db_setup.py b/mealie/db/db_setup.py
index 3f816564b..f05ab8940 100644
--- a/mealie/db/db_setup.py
+++ b/mealie/db/db_setup.py
@@ -1,4 +1,4 @@
-from app_config import SQLITE_FILE, USE_MONGO, USE_SQL
+from app_config import SQLITE_FILE, USE_SQL
from db.sql.db_session import globa_init as sql_global_init
@@ -10,7 +10,5 @@ if USE_SQL:
pass
-elif USE_MONGO:
- from db.mongo.mongo_setup import global_init as mongo_global_init
-
- mongo_global_init()
+else:
+ raise Exception("Cannot identify database type")
diff --git a/mealie/db/db_themes.py b/mealie/db/db_themes.py
deleted file mode 100644
index 14a378b76..000000000
--- a/mealie/db/db_themes.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from app_config import USE_MONGO, USE_SQL
-
-from db.db_base import BaseDocument
-from db.db_setup import USE_MONGO, USE_SQL
-from db.mongo.settings_models import SiteThemeDocument, ThemeColorsDocument
-from db.sql.db_session import create_session
-from db.sql.theme_models import SiteThemeModel
-
-
-class _Themes(BaseDocument):
- def __init__(self) -> None:
- self.primary_key = "name"
- if USE_SQL:
- self.sql_model = SiteThemeModel
- self.create_session = create_session
- else:
- self.document = SiteThemeDocument
-
- def save_new(self, theme_data: dict) -> None:
- if USE_MONGO:
- theme_data["colors"] = ThemeColorsDocument(**theme_data["colors"])
-
- document = self.document(**theme_data)
-
- document.save()
- elif USE_SQL:
- session = self.create_session()
- new_theme = self.sql_model(**theme_data)
-
- session.add(new_theme)
- session.commit()
-
- return_data = new_theme.dict()
-
- session.close()
- return return_data
-
- def update(self, data: dict) -> dict:
- if USE_MONGO:
- colors = ThemeColorsDocument(**data["colors"])
- theme_document = self.document.objects.get(name=data.get("name"))
-
- if theme_document:
- theme_document.update(set__colors=colors)
- theme_document.save()
- else:
- raise Exception("No database entry was found to update")
-
- elif USE_SQL:
- session, theme_model = self._query_one(
- match_value=data["name"], match_key="name"
- )
-
- theme_model.update(**data)
- session.commit()
- session.close()
diff --git a/mealie/db/mongo/meal_models.py b/mealie/db/mongo/meal_models.py
deleted file mode 100644
index edfece78f..000000000
--- a/mealie/db/mongo/meal_models.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import uuid
-
-import mongoengine
-
-
-class MealDocument(mongoengine.EmbeddedDocument):
- slug = mongoengine.StringField()
- name = mongoengine.StringField()
- date = mongoengine.DateField()
- dateText = mongoengine.StringField()
- image = mongoengine.StringField()
- description = mongoengine.StringField()
-
-
-class MealPlanDocument(mongoengine.Document):
- uid = mongoengine.UUIDField(default=uuid.uuid1)
- startDate = mongoengine.DateField(required=True)
- endDate = mongoengine.DateField(required=True)
- meals = mongoengine.ListField(required=True)
-
- meta = {
- "db_alias": "core",
- "collection": "meals",
- }
diff --git a/mealie/db/mongo/mongo_setup.py b/mealie/db/mongo/mongo_setup.py
deleted file mode 100644
index da584396e..000000000
--- a/mealie/db/mongo/mongo_setup.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import mongoengine
-from app_config import DB_HOST, DB_PASSWORD, DB_PORT, DB_USERNAME, MEALIE_DB_NAME
-from utils.logger import logger
-
-
-def global_init():
- mongoengine.register_connection(
- alias="core",
- name=MEALIE_DB_NAME,
- host=DB_HOST,
- port=int(DB_PORT),
- username=DB_USERNAME,
- password=DB_PASSWORD,
- authentication_source="admin",
- )
-
- logger.info("Mongo Data Initialized")
diff --git a/mealie/db/mongo/recipe_models.py b/mealie/db/mongo/recipe_models.py
deleted file mode 100644
index 02b4a9ba7..000000000
--- a/mealie/db/mongo/recipe_models.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import datetime
-
-import mongoengine
-
-
-class RecipeDocument(mongoengine.Document):
- # Standard Schema
- # id = mongoengine.UUIDField(primary_key=True)
- name = mongoengine.StringField(required=True)
- description = mongoengine.StringField(required=True)
- image = mongoengine.StringField(required=False)
- recipeYield = mongoengine.StringField(required=True, default="")
- recipeIngredient = mongoengine.ListField(required=True, default=[])
- recipeInstructions = mongoengine.ListField(requiredd=True, default=[])
- totalTime = mongoengine.StringField(required=False)
-
- # Mealie Specific
- slug = mongoengine.StringField(required=True, unique=True)
- categories = mongoengine.ListField(default=[])
- tags = mongoengine.ListField(default=[])
- dateAdded = mongoengine.DateTimeField(binary=True, default=datetime.date.today)
- notes = mongoengine.ListField(default=[])
- rating = mongoengine.IntField(required=True, default=0)
- orgURL = mongoengine.URLField(required=False)
- extras = mongoengine.DictField(required=False)
-
- meta = {
- "db_alias": "core",
- "collection": "recipes",
- }
-
-
-if __name__ == "__main__":
- pass
diff --git a/mealie/db/mongo/settings_models.py b/mealie/db/mongo/settings_models.py
deleted file mode 100644
index d9ddaddea..000000000
--- a/mealie/db/mongo/settings_models.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import mongoengine
-
-
-class WebhooksDocument(mongoengine.EmbeddedDocument):
- webhookURLs = mongoengine.ListField(required=False, default=[])
- webhookTime = mongoengine.StringField(required=False, default="00:00")
- enabled = mongoengine.BooleanField(required=False, default=False)
-
-
-class SiteSettingsDocument(mongoengine.Document):
- name = mongoengine.StringField(require=True, default="main", unique=True)
- webhooks = mongoengine.EmbeddedDocumentField(WebhooksDocument, required=True)
-
- meta = {
- "db_alias": "core",
- "collection": "settings",
- }
-
-
-class ThemeColorsDocument(mongoengine.EmbeddedDocument):
- primary = mongoengine.StringField(require=True)
- accent = mongoengine.StringField(require=True)
- secondary = mongoengine.StringField(require=True)
- success = mongoengine.StringField(require=True)
- info = mongoengine.StringField(require=True)
- warning = mongoengine.StringField(require=True)
- error = mongoengine.StringField(require=True)
-
-
-class SiteThemeDocument(mongoengine.Document):
- name = mongoengine.StringField(require=True, unique=True)
- colors = mongoengine.EmbeddedDocumentField(ThemeColorsDocument, required=True)
-
- meta = {
- "db_alias": "core",
- "collection": "themes",
- }
diff --git a/mealie/db/mongo/user_models.py b/mealie/db/mongo/user_models.py
deleted file mode 100644
index f6c771f2f..000000000
--- a/mealie/db/mongo/user_models.py
+++ /dev/null
@@ -1,6 +0,0 @@
-
-# import mongoengine
-
-# class User(mongoengine.Document):
-# username: mongoengine.EmailField()
-# password: mongoengine.ReferenceField
\ No newline at end of file
diff --git a/mealie/models/backup_models.py b/mealie/models/backup_models.py
index 8502c3cf0..21bf661b6 100644
--- a/mealie/models/backup_models.py
+++ b/mealie/models/backup_models.py
@@ -4,15 +4,32 @@ from typing import List, Optional
from pydantic import BaseModel
+class BackupOptions(BaseModel):
+ recipes: bool = True
+ settings: bool = True
+ themes: bool = True
+
+ class Config:
+ schema_extra = {
+ "example": {
+ "recipes": True,
+ "settings": True,
+ "themes": True,
+ }
+ }
+
+
class BackupJob(BaseModel):
tag: Optional[str]
- template: Optional[List[str]]
+ options: BackupOptions
+ templates: Optional[List[str]] = []
class Config:
schema_extra = {
"example": {
"tag": "July 23rd 2021",
- "template": "recipes.md",
+ "options": BackupOptions,
+ "template": ["recipes.md"],
}
}
@@ -49,13 +66,13 @@ class ImportJob(BaseModel):
settings: bool = False
class Config:
- schema_extra = {
- "example": {
- "name": "my_local_backup.zip",
- "recipes": True,
- "force": False,
- "rebase": False,
- "themes": False,
- "settings": False
- }
+ schema_extra = {
+ "example": {
+ "name": "my_local_backup.zip",
+ "recipes": True,
+ "force": False,
+ "rebase": False,
+ "themes": False,
+ "settings": False,
}
+ }
diff --git a/mealie/routes/backup_routes.py b/mealie/routes/backup_routes.py
index 823543192..f29c560ce 100644
--- a/mealie/routes/backup_routes.py
+++ b/mealie/routes/backup_routes.py
@@ -19,7 +19,7 @@ def available_imports():
backup = LocalBackup(name=archive.name, date=archive.stat().st_ctime)
imports.append(backup)
- for template in TEMPLATE_DIR.glob("*.md"):
+ for template in TEMPLATE_DIR.glob("*.*"):
templates.append(template.name)
imports.sort(key=operator.attrgetter("date"), reverse=True)
@@ -30,7 +30,13 @@ def available_imports():
@router.post("/api/backups/export/database/", status_code=201)
def export_database(data: BackupJob):
"""Generates a backup of the recipe database in json format."""
- export_path = backup_all(data.tag, data.template)
+ export_path = backup_all(
+ tag=data.tag,
+ templates=data.templates,
+ export_recipes=data.options.recipes,
+ export_settings=data.options.settings,
+ export_themes=data.options.themes,
+ )
try:
return SnackResponse.success("Backup Created at " + export_path)
except:
diff --git a/mealie/services/backups/exports.py b/mealie/services/backups/exports.py
index dbe19f3f8..28ed19baf 100644
--- a/mealie/services/backups/exports.py
+++ b/mealie/services/backups/exports.py
@@ -3,11 +3,11 @@ import shutil
from datetime import datetime
from pathlib import Path
+from app_config import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR
from jinja2 import Template
from services.meal_services import MealPlan
from services.recipe_services import Recipe
from services.settings_services import SiteSettings, SiteTheme
-from app_config import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR
from utils.logger import logger
@@ -123,15 +123,26 @@ class ExportDatabase:
return str(zip_path.absolute()) + ".zip"
-def backup_all(tag=None, templates=None):
+def backup_all(
+ tag=None,
+ templates=None,
+ export_recipes=True,
+ export_settings=True,
+ export_themes=True,
+):
db_export = ExportDatabase(tag=tag, templates=templates)
- db_export.export_recipes()
- db_export.export_images()
- db_export.export_settings()
- db_export.export_themes()
- db_export.export_meals()
- #
+ if export_recipes:
+ db_export.export_recipes()
+ db_export.export_images()
+
+ if export_settings:
+ db_export.export_settings()
+
+ if export_themes:
+ db_export.export_themes()
+ # db_export.export_meals()
+
return db_export.finish_export()
diff --git a/mealie/services/image_services.py b/mealie/services/image_services.py
index 8b2432972..4200a186a 100644
--- a/mealie/services/image_services.py
+++ b/mealie/services/image_services.py
@@ -2,9 +2,7 @@ import shutil
from pathlib import Path
import requests
-
-CWD = Path(__file__).parent
-IMG_DIR = CWD.parent.joinpath("data", "img")
+from app_config import IMG_DIR
def read_image(recipe_slug: str) -> Path:
diff --git a/mealie/services/scrape_services.py b/mealie/services/scrape_services.py
index 0bc08cb4a..6d72c59ba 100644
--- a/mealie/services/scrape_services.py
+++ b/mealie/services/scrape_services.py
@@ -57,7 +57,17 @@ def normalize_yield(yld) -> str:
return yld
+def normalize_time(time_entry) -> str:
+ if type(time_entry) == type(None):
+ return None
+ elif type(time_entry) != str:
+ return str(time_entry)
+
+
def normalize_data(recipe_data: dict) -> dict:
+ recipe_data["totalTime"] = normalize_time(recipe_data.get("totalTime"))
+ recipe_data["prepTime"] = normalize_time(recipe_data.get("prepTime"))
+ recipe_data["performTime"] = normalize_time(recipe_data.get("performTime"))
recipe_data["recipeYield"] = normalize_yield(recipe_data.get("recipeYield"))
recipe_data["recipeInstructions"] = normalize_instructions(
recipe_data["recipeInstructions"]
diff --git a/mealie/utils/api_docs.py b/mealie/utils/api_docs.py
index 823afee0a..859b89043 100644
--- a/mealie/utils/api_docs.py
+++ b/mealie/utils/api_docs.py
@@ -1,6 +1,6 @@
import json
-from app_config import BASE_DIR
+from app_config import DATA_DIR
"""Script to export the ReDoc documentation page into a standalone HTML file."""
@@ -33,7 +33,7 @@ HTML_TEMPLATE = """
def generate_api_docs(app):
- out_dir = BASE_DIR.joinpath(".temp")
+ out_dir = DATA_DIR.joinpath(".temp")
out_dir.mkdir(parents=True, exist_ok=True)
out_path = out_dir.joinpath("index.html")
with open(out_path, "w") as fd:
diff --git a/mealie/utils/logger.py b/mealie/utils/logger.py
index f0780e1a3..03fa87933 100644
--- a/mealie/utils/logger.py
+++ b/mealie/utils/logger.py
@@ -1,16 +1,17 @@
import logging
from pathlib import Path
+from app_config import DATA_DIR
+
LOGGER_LEVEL = "INFO"
CWD = Path(__file__).parent
-LOGGER_FILE = CWD.parent.joinpath("data", "mealie.log")
+LOGGER_FILE = DATA_DIR.joinpath("mealie.log")
logging.basicConfig(
level=LOGGER_LEVEL,
format="%(asctime)s %(levelname)s: %(message)s",
datefmt="%d-%b-%y %H:%M:%S",
- filename=LOGGER_FILE,
)
logger = logging.getLogger(__name__)
diff --git a/poetry.lock b/poetry.lock
index 50190205d..1907485b3 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -395,17 +395,6 @@ BeautifulSoup4 = ">=4.6.0"
html5lib = ">=1.0.1"
requests = ">=2.18.4"
-[[package]]
-name = "mongoengine"
-version = "0.22.1"
-description = "MongoEngine is a Python Object-Document Mapper for working with MongoDB."
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-pymongo = ">=3.4,<4.0"
-
[[package]]
name = "mypy-extensions"
version = "0.4.3"
@@ -480,24 +469,6 @@ isort = ">=4.2.5,<6"
mccabe = ">=0.6,<0.7"
toml = ">=0.7.1"
-[[package]]
-name = "pymongo"
-version = "3.11.2"
-description = "Python driver for MongoDB "
-category = "main"
-optional = false
-python-versions = "*"
-
-[package.extras]
-aws = ["pymongo-auth-aws (<2.0.0)"]
-encryption = ["pymongocrypt (<2.0.0)"]
-gssapi = ["pykerberos"]
-ocsp = ["pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)"]
-snappy = ["python-snappy"]
-srv = ["dnspython (>=1.16.0,<1.17.0)"]
-tls = ["ipaddress"]
-zstd = ["zstandard"]
-
[[package]]
name = "pyparsing"
version = "2.4.7"
@@ -864,7 +835,7 @@ python-versions = "*"
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
-content-hash = "41e74af4ccdf3d291de04842718297a83774c80da335894e1eb0fcacb0fddac5"
+content-hash = "49f7f72b21beae20519bf5c1e86ab21391bbaa7c5fd47d455ee898d86b7d6ee0"
[metadata.files]
aiofiles = [
@@ -1096,10 +1067,6 @@ mccabe = [
mf2py = [
{file = "mf2py-1.1.2.tar.gz", hash = "sha256:84f1f8f2ff3f1deb1c30be497e7ccd805452996a662fd4a77f09e0105bede2c9"},
]
-mongoengine = [
- {file = "mongoengine-0.22.1-py3-none-any.whl", hash = "sha256:4d5efb8b6ddffc087d0741fe56fe30637b5629e33c8fae8de53a907ec20c43dd"},
- {file = "mongoengine-0.22.1.tar.gz", hash = "sha256:620d13db551c849402eb3c362878934f5260ec0028fff2a5d81bf53b21d91572"},
-]
mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
@@ -1148,72 +1115,6 @@ pylint = [
{file = "pylint-2.6.0-py3-none-any.whl", hash = "sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f"},
{file = "pylint-2.6.0.tar.gz", hash = "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210"},
]
-pymongo = [
- {file = "pymongo-3.11.2-cp27-cp27m-macosx_10_14_intel.whl", hash = "sha256:9be785bd4e1ba0148fb00ca84e4dbfbd1c74df3af3a648559adc60b0782f34de"},
- {file = "pymongo-3.11.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:646d4d30c5aa7c0ddbfe9b990f0f77a88621024a21ad0b792bd9d58caa9611f0"},
- {file = "pymongo-3.11.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:8d669c720891781e7c82d412cad39f9730ef277e3957b48a3344dae47d3caa03"},
- {file = "pymongo-3.11.2-cp27-cp27m-win32.whl", hash = "sha256:ce53c00be204ec4428d3c1f3c478ae89d388efec575544c27f57b61e9fa4a7f2"},
- {file = "pymongo-3.11.2-cp27-cp27m-win_amd64.whl", hash = "sha256:82d5ded5834b6c92380847860eb28dcaf20b847a27cee5811c4aaceef87fd280"},
- {file = "pymongo-3.11.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:fcc66d17a3363b7bd6d2655de8706e25a3cd1be2bd1b8e8d8a5c504a6ef893ae"},
- {file = "pymongo-3.11.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:b875bb4b438931dce550e170bfb558597189b8d0160f4ac60f14a21955161699"},
- {file = "pymongo-3.11.2-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:6700e251c6396cc05d7460dc05ef8e19e60a7b53b62c007725b48e123aaa2b1c"},
- {file = "pymongo-3.11.2-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:c046e09e886f4539f8626afba17fa8f2e6552731f9384e2827154e3e3b7fda4e"},
- {file = "pymongo-3.11.2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:4942a5659ae927bb764a123a6409870ca5dd572d83b3bfb71412c9a191bbf792"},
- {file = "pymongo-3.11.2-cp34-cp34m-win32.whl", hash = "sha256:422069f2cebf58c9dd9e8040b4768f7be4f228c95bc4505e8fa8e7b4f7191ad8"},
- {file = "pymongo-3.11.2-cp34-cp34m-win_amd64.whl", hash = "sha256:44376a657717de8847d5d71a9305f3595c7e78c91ac77edbb87058d12ede87a6"},
- {file = "pymongo-3.11.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:36b9b98a39565a8f33803c81569442b35e749a72fb1aa7d0bcdb1a33052f8bcc"},
- {file = "pymongo-3.11.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:a118a1df7280ffab7fe0f3eab325868339ff1c4d5b8e0750db0f0a796da8f849"},
- {file = "pymongo-3.11.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c812b6e53344e92f10f12235219fb769c491a4a87a02c9c3f93fe632e493bda8"},
- {file = "pymongo-3.11.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:cc421babc687dc52ce0fc19787b2404518ca749d9db59576100946ff886f38ed"},
- {file = "pymongo-3.11.2-cp35-cp35m-manylinux2014_i686.whl", hash = "sha256:6aac7e0e8de92f11a410eb68c24a2decbac6f094e82fd95d22546d0168e7a18b"},
- {file = "pymongo-3.11.2-cp35-cp35m-manylinux2014_ppc64le.whl", hash = "sha256:c6cf288c9e03195d8e12b72a6388b32f18a5e9c2545622417a963e428e1fe496"},
- {file = "pymongo-3.11.2-cp35-cp35m-manylinux2014_s390x.whl", hash = "sha256:5980509801cbd2942df31714d055d89863684b4de26829c349362e610a48694e"},
- {file = "pymongo-3.11.2-cp35-cp35m-manylinux2014_x86_64.whl", hash = "sha256:264843ce2af0640994a4331148ef5312989bc004678c457460758766c9b4decc"},
- {file = "pymongo-3.11.2-cp35-cp35m-win32.whl", hash = "sha256:ef18aa15b1aa18c42933deed5233b3284186e9ed85c25d2704ceff5099a3964c"},
- {file = "pymongo-3.11.2-cp35-cp35m-win_amd64.whl", hash = "sha256:019ddf7ced8e42cc6c8c608927c799be8097237596c94ffe551f6ef70e55237e"},
- {file = "pymongo-3.11.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:96c6aef7ffb0d37206c0342abb82d874fa8cdc344267277ec63f562b94335c22"},
- {file = "pymongo-3.11.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:82f6e42ba40440a7e0a20bfe12465a3b62d65966a4c7ad1a21b36ffff88de6fe"},
- {file = "pymongo-3.11.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5ad7b96c27acd7e256b33f47cf3d23bd7dd902f9c033ae43f32ffcbc37bebafd"},
- {file = "pymongo-3.11.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:45728e6aae3023afb5b2829586d1d2bfd9f0d71cfd7d3c924b71a5e9aef617a8"},
- {file = "pymongo-3.11.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:ce9964c117cbe5cf6269f30a2b334d28675956e988b7dbd0b4f7370924afda2e"},
- {file = "pymongo-3.11.2-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:1222025db539641071a1b67f6950f65a6342a39db5b454bf306abd6954f1ad8a"},
- {file = "pymongo-3.11.2-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:fc4946acb6cdada08f60aca103b61334995523da65be5fe816ea8571c9967d46"},
- {file = "pymongo-3.11.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:76579fcf77052b39796fe4a11818d1289dd48cffe15951b3403288fa163c29f6"},
- {file = "pymongo-3.11.2-cp36-cp36m-win32.whl", hash = "sha256:d6f82e86896a8db70e8ae8fa4b7556a0f188f1d8a6c53b2ba229889d55a59308"},
- {file = "pymongo-3.11.2-cp36-cp36m-win_amd64.whl", hash = "sha256:082832a59da18efab4d9148cca396451bac99da9757f31767f706e828b5b8500"},
- {file = "pymongo-3.11.2-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:3646c2286d889618d43e01d9810ac1fc17709d2b4dec61366df5edc8ba228b3e"},
- {file = "pymongo-3.11.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:3ec8f8e106a1476659d8c020228b45614daabdbdb6c6454a843a1d4f77d13339"},
- {file = "pymongo-3.11.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:202ea1d4edc8a5439fc179802d807b49e7e563207fea5610779e56674ac770c6"},
- {file = "pymongo-3.11.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b50af6701b4a5288b77fb4db44a363aa9485caf2c3e7a40c0373fd45e34440af"},
- {file = "pymongo-3.11.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:46792b71ab802d9caf1fc9d52e83399ef8e1a36e91eef4d827c06e36b8df2230"},
- {file = "pymongo-3.11.2-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:21d7b48567a1c80f9266e0ab61c1218a31279d911da345679188733e354f81cc"},
- {file = "pymongo-3.11.2-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:29a6840c2ac778010547cad5870f3db2e080ad7fad01197b07fff993c08692c8"},
- {file = "pymongo-3.11.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:6122470dfa61d4909b75c98012c1577404ba4ab860d0095e0c6980560cb3711f"},
- {file = "pymongo-3.11.2-cp37-cp37m-win32.whl", hash = "sha256:047cc2007b280672ddfdf2e7b862aad8d898f481f65bbc9067bfa4e420a019a9"},
- {file = "pymongo-3.11.2-cp37-cp37m-win_amd64.whl", hash = "sha256:1580fad512c678b720784e5c9018621b1b3bd37fb5b1633e874738862d6435c7"},
- {file = "pymongo-3.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e69fa025a1db189443428f345fea5555d16413df6addc056e17bb8c9794b006"},
- {file = "pymongo-3.11.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:813db97e9955b6b1b50b5cebd18cb148580603bb9b067ea4c5cc656b333bc906"},
- {file = "pymongo-3.11.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:523804bd8fcb5255508052b50073a27c701b90a73ea46e29be46dad5fe01bde6"},
- {file = "pymongo-3.11.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fa741e9c805567239f845c7e9a016aff797f9bb02ff9bc8ccd2fbd9eafefedd4"},
- {file = "pymongo-3.11.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:b95d2c2829b5956bf54d9a22ffec911dea75abf0f0f7e0a8a57423434bfbde91"},
- {file = "pymongo-3.11.2-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:6e7a6057481a644970e43475292e1c0af095ca39a20fe83781196bd6e6690a38"},
- {file = "pymongo-3.11.2-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:540dafd6f4a0590fc966465c726b80fa7c0804490c39786ef29236fe68c94401"},
- {file = "pymongo-3.11.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:d9d3ae537f61011191b2fd6f8527b9f9f8a848b37d4c85a0f7bb28004c42b546"},
- {file = "pymongo-3.11.2-cp38-cp38-win32.whl", hash = "sha256:047c325c4a96e7be7d11acf58639bcf71a81ca212d9c6590e3369bc28678647a"},
- {file = "pymongo-3.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:b4294ddf76452459433ecfa6a93258608b5e462c76ef15e4695ed5e2762f009f"},
- {file = "pymongo-3.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:061d59f525831c4051af0b6dbafa62b0b8b168d4ef5b6e3c46d0811b8499d100"},
- {file = "pymongo-3.11.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:ed98683d8f01f1c46ef2d02469e04e9a8fe9a73a9741a4e6e66677a73b59bec8"},
- {file = "pymongo-3.11.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7f0c507e1f108790840d6c4b594019ebf595025c324c9f7e9c9b2b15b41f884e"},
- {file = "pymongo-3.11.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9d19843568df9d263dc92ae4cc2279879add8a26996473f9155590cac635b321"},
- {file = "pymongo-3.11.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:6175fd105da74a09adb38f93be96e1f64873294c906e5e722cbbc5bd10c44e3b"},
- {file = "pymongo-3.11.2-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:944ed467feb949e103555863fa934fb84216a096b0004ca364d3ddf9d18e2b9e"},
- {file = "pymongo-3.11.2-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:4be4fe9d18523da98deeb0b554ac76e1dc1562ee879d62572b34dda8593efcc1"},
- {file = "pymongo-3.11.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:270a1f6a331eac3a393090af06df68297cb31a8b2df0bdcbd97dc613c5758e78"},
- {file = "pymongo-3.11.2-cp39-cp39-win32.whl", hash = "sha256:e565d1e4388765c135052717f15f9e0314f9d172062444c6b3fc0002e93ed04b"},
- {file = "pymongo-3.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:0a53a751d977ad02f1bd22ddb6288bb4816c4758f44a50225462aeeae9cbf6a0"},
- {file = "pymongo-3.11.2-py2.7-macosx-10.14-intel.egg", hash = "sha256:c1d1992bbdf363b22b5a9543ab7d7c6f27a1498826d50d91319b803ddcf1142e"},
- {file = "pymongo-3.11.2.tar.gz", hash = "sha256:c2b67881392a9e85aa108e75f62cdbe372d5a3f17ea5f8d3436dcf4662052f14"},
-]
pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
diff --git a/pyproject.toml b/pyproject.toml
index b443b13e1..2d7167f38 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,7 +20,6 @@ APScheduler = "^3.6.3"
SQLAlchemy = "^1.3.22"
Jinja2 = "^2.11.2"
python-dotenv = "^0.15.0"
-mongoengine = "^0.22.1"
python-slugify = "^4.0.1"
requests = "^2.25.1"
PyYAML = "^5.3.1"