+
-
-
+
+
{{ title.toUpperCase() }}
@@ -15,15 +15,21 @@
- {{$t('general.sort')}}
+ {{
+ $t("general.sort")
+ }}
- {{$t('general.recent')}}
+ {{
+ $t("general.recent")
+ }}
- {{$t('general.sort-alphabetically')}}
+ {{
+ $t("general.sort-alphabetically")
+ }}
@@ -31,44 +37,45 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -84,12 +91,19 @@ export default {
sortable: {
default: false,
},
- title: String,
+ title: {
+ default: null
+ },
recipes: Array,
cardLimit: {
- default: 6,
+ default: 999,
},
},
+ watch: {
+ recipes(val) {
+ console.log(val)
+ }
+ },
computed: {
viewScale() {
switch (this.$vuetify.breakpoint.name) {
diff --git a/frontend/src/pages/Admin/Settings/index.vue b/frontend/src/pages/Admin/Settings/index.vue
index 13d2bc18f..2a7920d44 100644
--- a/frontend/src/pages/Admin/Settings/index.vue
+++ b/frontend/src/pages/Admin/Settings/index.vue
@@ -14,15 +14,19 @@
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/routes/index.js b/frontend/src/routes/index.js
index df94b1512..01eb86780 100644
--- a/frontend/src/routes/index.js
+++ b/frontend/src/routes/index.js
@@ -3,6 +3,7 @@ import Page404 from "@/pages/404Page";
import SearchPage from "@/pages/SearchPage";
import ViewRecipe from "@/pages/Recipe/ViewRecipe";
import NewRecipe from "@/pages/Recipe/NewRecipe";
+import CustomPage from "@/pages/Recipes/CustomPage";
import AllRecipes from "@/pages/Recipes/AllRecipes";
import CategoryPage from "@/pages/Recipes/CategoryPage";
import Planner from "@/pages/MealPlan/Planner";
@@ -31,6 +32,7 @@ export const routes = [
{ path: "/debug", component: Debug },
{ path: "/search", component: SearchPage },
{ path: "/recipes/all", component: AllRecipes },
+ { path: "/recipes/test-page", component: CustomPage },
{ path: "/recipes/:category", component: CategoryPage },
{ path: "/recipe/:recipe", component: ViewRecipe },
{ path: "/new/", component: NewRecipe },
diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js
index b6bbc277c..a538bed6e 100644
--- a/frontend/src/store/index.js
+++ b/frontend/src/store/index.js
@@ -4,7 +4,6 @@ import api from "@/api";
import createPersistedState from "vuex-persistedstate";
import userSettings from "./modules/userSettings";
import language from "./modules/language";
-import homePage from "./modules/homePage";
import siteSettings from "./modules/siteSettings";
import groups from "./modules/groups";
@@ -13,13 +12,12 @@ Vue.use(Vuex);
const store = new Vuex.Store({
plugins: [
createPersistedState({
- paths: ["userSettings", "language", "homePage", "SideSettings"],
+ paths: ["userSettings", "language", "SideSettings"],
}),
],
modules: {
userSettings,
language,
- homePage,
siteSettings,
groups,
},
diff --git a/frontend/src/store/modules/siteSettings.js b/frontend/src/store/modules/siteSettings.js
index d8357fa9b..1495b4c72 100644
--- a/frontend/src/store/modules/siteSettings.js
+++ b/frontend/src/store/modules/siteSettings.js
@@ -11,7 +11,7 @@ const state = {
const mutations = {
setSettings(state, payload) {
- state.settings = payload;
+ state.siteSettings = payload;
},
};
diff --git a/mealie/app.py b/mealie/app.py
index f4faeafd1..89ee63842 100644
--- a/mealie/app.py
+++ b/mealie/app.py
@@ -4,7 +4,8 @@ from fastapi.logger import logger
# import utils.startup as startup
from mealie.core.config import APP_VERSION, PORT, docs_url, redoc_url
-from mealie.routes import backup_routes, debug_routes, migration_routes, setting_routes, theme_routes
+from mealie.routes import backup_routes, debug_routes, migration_routes, theme_routes
+from mealie.routes.site_settings import all_settings
from mealie.routes.groups import groups
from mealie.routes.mealplans import mealplans
from mealie.routes.recipe import all_recipe_routes, category_routes, recipe_crud_routes, tag_routes
@@ -36,7 +37,7 @@ def api_routers():
# Meal Routes
app.include_router(mealplans.router)
# Settings Routes
- app.include_router(setting_routes.router)
+ app.include_router(all_settings.router)
app.include_router(theme_routes.router)
# Backups/Imports Routes
app.include_router(backup_routes.router)
diff --git a/mealie/db/database.py b/mealie/db/database.py
index a519ed309..5a1a66343 100644
--- a/mealie/db/database.py
+++ b/mealie/db/database.py
@@ -2,14 +2,14 @@ from mealie.db.db_base import BaseDocument
from mealie.db.models.group import Group
from mealie.db.models.mealplan import MealPlanModel
from mealie.db.models.recipe.recipe import Category, RecipeModel, Tag
-from mealie.db.models.settings import SiteSettings
+from mealie.db.models.settings import CustomPage, SiteSettings
from mealie.db.models.sign_up import SignUp
from mealie.db.models.theme import SiteThemeModel
from mealie.db.models.users import User
from mealie.schema.category import RecipeCategoryResponse, RecipeTagResponse
from mealie.schema.meal import MealPlanInDB
from mealie.schema.recipe import Recipe
-from mealie.schema.settings import SiteSettings as SiteSettingsSchema
+from mealie.schema.settings import CustomPageOut, SiteSettings as SiteSettingsSchema
from mealie.schema.sign_up import SignUpOut
from mealie.schema.theme import SiteTheme
from mealie.schema.user import GroupInDB, UserInDB
@@ -118,6 +118,13 @@ class _SignUps(BaseDocument):
self.orm_mode = True
self.schema = SignUpOut
+class _CustomPages(BaseDocument):
+ def __init__(self) -> None:
+ self.primary_key = "id"
+ self.sql_model = CustomPage
+ self.orm_mode = True
+ self.schema = CustomPageOut
+
class Database:
def __init__(self) -> None:
@@ -130,6 +137,7 @@ class Database:
self.users = _Users()
self.sign_ups = _SignUps()
self.groups = _Groups()
+ self.custom_pages = _CustomPages()
db = Database()
diff --git a/mealie/db/models/recipe/category.py b/mealie/db/models/recipe/category.py
index e954bc02b..a4ee7b0b3 100644
--- a/mealie/db/models/recipe/category.py
+++ b/mealie/db/models/recipe/category.py
@@ -26,6 +26,13 @@ recipes2categories = sa.Table(
sa.Column("category_slug", sa.String, sa.ForeignKey("categories.slug")),
)
+custom_pages2categories = sa.Table(
+ "custom_pages2categories",
+ SqlAlchemyBase.metadata,
+ sa.Column("custom_page_id", sa.Integer, sa.ForeignKey("custom_pages.id")),
+ sa.Column("category_slug", sa.String, sa.ForeignKey("categories.slug")),
+)
+
class Category(SqlAlchemyBase):
__tablename__ = "categories"
@@ -36,7 +43,7 @@ class Category(SqlAlchemyBase):
@validates("name")
def validate_name(self, key, name):
- assert not name == ""
+ assert name != ""
return name
def __init__(self, name) -> None:
diff --git a/mealie/db/models/settings.py b/mealie/db/models/settings.py
index b26e80ed1..1f64745ca 100644
--- a/mealie/db/models/settings.py
+++ b/mealie/db/models/settings.py
@@ -1,7 +1,7 @@
import sqlalchemy as sa
import sqlalchemy.orm as orm
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
-from mealie.db.models.recipe.category import Category, site_settings2categories
+from mealie.db.models.recipe.category import Category, custom_pages2categories, site_settings2categories
from sqlalchemy.orm import Session
@@ -29,7 +29,29 @@ class SiteSettings(SqlAlchemyBase, BaseMixins):
self.language = language
self.cards_per_section = cards_per_section
self.show_recent = show_recent
- self.categories = [Category.get_ref(session=session, name=cat.get("slug")) for cat in categories]
+ self.categories = [Category.get_ref(session=session, slug=cat.get("slug")) for cat in categories]
+
+ def update(self, *args, **kwarg):
+ self.__init__(*args, **kwarg)
+
+
+class CustomPage(SqlAlchemyBase, BaseMixins):
+ __tablename__ = "custom_pages"
+ id = sa.Column(sa.Integer, primary_key=True)
+ position = sa.Column(sa.Integer, nullable=False)
+ name = sa.Column(sa.String, nullable=False)
+ slug = sa.Column(sa.String, nullable=False)
+ categories = orm.relationship(
+ "Category",
+ secondary=custom_pages2categories,
+ single_parent=True,
+ )
+
+ def __init__(self, session=None, name=None, slug=None, position=0, categories=[]) -> None:
+ self.name = name
+ self.slug = slug
+ self.position = position
+ self.categories = [Category.get_ref(session=session, slug=cat.get("slug")) for cat in categories]
def update(self, *args, **kwarg):
self.__init__(*args, **kwarg)
diff --git a/mealie/routes/users/__init__ copy.py b/mealie/routes/site_settings/__init__.py
similarity index 100%
rename from mealie/routes/users/__init__ copy.py
rename to mealie/routes/site_settings/__init__.py
diff --git a/mealie/routes/site_settings/all_settings.py b/mealie/routes/site_settings/all_settings.py
new file mode 100644
index 000000000..09da2eda2
--- /dev/null
+++ b/mealie/routes/site_settings/all_settings.py
@@ -0,0 +1,7 @@
+from fastapi import APIRouter
+from mealie.routes.site_settings import custom_pages, site_settings
+
+router = APIRouter()
+
+router.include_router(custom_pages.router)
+router.include_router(site_settings.router)
diff --git a/mealie/routes/site_settings/custom_pages.py b/mealie/routes/site_settings/custom_pages.py
new file mode 100644
index 000000000..4c91779c1
--- /dev/null
+++ b/mealie/routes/site_settings/custom_pages.py
@@ -0,0 +1,52 @@
+from fastapi import APIRouter, Depends
+from mealie.db.database import db
+from mealie.db.db_setup import generate_session
+from mealie.routes.deps import get_current_user
+from mealie.schema.settings import CustomPageBase
+from mealie.schema.snackbar import SnackResponse
+from mealie.schema.user import UserInDB
+from sqlalchemy.orm.session import Session
+
+router = APIRouter(prefix="/api/site-settings/custom-pages", tags=["Settings"])
+
+
+@router.get("")
+def get_custom_pages(session: Session = Depends(generate_session)):
+ """ Returns the sites custom pages """
+
+ return db.custom_pages.get_all(session)
+
+
+@router.post("")
+async def create_new_page(
+ new_page: CustomPageBase,
+ session: Session = Depends(generate_session),
+ current_user: UserInDB = Depends(get_current_user),
+):
+ """ Creates a new Custom Page """
+
+ db.custom_pages.create(session, new_page.dict())
+
+ return SnackResponse.success("New Page Created")
+
+
+@router.get("/{id}")
+async def delete_custom_page(
+ id: int,
+ session: Session = Depends(generate_session),
+):
+ """ Removes a custom page from the database """
+
+ return db.custom_pages.get(session, id)
+
+
+@router.delete("/{id}")
+async def delete_custom_page(
+ id: int,
+ session: Session = Depends(generate_session),
+ current_user: UserInDB = Depends(get_current_user),
+):
+ """ Removes a custom page from the database """
+
+ db.custom_pages.delete(session, id)
+ return
diff --git a/mealie/routes/setting_routes.py b/mealie/routes/site_settings/site_settings.py
similarity index 95%
rename from mealie/routes/setting_routes.py
rename to mealie/routes/site_settings/site_settings.py
index 81cd18d46..4f7bf9772 100644
--- a/mealie/routes/setting_routes.py
+++ b/mealie/routes/site_settings/site_settings.py
@@ -16,9 +16,7 @@ router = APIRouter(prefix="/api/site-settings", tags=["Settings"])
def get_main_settings(session: Session = Depends(generate_session)):
""" Returns basic site settings """
- data = db.settings.get(session, 1)
-
- return data
+ return db.settings.get(session, 1)
@router.put("")
diff --git a/mealie/schema/recipe.py b/mealie/schema/recipe.py
index ad343be18..54a83d534 100644
--- a/mealie/schema/recipe.py
+++ b/mealie/schema/recipe.py
@@ -101,11 +101,10 @@ class Recipe(BaseModel):
name: str = values["name"]
calc_slug: str = slugify(name)
- if slug == calc_slug:
- return slug
- else:
+ if slug != calc_slug:
slug = calc_slug
- return slug
+
+ return slug
class AllRecipeRequest(BaseModel):
diff --git a/mealie/schema/settings.py b/mealie/schema/settings.py
index 0e97aa8c9..9f147d16a 100644
--- a/mealie/schema/settings.py
+++ b/mealie/schema/settings.py
@@ -1,8 +1,9 @@
from typing import Optional
from fastapi_camelcase import CamelModel
-
from mealie.schema.category import CategoryBase
+from pydantic import validator
+from slugify import slugify
class SiteSettings(CamelModel):
@@ -25,3 +26,30 @@ class SiteSettings(CamelModel):
],
}
}
+
+
+class CustomPageBase(CamelModel):
+ name: str
+ slug: Optional[str]
+ position: int
+ categories: list[CategoryBase] = []
+
+ class Config:
+ orm_mode = True
+
+ @validator("slug", always=True, pre=True)
+ def validate_slug(slug: str, values):
+ name: str = values["name"]
+ calc_slug: str = slugify(name)
+
+ if slug != calc_slug:
+ slug = calc_slug
+
+ return slug
+
+
+class CustomPageOut(CustomPageBase):
+ id: int
+
+ class Config:
+ orm_mode = True