diff --git a/docs/docs/overrides/api.html b/docs/docs/overrides/api.html index 0dc543851..526c3d3dc 100644 --- a/docs/docs/overrides/api.html +++ b/docs/docs/overrides/api.html @@ -14,7 +14,7 @@
diff --git a/frontend/components/Layout/DefaultLayout.vue b/frontend/components/Layout/DefaultLayout.vue index 86e74c2a1..7dce34bf0 100644 --- a/frontend/components/Layout/DefaultLayout.vue +++ b/frontend/components/Layout/DefaultLayout.vue @@ -100,9 +100,7 @@ import type { SideBarLink } from "~/types/application-types"; import { useAppInfo } from "~/composables/api"; import { useCookbookPreferences } from "~/composables/use-users/preferences"; import { useCookbookStore, usePublicCookbookStore } from "~/composables/store/use-cookbook-store"; -import { useHouseholdStore, usePublicHouseholdStore } from "~/composables/store/use-household-store"; import type { ReadCookBook } from "~/lib/api/types/cookbook"; -import type { HouseholdSummary } from "~/lib/api/types/household"; export default defineNuxtComponent({ setup() { @@ -116,12 +114,8 @@ export default defineNuxtComponent({ const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || ""); const cookbookPreferences = useCookbookPreferences(); - const ownCookbookStore = useCookbookStore(i18n); - const ownHouseholdStore = useHouseholdStore(i18n); - const publicCookbookStoreCache = ref>>({}); - const publicHouseholdStoreCache = ref>>({}); function getPublicCookbookStore(slug: string) { if (!publicCookbookStoreCache.value[slug]) { @@ -130,13 +124,6 @@ export default defineNuxtComponent({ return publicCookbookStoreCache.value[slug]; } - function getPublicHouseholdStore(slug: string) { - if (!publicHouseholdStoreCache.value[slug]) { - publicHouseholdStoreCache.value[slug] = usePublicHouseholdStore(slug, i18n); - } - return publicHouseholdStoreCache.value[slug]; - } - const cookbooks = computed(() => { if (isOwnGroup.value) { return ownCookbookStore.store.value; @@ -148,24 +135,6 @@ export default defineNuxtComponent({ return []; }); - const households = computed(() => { - if (isOwnGroup.value) { - return ownHouseholdStore.store.value; - } - else if (groupSlug.value) { - const publicStore = getPublicHouseholdStore(groupSlug.value); - return unref(publicStore.store); - } - return []; - }); - - const householdsById = computed(() => { - return households.value.reduce((acc, household) => { - acc[household.id] = household; - return acc; - }, {} as { [key: string]: HouseholdSummary }); - }); - const appInfo = useAppInfo(); const showImageImport = computed(() => appInfo.value?.enableOpenaiImageServices); @@ -197,11 +166,8 @@ export default defineNuxtComponent({ const ownLinks: SideBarLink[] = []; const links: SideBarLink[] = []; const cookbooksByHousehold = sortedCookbooks.reduce((acc, cookbook) => { - const householdName = householdsById.value[cookbook.householdId]?.name || ""; - if (!acc[householdName]) { - acc[householdName] = []; - } - acc[householdName].push(cookbook); + const householdName = cookbook.household?.name || ""; + (acc[householdName] ||= []).push(cookbook); return acc; }, {} as Record); diff --git a/frontend/lib/api/types/cookbook.ts b/frontend/lib/api/types/cookbook.ts index 753b11c6a..7104b774c 100644 --- a/frontend/lib/api/types/cookbook.ts +++ b/frontend/lib/api/types/cookbook.ts @@ -9,6 +9,10 @@ export type LogicalOperator = "AND" | "OR"; export type RelationalKeyword = "IS" | "IS NOT" | "IN" | "NOT IN" | "CONTAINS ALL" | "LIKE" | "NOT LIKE"; export type RelationalOperator = "=" | "<>" | ">" | "<" | ">=" | "<="; +export interface CookbookHousehold { + id: string; + name: string; +} export interface CreateCookBook { name: string; description?: string; @@ -28,6 +32,7 @@ export interface ReadCookBook { householdId: string; id: string; queryFilter?: QueryFilterJSON; + household?: CookbookHousehold | null; } export interface QueryFilterJSON { parts?: QueryFilterJSONPart[]; diff --git a/frontend/lib/api/types/openai.ts b/frontend/lib/api/types/openai.ts index be28b87be..10b506402 100644 --- a/frontend/lib/api/types/openai.ts +++ b/frontend/lib/api/types/openai.ts @@ -6,8 +6,6 @@ */ export interface OpenAIIngredient { - input: string; - confidence?: number | null; quantity?: number | null; unit?: string | null; food?: string | null; diff --git a/frontend/types/components.d.ts b/frontend/types/components.d.ts index 25d97d654..bcee9b06c 100644 --- a/frontend/types/components.d.ts +++ b/frontend/types/components.d.ts @@ -3,6 +3,7 @@ import type AdvancedOnly from "@/components/global/AdvancedOnly.vue"; import type AppButtonCopy from "@/components/global/AppButtonCopy.vue"; import type AppButtonUpload from "@/components/global/AppButtonUpload.vue"; import type AppLoader from "@/components/global/AppLoader.vue"; +import type AppLogo from "@/components/global/AppLogo.vue"; import type AppToolbar from "@/components/global/AppToolbar.vue"; import type AutoForm from "@/components/global/AutoForm.vue"; import type BannerExperimental from "@/components/global/BannerExperimental.vue"; @@ -43,6 +44,7 @@ declare module "vue" { AppButtonCopy: typeof AppButtonCopy; AppButtonUpload: typeof AppButtonUpload; AppLoader: typeof AppLoader; + AppLogo: typeof AppLogo; AppToolbar: typeof AppToolbar; AutoForm: typeof AutoForm; BannerExperimental: typeof BannerExperimental; @@ -79,4 +81,4 @@ declare module "vue" { } } -export { }; +export {}; diff --git a/mealie/schema/cookbook/__init__.py b/mealie/schema/cookbook/__init__.py index 8a358571a..65df16532 100644 --- a/mealie/schema/cookbook/__init__.py +++ b/mealie/schema/cookbook/__init__.py @@ -1,8 +1,9 @@ # This file is auto-generated by gen_schema_exports.py -from .cookbook import CookBookPagination, CreateCookBook, ReadCookBook, SaveCookBook, UpdateCookBook +from .cookbook import CookbookHousehold, CookBookPagination, CreateCookBook, ReadCookBook, SaveCookBook, UpdateCookBook __all__ = [ "CookBookPagination", + "CookbookHousehold", "CreateCookBook", "ReadCookBook", "SaveCookBook", diff --git a/mealie/schema/cookbook/cookbook.py b/mealie/schema/cookbook/cookbook.py index 66ba3b668..8d7761e3c 100644 --- a/mealie/schema/cookbook/cookbook.py +++ b/mealie/schema/cookbook/cookbook.py @@ -3,8 +3,11 @@ from typing import Annotated import sqlalchemy as sa from pydantic import UUID4, ConfigDict, Field, ValidationInfo, field_validator from slugify import slugify +from sqlalchemy.orm import joinedload +from sqlalchemy.orm.interfaces import LoaderOption from mealie.core.root_logger import get_logger +from mealie.db.models.household.cookbook import CookBook from mealie.db.models.recipe import RecipeModel from mealie.schema._mealie import MealieModel from mealie.schema.response.pagination import PaginationBase @@ -13,6 +16,12 @@ from mealie.schema.response.query_filter import QueryFilterBuilder, QueryFilterJ logger = get_logger() +class CookbookHousehold(MealieModel): + id: UUID4 + name: str + model_config = ConfigDict(from_attributes=True) + + class CreateCookBook(MealieModel): name: str description: str = "" @@ -62,6 +71,7 @@ class UpdateCookBook(SaveCookBook): class ReadCookBook(UpdateCookBook): query_filter: Annotated[QueryFilterJSON, Field(validate_default=True)] = None # type: ignore + household: CookbookHousehold | None = None model_config = ConfigDict(from_attributes=True) @@ -80,6 +90,10 @@ class ReadCookBook(UpdateCookBook): logger.exception(f"Invalid query filter string: {query_filter_string}") return QueryFilterJSON() + @classmethod + def loader_options(cls) -> list[LoaderOption]: + return [joinedload(CookBook.household)] + class CookBookPagination(PaginationBase): items: list[ReadCookBook] diff --git a/tests/integration_tests/public_explorer_tests/test_public_cookbooks.py b/tests/integration_tests/public_explorer_tests/test_public_cookbooks.py index c3902a6d4..7fba33316 100644 --- a/tests/integration_tests/public_explorer_tests/test_public_cookbooks.py +++ b/tests/integration_tests/public_explorer_tests/test_public_cookbooks.py @@ -139,6 +139,7 @@ def test_get_one_cookbook( assert response.status_code == 200 cookbook_data = response.json() assert cookbook_data["id"] == str(cookbook.id) + assert cookbook_data["household"]["name"] == household.name def test_get_cookbooks_with_recipes(api_client: TestClient, unique_user: TestUser, h2_user: TestUser): diff --git a/tests/integration_tests/user_household_tests/test_group_cookbooks.py b/tests/integration_tests/user_household_tests/test_group_cookbooks.py index 90dbc2fa8..5807d0b1e 100644 --- a/tests/integration_tests/user_household_tests/test_group_cookbooks.py +++ b/tests/integration_tests/user_household_tests/test_group_cookbooks.py @@ -89,6 +89,9 @@ def test_read_cookbook( use_other_household: bool, ): sample = random.choice(cookbooks) + household = unique_user.repos.households.get_one(sample.data["household_id"]) + assert household + if use_other_household: headers = h2_user.token else: @@ -104,6 +107,8 @@ def test_read_cookbook( assert page_data["slug"] == sample.slug assert page_data["name"] == sample.name assert page_data["groupId"] == str(unique_user.group_id) + assert page_data["householdId"] == str(unique_user.household_id) + assert page_data["household"]["name"] == household.name def test_update_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):