fix: enable nested base recipe references to display correctly
All checks were successful
CI / update (push) Successful in 1m10s
All checks were successful
CI / update (push) Successful in 1m10s
- Add recursive population for nested base recipe references (up to 3 levels deep) in API endpoints - Implement recursive mapping of baseRecipeRef to resolvedRecipe for all nesting levels - Add recursive flattening functions in frontend components to handle nested references - Fix TranslationApproval to use short_name instead of ObjectId for base recipe lookups - Add circular reference detection to prevent infinite loops This ensures that when Recipe A references Recipe B as a base, and Recipe B references Recipe C, all three recipes' content is properly displayed.
This commit is contained in:
@@ -17,11 +17,27 @@ export const GET: RequestHandler = async ({ params }) => {
|
||||
})
|
||||
.populate({
|
||||
path: 'translations.en.ingredients.baseRecipeRef',
|
||||
select: 'short_name name ingredients instructions translations'
|
||||
select: 'short_name name ingredients instructions translations',
|
||||
populate: {
|
||||
path: 'ingredients.baseRecipeRef',
|
||||
select: 'short_name name ingredients instructions translations',
|
||||
populate: {
|
||||
path: 'ingredients.baseRecipeRef',
|
||||
select: 'short_name name ingredients instructions translations'
|
||||
}
|
||||
}
|
||||
})
|
||||
.populate({
|
||||
path: 'translations.en.instructions.baseRecipeRef',
|
||||
select: 'short_name name ingredients instructions translations'
|
||||
select: 'short_name name ingredients instructions translations',
|
||||
populate: {
|
||||
path: 'instructions.baseRecipeRef',
|
||||
select: 'short_name name ingredients instructions translations',
|
||||
populate: {
|
||||
path: 'instructions.baseRecipeRef',
|
||||
select: 'short_name name ingredients instructions translations'
|
||||
}
|
||||
}
|
||||
})
|
||||
.lean();
|
||||
|
||||
@@ -64,23 +80,32 @@ export const GET: RequestHandler = async ({ params }) => {
|
||||
germanShortName: recipe.short_name,
|
||||
};
|
||||
|
||||
// Map populated base recipe refs to resolvedRecipe field
|
||||
if (englishRecipe.ingredients) {
|
||||
englishRecipe.ingredients = englishRecipe.ingredients.map((item: any) => {
|
||||
// Recursively map populated base recipe refs to resolvedRecipe field
|
||||
function mapBaseRecipeRefs(items: any[]): any[] {
|
||||
return items.map((item: any) => {
|
||||
if (item.type === 'reference' && item.baseRecipeRef) {
|
||||
return { ...item, resolvedRecipe: item.baseRecipeRef };
|
||||
const resolvedRecipe = { ...item.baseRecipeRef };
|
||||
|
||||
// Recursively map nested baseRecipeRefs
|
||||
if (resolvedRecipe.ingredients) {
|
||||
resolvedRecipe.ingredients = mapBaseRecipeRefs(resolvedRecipe.ingredients);
|
||||
}
|
||||
if (resolvedRecipe.instructions) {
|
||||
resolvedRecipe.instructions = mapBaseRecipeRefs(resolvedRecipe.instructions);
|
||||
}
|
||||
|
||||
return { ...item, resolvedRecipe };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
if (englishRecipe.ingredients) {
|
||||
englishRecipe.ingredients = mapBaseRecipeRefs(englishRecipe.ingredients);
|
||||
}
|
||||
|
||||
if (englishRecipe.instructions) {
|
||||
englishRecipe.instructions = englishRecipe.instructions.map((item: any) => {
|
||||
if (item.type === 'reference' && item.baseRecipeRef) {
|
||||
return { ...item, resolvedRecipe: item.baseRecipeRef };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
englishRecipe.instructions = mapBaseRecipeRefs(englishRecipe.instructions);
|
||||
}
|
||||
|
||||
// Merge English alt/caption with original image paths
|
||||
|
||||
@@ -9,11 +9,27 @@ export const GET: RequestHandler = async ({params}) => {
|
||||
let recipe = await Recipe.findOne({ short_name: params.name})
|
||||
.populate({
|
||||
path: 'ingredients.baseRecipeRef',
|
||||
select: 'short_name name ingredients translations'
|
||||
select: 'short_name name ingredients translations',
|
||||
populate: {
|
||||
path: 'ingredients.baseRecipeRef',
|
||||
select: 'short_name name ingredients translations',
|
||||
populate: {
|
||||
path: 'ingredients.baseRecipeRef',
|
||||
select: 'short_name name ingredients translations'
|
||||
}
|
||||
}
|
||||
})
|
||||
.populate({
|
||||
path: 'instructions.baseRecipeRef',
|
||||
select: 'short_name name instructions translations'
|
||||
select: 'short_name name instructions translations',
|
||||
populate: {
|
||||
path: 'instructions.baseRecipeRef',
|
||||
select: 'short_name name instructions translations',
|
||||
populate: {
|
||||
path: 'instructions.baseRecipeRef',
|
||||
select: 'short_name name instructions translations'
|
||||
}
|
||||
}
|
||||
})
|
||||
.lean() as RecipeModelType[];
|
||||
|
||||
@@ -22,23 +38,32 @@ export const GET: RequestHandler = async ({params}) => {
|
||||
throw error(404, "Recipe not found")
|
||||
}
|
||||
|
||||
// Map populated refs to resolvedRecipe field
|
||||
if (recipe?.ingredients) {
|
||||
recipe.ingredients = recipe.ingredients.map((item: any) => {
|
||||
// Recursively map populated refs to resolvedRecipe field
|
||||
function mapBaseRecipeRefs(items: any[]): any[] {
|
||||
return items.map((item: any) => {
|
||||
if (item.type === 'reference' && item.baseRecipeRef) {
|
||||
return { ...item, resolvedRecipe: item.baseRecipeRef };
|
||||
const resolvedRecipe = { ...item.baseRecipeRef };
|
||||
|
||||
// Recursively map nested baseRecipeRefs
|
||||
if (resolvedRecipe.ingredients) {
|
||||
resolvedRecipe.ingredients = mapBaseRecipeRefs(resolvedRecipe.ingredients);
|
||||
}
|
||||
if (resolvedRecipe.instructions) {
|
||||
resolvedRecipe.instructions = mapBaseRecipeRefs(resolvedRecipe.instructions);
|
||||
}
|
||||
|
||||
return { ...item, resolvedRecipe };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
if (recipe?.ingredients) {
|
||||
recipe.ingredients = mapBaseRecipeRefs(recipe.ingredients);
|
||||
}
|
||||
|
||||
if (recipe?.instructions) {
|
||||
recipe.instructions = recipe.instructions.map((item: any) => {
|
||||
if (item.type === 'reference' && item.baseRecipeRef) {
|
||||
return { ...item, resolvedRecipe: item.baseRecipeRef };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
recipe.instructions = mapBaseRecipeRefs(recipe.instructions);
|
||||
}
|
||||
|
||||
return json(recipe);
|
||||
|
||||
Reference in New Issue
Block a user