mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-05 13:35:23 +02:00
feature: proper multi-tenant-support (#969)(WIP)
* update naming * refactor tests to use shared structure * shorten names * add tools test case * refactor to support multi-tenant * set group_id on creation * initial refactor for multitenant tags/cats * spelling * additional test case for same valued resources * fix recipe update tests * apply indexes to foreign keys * fix performance regressions * handle unknown exception * utility decorator for function debugging * migrate recipe_id to UUID * GUID for recipes * remove unused import * move image functions into package * move utilities to packages dir * update import * linter * image image and asset routes * update assets and images to use UUIDs * fix migration base * image asset test coverage * use ids for categories and tag crud functions * refactor recipe organizer test suite to reduce duplication * add uuid serlization utility * organizer base router * slug routes testing and fixes * fix postgres error * adopt UUIDs * move tags, categories, and tools under "organizers" umbrella * update composite label * generate ts types * fix import error * update frontend types * fix type errors * fix postgres errors * fix #978 * add null check for title validation * add note in docs on multi-tenancy
This commit is contained in:
parent
9a82a172cb
commit
c617251f4c
157 changed files with 1866 additions and 1578 deletions
|
@ -107,6 +107,7 @@
|
|||
<v-list-item-avatar :rounded="false">
|
||||
<RecipeCardImage
|
||||
v-if="mealplan.recipe"
|
||||
:recipe-id="mealplan.recipe.id"
|
||||
tiny
|
||||
icon-size="25"
|
||||
:slug="mealplan.recipe ? mealplan.recipe.slug : ''"
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
></RecipeCardSection>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "@nuxtjs/composition-api";
|
||||
import RecipeCardSection from "~/components/Domain/Recipe/RecipeCardSection.vue";
|
||||
import { useRecipes, recentRecipes } from "~/composables/recipes";
|
||||
|
@ -23,4 +23,3 @@ export default defineComponent({
|
|||
},
|
||||
});
|
||||
</script>
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
:max-width="enableLandscape ? null : '50%'"
|
||||
min-height="50"
|
||||
:height="hideImage ? undefined : imageHeight"
|
||||
:src="recipeImage(recipe.slug, imageKey)"
|
||||
:src="recipeImage(recipe.id, imageKey)"
|
||||
class="d-print-none"
|
||||
@error="hideImage = true"
|
||||
>
|
||||
|
@ -284,6 +284,7 @@
|
|||
v-model="recipe.assets"
|
||||
:edit="form"
|
||||
:slug="recipe.slug"
|
||||
:recipe-id="recipe.id"
|
||||
/>
|
||||
</client-only>
|
||||
</div>
|
||||
|
@ -362,6 +363,7 @@
|
|||
v-model="recipe.assets"
|
||||
:edit="form"
|
||||
:slug="recipe.slug"
|
||||
:recipe-id="recipe.id"
|
||||
/>
|
||||
</client-only>
|
||||
</div>
|
||||
|
@ -562,7 +564,6 @@ export default defineComponent({
|
|||
|
||||
const { recipeImage } = useStaticRoutes();
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// Layout Helpers
|
||||
|
||||
|
@ -691,9 +692,8 @@ export default defineComponent({
|
|||
// Recipe Tools
|
||||
|
||||
async function updateTool(tool: RecipeTool) {
|
||||
if (tool.id === undefined)
|
||||
return;
|
||||
|
||||
if (tool.id === undefined) return;
|
||||
|
||||
const { response } = await api.tools.updateOne(tool.id, tool);
|
||||
|
||||
if (response?.status === 200) {
|
||||
|
|
|
@ -72,7 +72,7 @@ export default defineComponent({
|
|||
});
|
||||
|
||||
const category = useAsync(async () => {
|
||||
const { data } = await api.categories.getOne(slug);
|
||||
const { data } = await api.categories.bySlug(slug);
|
||||
if (data) {
|
||||
state.initialValue = data.name;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ export default defineComponent({
|
|||
if (!category.value) {
|
||||
return;
|
||||
}
|
||||
const { data } = await api.categories.updateOne(category.value.slug, category.value);
|
||||
const { data } = await api.categories.updateOne(category.value.id, category.value);
|
||||
|
||||
if (data) {
|
||||
router.push("/recipes/categories/" + data.slug);
|
||||
|
|
|
@ -72,7 +72,7 @@ export default defineComponent({
|
|||
});
|
||||
|
||||
const tags = useAsync(async () => {
|
||||
const { data } = await api.tags.getOne(slug);
|
||||
const { data } = await api.tags.bySlug(slug);
|
||||
if (data) {
|
||||
state.initialValue = data.name;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ export default defineComponent({
|
|||
if (!tags.value) {
|
||||
return;
|
||||
}
|
||||
const { data } = await api.tags.updateOne(tags.value.slug, tags.value);
|
||||
const { data } = await api.tags.updateOne(tags.value.id, tags.value);
|
||||
|
||||
if (data) {
|
||||
router.push("/recipes/tags/" + data.slug);
|
||||
|
|
|
@ -66,7 +66,7 @@ export default defineComponent({
|
|||
});
|
||||
|
||||
const tools = useAsync(async () => {
|
||||
const { data } = await api.tools.byslug(slug);
|
||||
const { data } = await api.tools.bySlug(slug);
|
||||
if (data) {
|
||||
state.initialValue = data.name;
|
||||
}
|
||||
|
|
|
@ -115,8 +115,8 @@ import RecipeCategoryTagSelector from "~/components/Domain/Recipe/RecipeCategory
|
|||
import RecipeCardSection from "~/components/Domain/Recipe/RecipeCardSection.vue";
|
||||
import { useRecipes, allRecipes, useFoods } from "~/composables/recipes";
|
||||
import { RecipeSummary } from "~/types/api-types/recipe";
|
||||
import { Tag } from "~/api/class-interfaces/tags";
|
||||
import { useRouteQuery } from "~/composables/use-router";
|
||||
import { RecipeTag } from "~/types/api-types/user";
|
||||
|
||||
interface GenericFilter {
|
||||
exclude: boolean;
|
||||
|
@ -189,7 +189,7 @@ export default defineComponent({
|
|||
state.includeTags,
|
||||
|
||||
// @ts-ignore See above
|
||||
recipe.tags.map((x: Tag) => x.name),
|
||||
recipe.tags.map((x: RecipeTag) => x.name),
|
||||
state.tagFilter.matchAny,
|
||||
state.tagFilter.exclude
|
||||
);
|
||||
|
|
|
@ -324,7 +324,7 @@ export default defineComponent({
|
|||
if (data) {
|
||||
if (data && data !== undefined) {
|
||||
console.log("Computed Meta. RefKey=");
|
||||
const imageURL = data.slug ? recipeImage(data.slug) : undefined;
|
||||
const imageURL = data.id ? recipeImage(data.id) : undefined;
|
||||
title.value = data.name;
|
||||
|
||||
meta.value = [
|
||||
|
|
|
@ -411,7 +411,7 @@ export default defineComponent({
|
|||
return shoppingList.value?.recipeReferences?.map((ref) => ref.recipe) ?? [];
|
||||
});
|
||||
|
||||
async function addRecipeReferenceToList(recipeId: number) {
|
||||
async function addRecipeReferenceToList(recipeId: string) {
|
||||
if (!shoppingList.value) {
|
||||
return;
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
|
||||
async function removeRecipeReferenceToList(recipeId: number) {
|
||||
async function removeRecipeReferenceToList(recipeId: string) {
|
||||
if (!shoppingList.value) {
|
||||
return;
|
||||
}
|
||||
|
@ -577,4 +577,3 @@ export default defineComponent({
|
|||
max-width: 50px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue