fix: build mealie permalink as /g/<group>/r/<slug>, not /recipe/<slug>
Alice caught it. Mealie's web URL format is: https://mealie.example.com/g/example-household/r/dairy-free-bread-recipe Was emitting /recipe/<slug> which 404s. Added _user_group_slug() helper that pulls .group.slug from /api/users/self (handles dict-or-string-or-fallback shapes for cross-version compat), threads the proper URL through both: - /api/recipes/<slug>.json (used by the modal) - /recipes/<slug> server-rendered detail (used as fallback for direct links) Falls back to the old /recipe/<slug> path if we can't resolve a group slug (won't break, will just 404 in Mealie if that ever happens).
This commit is contained in:
parent
8212abbfc3
commit
f804d7880c
3 changed files with 40 additions and 6 deletions
|
|
@ -482,8 +482,20 @@ def create_app() -> Flask:
|
||||||
recipe = client.get_recipe(slug)
|
recipe = client.get_recipe(slug)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"error": str(e)}), 502
|
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
|
hid = current_household_id()
|
||||||
return jsonify({"recipe": recipe, "public_url": cfg.mealie_public_url})
|
recipe["picked"] = slug in db.list_household_pick_slugs(hid) if hid else False
|
||||||
|
# Mealie's web URL: <public>/g/<group-slug>/r/<recipe-slug>
|
||||||
|
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/<slug>")
|
@app.get("/recipes/<slug>")
|
||||||
@require_session
|
@require_session
|
||||||
|
|
@ -497,10 +509,16 @@ def create_app() -> Flask:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return (f"recipe load failed: {e}", 502)
|
return (f"recipe load failed: {e}", 502)
|
||||||
picked = slug in db.list_meal_pick_slugs(u["sub"])
|
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(
|
return render_template(
|
||||||
"recipe_detail.html",
|
"recipe_detail.html",
|
||||||
recipe=recipe,
|
recipe=recipe,
|
||||||
public_url=cfg.mealie_public_url,
|
public_url=cfg.mealie_public_url,
|
||||||
|
mealie_url=mealie_url,
|
||||||
picked=picked,
|
picked=picked,
|
||||||
active="recipes",
|
active="recipes",
|
||||||
)
|
)
|
||||||
|
|
@ -534,6 +552,22 @@ def create_app() -> Flask:
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
def _user_group_slug(client) -> str | None:
|
||||||
|
"""Mealie's recipe permalink lives at /g/<group-slug>/r/<slug>. 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]:
|
def _sort_to_order(sort: str) -> tuple[str, str]:
|
||||||
"""Map our sort keys to Mealie's orderBy + direction."""
|
"""Map our sort keys to Mealie's orderBy + direction."""
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -539,13 +539,13 @@ button { font-family: inherit; }
|
||||||
const r = await fetch('/api/recipes/' + encodeURIComponent(slug) + '.json');
|
const r = await fetch('/api/recipes/' + encodeURIComponent(slug) + '.json');
|
||||||
if (!r.ok) throw new Error(r.status);
|
if (!r.ok) throw new Error(r.status);
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
renderRecipe(data.recipe, data.public_url);
|
renderRecipe(data.recipe, data.mealie_url);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
bodyEl.innerHTML = '<p style="color: var(--crit);">load failed.</p>';
|
bodyEl.innerHTML = '<p style="color: var(--crit);">load failed.</p>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderRecipe(r, publicUrl) {
|
function renderRecipe(r, mealieUrl) {
|
||||||
titleEl.textContent = r.name || '(untitled)';
|
titleEl.textContent = r.name || '(untitled)';
|
||||||
const meta = [];
|
const meta = [];
|
||||||
if (r.totalTime) meta.push('<span class="m">' + escapeHtml(r.totalTime) + '</span>');
|
if (r.totalTime) meta.push('<span class="m">' + escapeHtml(r.totalTime) + '</span>');
|
||||||
|
|
@ -584,7 +584,7 @@ button { font-family: inherit; }
|
||||||
data-slug="${escapeHtml(r.slug)}" data-name="${escapeHtml(r.name||'')}">
|
data-slug="${escapeHtml(r.slug)}" data-name="${escapeHtml(r.name||'')}">
|
||||||
🍄 ${isPicked ? 'pinned · unpin' : 'pin to plan'}
|
🍄 ${isPicked ? 'pinned · unpin' : 'pin to plan'}
|
||||||
</button>
|
</button>
|
||||||
<a class="btn" href="${publicUrl}/recipe/${encodeURIComponent(r.slug)}" target="_blank" rel="noopener">in mealie ↗</a>
|
<a class="btn" href="${mealieUrl}" target="_blank" rel="noopener">in mealie ↗</a>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
onclick="togglePick(this)">
|
onclick="togglePick(this)">
|
||||||
🍄 {% if picked %}pinned · remove{% else %}pin for ai plan{% endif %}
|
🍄 {% if picked %}pinned · remove{% else %}pin for ai plan{% endif %}
|
||||||
</button>
|
</button>
|
||||||
<a class="btn" href="{{ public_url }}/recipe/{{ recipe.slug }}" target="_blank" rel="noopener">view in mealie ↗</a>
|
<a class="btn" href="{{ mealie_url }}" target="_blank" rel="noopener">view in mealie ↗</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue