mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-23 15:19:41 +02:00
feat: Add summary to recipe instructions (#4410)
Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
This commit is contained in:
parent
99fec90288
commit
3dd61f7742
5 changed files with 59 additions and 10 deletions
|
@ -0,0 +1,34 @@
|
||||||
|
"""'Add summary to recipe instructions'
|
||||||
|
|
||||||
|
Revision ID: 3897397b4631
|
||||||
|
Revises: 86054b40fd06
|
||||||
|
Create Date: 2024-10-20 09:47:46.844436
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
import mealie.db.migration_types
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "3897397b4631"
|
||||||
|
down_revision: str | None = "86054b40fd06"
|
||||||
|
branch_labels: str | tuple[str, ...] | None = None
|
||||||
|
depends_on: str | tuple[str, ...] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table("recipe_instructions", schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column("summary", sa.String(), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table("recipe_instructions", schema=None) as batch_op:
|
||||||
|
batch_op.drop_column("summary")
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
|
@ -121,9 +121,22 @@
|
||||||
@click="toggleDisabled(index)"
|
@click="toggleDisabled(index)"
|
||||||
>
|
>
|
||||||
<v-card-title :class="{ 'pb-0': !isChecked(index) }">
|
<v-card-title :class="{ 'pb-0': !isChecked(index) }">
|
||||||
<span :class="isEditForm ? 'handle' : ''">
|
<v-text-field
|
||||||
<v-icon v-if="isEditForm" size="26" class="pb-1">{{ $globals.icons.arrowUpDown }}</v-icon>
|
v-if="isEditForm"
|
||||||
{{ $t("recipe.step-index", { step: index + 1 }) }}
|
v-model="step.summary"
|
||||||
|
class="headline handle"
|
||||||
|
hide-details
|
||||||
|
dense
|
||||||
|
solo
|
||||||
|
flat
|
||||||
|
:placeholder="$t('recipe.step-index', { step: index + 1 })"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<v-icon size="26">{{ $globals.icons.arrowUpDown }}</v-icon>
|
||||||
|
</template>
|
||||||
|
</v-text-field>
|
||||||
|
<span v-else>
|
||||||
|
{{ step.summary ? step.summary : $t("recipe.step-index", { step: index + 1 }) }}
|
||||||
</span>
|
</span>
|
||||||
<template v-if="isEditForm">
|
<template v-if="isEditForm">
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
|
@ -339,7 +352,7 @@ export default defineComponent({
|
||||||
// ===============================================================
|
// ===============================================================
|
||||||
// UI State Helpers
|
// UI State Helpers
|
||||||
|
|
||||||
function validateTitle(title: string | undefined) {
|
function hasSectionTitle(title: string | undefined) {
|
||||||
return !(title === null || title === "" || title === undefined);
|
return !(title === null || title === "" || title === undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +361,7 @@ export default defineComponent({
|
||||||
|
|
||||||
v.forEach((element: RecipeStep) => {
|
v.forEach((element: RecipeStep) => {
|
||||||
if (element.id !== undefined) {
|
if (element.id !== undefined) {
|
||||||
showTitleEditor.value[element.id] = validateTitle(element.title);
|
showTitleEditor.value[element.id] = hasSectionTitle(element.title);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -359,7 +372,7 @@ export default defineComponent({
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
props.value.forEach((element: RecipeStep) => {
|
props.value.forEach((element: RecipeStep) => {
|
||||||
if (element.id !== undefined) {
|
if (element.id !== undefined) {
|
||||||
showTitleEditor.value[element.id] = validateTitle(element.title);
|
showTitleEditor.value[element.id] = hasSectionTitle(element.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
// showCookMode.value = false;
|
// showCookMode.value = false;
|
||||||
|
@ -576,7 +589,7 @@ export default defineComponent({
|
||||||
const sectionSteps: number[] = [];
|
const sectionSteps: number[] = [];
|
||||||
|
|
||||||
for (let i = index; i < props.value.length; i++) {
|
for (let i = index; i < props.value.length; i++) {
|
||||||
if (!(i === index) && validateTitle(props.value[i].title)) {
|
if (!(i === index) && hasSectionTitle(props.value[i].title)) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
sectionSteps.push(i);
|
sectionSteps.push(i);
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
<h4 v-if="step.title" :key="`instruction-title-${stepIndex}`" class="instruction-title mb-2">
|
<h4 v-if="step.title" :key="`instruction-title-${stepIndex}`" class="instruction-title mb-2">
|
||||||
{{ step.title }}
|
{{ step.title }}
|
||||||
</h4>
|
</h4>
|
||||||
<h5>{{ $t("recipe.step-index", { step: stepIndex + instructionSection.stepOffset + 1 }) }}</h5>
|
<h5>{{ step.summary ? step.summary : $t("recipe.step-index", { step: stepIndex + instructionSection.stepOffset + 1 }) }}</h5>
|
||||||
<SafeMarkdown :source="step.text" class="recipe-step-body" />
|
<SafeMarkdown :source="step.text" class="recipe-step-body" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -23,8 +23,9 @@ class RecipeInstruction(SqlAlchemyBase):
|
||||||
recipe_id: Mapped[GUID | None] = mapped_column(GUID, ForeignKey("recipes.id"), index=True)
|
recipe_id: Mapped[GUID | None] = mapped_column(GUID, ForeignKey("recipes.id"), index=True)
|
||||||
position: Mapped[int | None] = mapped_column(Integer, index=True)
|
position: Mapped[int | None] = mapped_column(Integer, index=True)
|
||||||
type: Mapped[str | None] = mapped_column(String, default="")
|
type: Mapped[str | None] = mapped_column(String, default="")
|
||||||
title: Mapped[str | None] = mapped_column(String)
|
title: Mapped[str | None] = mapped_column(String) # This is the section title!!!
|
||||||
text: Mapped[str | None] = mapped_column(String, index=True)
|
text: Mapped[str | None] = mapped_column(String, index=True)
|
||||||
|
summary: Mapped[str | None] = mapped_column(String)
|
||||||
|
|
||||||
ingredient_references: Mapped[list[RecipeIngredientRefLink]] = orm.relationship(
|
ingredient_references: Mapped[list[RecipeIngredientRefLink]] = orm.relationship(
|
||||||
RecipeIngredientRefLink, cascade="all, delete-orphan"
|
RecipeIngredientRefLink, cascade="all, delete-orphan"
|
||||||
|
|
|
@ -16,7 +16,8 @@ class IngredientReferences(MealieModel):
|
||||||
|
|
||||||
class RecipeStep(MealieModel):
|
class RecipeStep(MealieModel):
|
||||||
id: UUID | None = Field(default_factory=uuid4)
|
id: UUID | None = Field(default_factory=uuid4)
|
||||||
title: str | None = ""
|
title: str | None = "" # This is the section title!!!
|
||||||
|
summary: str | None = ""
|
||||||
text: str
|
text: str
|
||||||
ingredient_references: list[IngredientReferences] = []
|
ingredient_references: list[IngredientReferences] = []
|
||||||
model_config = ConfigDict(from_attributes=True)
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue