diff --git a/cauldron/server.py b/cauldron/server.py index b0b274d..d0ea1c2 100644 --- a/cauldron/server.py +++ b/cauldron/server.py @@ -482,8 +482,20 @@ def create_app() -> Flask: recipe = client.get_recipe(slug) except Exception as e: return jsonify({"error": str(e)}), 502 - recipe["picked"] = slug in db.list_household_pick_slugs(current_household_id() or 0) if current_household_id() else False - return jsonify({"recipe": recipe, "public_url": cfg.mealie_public_url}) + hid = current_household_id() + recipe["picked"] = slug in db.list_household_pick_slugs(hid) if hid else False + # Mealie's web URL: /g//r/ + group_slug = _user_group_slug(client) + mealie_url = ( + f"{cfg.mealie_public_url}/g/{group_slug}/r/{slug}" + if group_slug + else f"{cfg.mealie_public_url}/recipe/{slug}" + ) + return jsonify({ + "recipe": recipe, + "public_url": cfg.mealie_public_url, + "mealie_url": mealie_url, + }) @app.get("/recipes/") @require_session @@ -497,10 +509,16 @@ def create_app() -> Flask: except Exception as e: return (f"recipe load failed: {e}", 502) picked = slug in db.list_meal_pick_slugs(u["sub"]) + group_slug = _user_group_slug(client) + mealie_url = ( + f"{cfg.mealie_public_url}/g/{group_slug}/r/{slug}" + if group_slug else f"{cfg.mealie_public_url}/recipe/{slug}" + ) return render_template( "recipe_detail.html", recipe=recipe, public_url=cfg.mealie_public_url, + mealie_url=mealie_url, picked=picked, active="recipes", ) @@ -534,6 +552,22 @@ def create_app() -> Flask: return app +def _user_group_slug(client) -> str | None: + """Mealie's recipe permalink lives at /g//r/. Pull + the group slug from /api/users/self. Cheap call (Mealie is on the + same docker bridge); could cache in session if it becomes hot.""" + try: + me = client.who_am_i() + except Exception: + return None + g = me.get("group") + if isinstance(g, dict): + return g.get("slug") or g.get("name") + if isinstance(g, str) and g: + return g + return me.get("groupSlug") or me.get("group_slug") or me.get("groupName") + + def _sort_to_order(sort: str) -> tuple[str, str]: """Map our sort keys to Mealie's orderBy + direction.""" return { diff --git a/cauldron/templates/_base.html b/cauldron/templates/_base.html index 5c75e6e..f73b624 100644 --- a/cauldron/templates/_base.html +++ b/cauldron/templates/_base.html @@ -539,13 +539,13 @@ button { font-family: inherit; } const r = await fetch('/api/recipes/' + encodeURIComponent(slug) + '.json'); if (!r.ok) throw new Error(r.status); const data = await r.json(); - renderRecipe(data.recipe, data.public_url); + renderRecipe(data.recipe, data.mealie_url); } catch (e) { bodyEl.innerHTML = '

load failed.

'; } } - function renderRecipe(r, publicUrl) { + function renderRecipe(r, mealieUrl) { titleEl.textContent = r.name || '(untitled)'; const meta = []; if (r.totalTime) meta.push('' + escapeHtml(r.totalTime) + ''); @@ -584,7 +584,7 @@ button { font-family: inherit; } data-slug="${escapeHtml(r.slug)}" data-name="${escapeHtml(r.name||'')}"> ๐Ÿ„ ${isPicked ? 'pinned ยท unpin' : 'pin to plan'} - in mealie โ†— + in mealie โ†— `; } diff --git a/cauldron/templates/recipe_detail.html b/cauldron/templates/recipe_detail.html index 626e2c8..5b3c1a3 100644 --- a/cauldron/templates/recipe_detail.html +++ b/cauldron/templates/recipe_detail.html @@ -61,7 +61,7 @@ onclick="togglePick(this)"> ๐Ÿ„ {% if picked %}pinned ยท remove{% else %}pin for ai plan{% endif %} - view in mealie โ†— + view in mealie โ†—