add base for meal-plan categories

This commit is contained in:
hay-kot 2021-02-13 12:10:09 -09:00
commit d9b9b36747
20 changed files with 133 additions and 31 deletions

View file

@ -11,8 +11,6 @@
</span>
</v-card-title>
<v-divider></v-divider>
<HomePageSettings />
<v-divider></v-divider>
<v-card-text>
<h2 class="mt-1 mb-4">{{ $t("settings.language") }}</h2>
<v-row>
@ -30,6 +28,8 @@
</v-row>
</v-card-text>
<v-divider></v-divider>
<HomePageSettings />
<v-divider></v-divider>
</v-card>
</template>
@ -59,6 +59,9 @@ export default {
this.langOptions = this.$store.getters.getAllLangs;
this.selectedLang = this.$store.getters.getActiveLang;
},
removeCategory(index) {
this.value.categories.splice(index, 1);
},
},
};
</script>

View file

@ -1,9 +1,45 @@
<template>
<v-card>
<v-card-title class="headline">
{{ $t("settings.webhooks.meal-planner-webhooks") }}
{{ $t("meal-plan.meal-planner") }}
</v-card-title>
<v-divider></v-divider>
<v-card-text>
<h2 class="mt-1">{{ $t("recipe.categories") }}</h2>
<v-row>
<v-col sm="12" md="6">
<v-select
v-model="planCategories"
:items="categories"
item-text="name"
item-value="name"
label="Allowed Categories"
multiple
chips
hint="Only recipes with these categories will be used in Meal Plans"
persistent-hint
>
<template v-slot:selection="data">
<v-chip
:input-value="data.selected"
close
@click:close="removeCategory(data.index)"
color="secondary"
dark
>
{{ data.item.name }}
</v-chip>
</template>
</v-select>
</v-col>
</v-row>
</v-card-text>
<v-divider> </v-divider>
<v-card-text>
<h2 class="mt-1 mb-4">
{{ $t("settings.webhooks.meal-planner-webhooks") }}
</h2>
<p>
{{
$t(
@ -68,21 +104,29 @@ export default {
webhooks: [],
enabled: false,
time: "",
planCategories: [],
};
},
mounted() {
this.getSiteSettings();
},
computed: {
categories() {
return this.$store.getters.getCategories;
},
},
methods: {
saveTime(value) {
this.time = value;
},
async getSiteSettings() {
let settings = await api.settings.requestAll();
console.log(settings);
this.webhooks = settings.webhooks.webhookURLs;
this.name = settings.name;
this.time = settings.webhooks.webhookTime;
this.enabled = settings.webhooks.enabled;
this.planCategories = settings.planCategories;
},
addWebhook() {
this.webhooks.push(" ");
@ -93,6 +137,7 @@ export default {
saveWebhooks() {
const body = {
name: this.name,
planCategories: this.planCategories,
webhooks: {
webhookURLs: this.webhooks,
webhookTime: this.time,
@ -104,6 +149,9 @@ export default {
testWebhooks() {
api.settings.testWebhooks();
},
removeCategory(index) {
this.planCategories.splice(index, 1);
},
},
};
</script>

View file

@ -45,6 +45,7 @@
},
"meal-plan": {
"dinner-this-week": "Dinner This Week",
"meal-planner": "Meal Planner",
"dinner-today": "Dinner Today",
"planner": "Planner",
"edit-meal-plan": "Edit Meal Plan",

View file

@ -16,7 +16,7 @@
<General />
<Theme class="mt-2" />
<Backup class="mt-2" />
<Webhooks class="mt-2" />
<MealPlanner class="mt-2" />
<Migration class="mt-2" />
<p class="text-center my-2">
{{ $t("settings.current") }}
@ -41,7 +41,7 @@
<script>
import Backup from "../components/Settings/Backup";
import General from "../components/Settings/General";
import Webhooks from "../components/Settings/Webhook";
import MealPlanner from "../components/Settings/MealPlanner";
import Theme from "../components/Settings/Theme";
import Migration from "../components/Settings/Migration";
import api from "@/api";
@ -50,7 +50,7 @@ import axios from "axios";
export default {
components: {
Backup,
Webhooks,
MealPlanner,
Theme,
Migration,
General,

View file

@ -29,6 +29,7 @@ const store = new Vuex.Store({
// All Recipe Data Store
recentRecipes: [],
allRecipes: [],
mealPlanCategories: [],
},
mutations: {
@ -44,6 +45,11 @@ const store = new Vuex.Store({
setRecentRecipes(state, payload) {
state.recentRecipes = payload;
},
setMealPlanCategories(state, payload) {
console.log(payload);
state.mealPlanCategories = payload;
},
},
actions: {
@ -69,6 +75,7 @@ const store = new Vuex.Store({
getSnackType: state => state.snackType,
getRecentRecipes: state => state.recentRecipes,
getMealPlanCategories: state => state.mealPlanCategories,
},
});

View file

@ -17,7 +17,7 @@ dotenv.load_dotenv(ENV)
# General
APP_VERSION = "v0.2.1"
DB_VERSION = "v0.2.0"
DB_VERSION = "v0.2.1"
PRODUCTION = os.environ.get("ENV")
PORT = int(os.getenv("mealie_port", 9000))
API = os.getenv("api_docs", True)

View file

@ -15,7 +15,7 @@ from db.sql.theme_models import SiteThemeModel
class _Recipes(BaseDocument):
def __init__(self) -> None:
self.primary_key = "slug"
self.sql_model = RecipeModel
self.sql_model: RecipeModel = RecipeModel
def update_image(self, session: Session, slug: str, extension: str = None) -> str:
entry: RecipeModel = self._query_one(session, match_value=slug)
@ -48,15 +48,6 @@ class _Settings(BaseDocument):
self.primary_key = "name"
self.sql_model = SiteSettingsModel
def create(self, session: Session, main: dict, webhooks: dict) -> str:
new_settings = self.sql_model(main.get("name"), webhooks)
session.add(new_settings)
return_data = new_settings.dict()
session.commit()
return return_data
class _Themes(BaseDocument):
def __init__(self) -> None:

View file

@ -85,6 +85,13 @@ class Category(SqlAlchemyBase):
"recipes": [x.dict() for x in self.recipes],
}
def dict_no_recipes(self):
return {
"id": self.id,
"slug": self.slug,
"name": self.name,
}
class Tag(SqlAlchemyBase):
__tablename__ = "tags"

View file

@ -1,27 +1,54 @@
import sqlalchemy as sa
import sqlalchemy.orm as orm
from db.sql.model_base import BaseMixins, SqlAlchemyBase
from db.sql.recipe_models import Category
class SiteSettingsModel(SqlAlchemyBase):
class SiteSettingsModel(SqlAlchemyBase, BaseMixins):
__tablename__ = "site_settings"
name = sa.Column(sa.String, primary_key=True)
planCategories = orm.relationship(
"MealCategory", uselist=True, cascade="all, delete"
)
webhooks = orm.relationship("WebHookModel", uselist=False, cascade="all, delete")
def __init__(self, name: str = None, webhooks: dict = None, session=None) -> None:
def __init__(
self, name: str = None, webhooks: dict = None, planCategories=[], session=None
) -> None:
self.name = name
self.planCategories = [MealCategory(cat) for cat in planCategories]
self.webhooks = WebHookModel(**webhooks)
def update(self, session, name, webhooks: dict) -> dict:
def update(self, session, name, webhooks: dict, planCategories=[]) -> dict:
self._sql_remove_list(session, [MealCategory], self.name)
self.name = name
self.planCategories = [MealCategory(x) for x in planCategories]
self.webhooks.update(session=session, **webhooks)
return
def dict(self):
data = {"name": self.name, "webhooks": self.webhooks.dict()}
data = {
"name": self.name,
"planCategories": [cat.to_str() for cat in self.planCategories],
"webhooks": self.webhooks.dict(),
}
return data
class MealCategory(SqlAlchemyBase):
__tablename__ = "meal_plan_categories"
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
parent_id = sa.Column(sa.Integer, sa.ForeignKey("site_settings.name"))
def __init__(self, name) -> None:
self.name = name
def to_str(self):
return self.name
class WebHookModel(SqlAlchemyBase, BaseMixins):
__tablename__ = "webhook_settings"
id = sa.Column(sa.Integer, primary_key=True)

View file

View file

@ -1,4 +1,4 @@
from typing import List
from typing import List, Optional
from pydantic.main import BaseModel
from services.recipe_services import Recipe
@ -8,7 +8,7 @@ class RecipeCategoryResponse(BaseModel):
id: int
name: str
slug: str
recipes: List[Recipe]
recipes: Optional[List[Recipe]]
class Config:
schema_extra = {"example": {"id": 1, "name": "dinner", "recipes": [{}]}}

View file

@ -3,6 +3,7 @@ from typing import List, Optional
from pydantic import BaseModel
class Webhooks(BaseModel):
webhookTime: str = "00:00"
webhookURLs: Optional[List[str]] = []
@ -11,12 +12,14 @@ class Webhooks(BaseModel):
class SiteSettings(BaseModel):
name: str = "main"
planCategories: list[str] = []
webhooks: Webhooks
class Config:
schema_extra = {
"example": {
"name": "main",
"planCategories": ["dinner", "lunch"],
"webhooks": {
"webhookTime": "00:00",
"webhookURLs": ["https://mywebhookurl.com/webhook"],

View file

@ -69,3 +69,15 @@ def get_all_recipes_post(
"""
return db.recipes.get_all_limit_columns(session, body.properties, body.limit)
@router.post("/api/category")
async def filter_by_category(
categories: list, session: Session = Depends(generate_session)
):
""" pass a list of categories and get a list of recipes associated with those categories """
#! This should be refactored into a single database call, but I couldn't figure it out
in_category = [db.categories.get(session, cat) for cat in categories]
in_category = [cat.get("recipes") for cat in in_category]
in_category = [item for sublist in in_category for item in sublist]
return in_category

View file

@ -3,7 +3,6 @@ from db.db_setup import generate_session
from fastapi import APIRouter, Depends
from models.category_models import RecipeCategoryResponse
from sqlalchemy.orm.session import Session
from utils.snackbar import SnackResponse
router = APIRouter(
@ -26,6 +25,7 @@ def get_all_recipes_by_category(
return db.categories.get(session, category)
@router.delete("/{category}")
async def delete_recipe_category(
category: str, session: Session = Depends(generate_session)

View file

@ -19,13 +19,14 @@ def get_main_settings(session: Session = Depends(generate_session)):
except:
default_settings_init(session)
data = db.settings.get(session, "main")
print(data)
return data
@router.put("")
def update_settings(data: SiteSettings, session: Session = Depends(generate_session)):
""" Returns Site Settings """
print("Categories", data.planCategories)
db.settings.update(session, "main", data.dict())
return SnackResponse.success("Settings Updated")

View file

@ -3,6 +3,7 @@ from pathlib import Path
import requests
from app_config import IMG_DIR
from utils.logger import logger
def read_image(recipe_slug: str) -> Path:
@ -48,6 +49,7 @@ def scrape_image(image_url: str, slug: str) -> Path:
try:
r = requests.get(image_url, stream=True)
except:
logger.exception("Fatal Image Request Exception")
return None
if r.status_code == 200:

View file

@ -1,5 +1,4 @@
from datetime import date, timedelta
from pathlib import Path
from typing import List, Optional
from db.database import db

View file

@ -1,7 +1,8 @@
from db.database import db
from db.db_setup import create_session, sql_exists
from db.db_setup import create_session
from models.settings_models import SiteSettings, Webhooks
from sqlalchemy.orm.session import Session
from utils.logger import logger
def default_settings_init(session: Session = None):
@ -10,7 +11,7 @@ def default_settings_init(session: Session = None):
try:
webhooks = Webhooks()
default_entry = SiteSettings(name="main", webhooks=webhooks)
document = db.settings.create(session, default_entry.dict(), webhooks.dict())
document = db.settings.create(session, default_entry.dict())
logger.info(f"Created Site Settings: \n {document}")
except:
pass